Changeset View
Changeset View
Standalone View
Standalone View
src/applications/repository/storage/PhabricatorRepository.php
Show First 20 Lines • Show All 1,643 Lines • ▼ Show 20 Lines | public function writeStatusMessage( | ||||
if ($status_code === null) { | if ($status_code === null) { | ||||
queryfx( | queryfx( | ||||
$conn_w, | $conn_w, | ||||
'DELETE FROM %T WHERE repositoryID = %d AND statusType = %s', | 'DELETE FROM %T WHERE repositoryID = %d AND statusType = %s', | ||||
$table_name, | $table_name, | ||||
$this->getID(), | $this->getID(), | ||||
$status_type); | $status_type); | ||||
} else { | } else { | ||||
// If the existing message has the same code (e.g., we just hit an | |||||
// error and also previously hit an error) we increment the message | |||||
// count by 1. This allows us to determine how many times in a row | |||||
// we've run into an error. | |||||
queryfx( | queryfx( | ||||
$conn_w, | $conn_w, | ||||
'INSERT INTO %T | 'INSERT INTO %T | ||||
(repositoryID, statusType, statusCode, parameters, epoch) | (repositoryID, statusType, statusCode, parameters, epoch, | ||||
VALUES (%d, %s, %s, %s, %d) | messageCount) | ||||
VALUES (%d, %s, %s, %s, %d, %d) | |||||
ON DUPLICATE KEY UPDATE | ON DUPLICATE KEY UPDATE | ||||
statusCode = VALUES(statusCode), | statusCode = VALUES(statusCode), | ||||
parameters = VALUES(parameters), | parameters = VALUES(parameters), | ||||
epoch = VALUES(epoch)', | epoch = VALUES(epoch), | ||||
messageCount = | |||||
IF( | |||||
statusCode = VALUES(statusCode), | |||||
messageCount + 1, | |||||
VALUES(messageCount))', | |||||
$table_name, | $table_name, | ||||
$this->getID(), | $this->getID(), | ||||
$status_type, | $status_type, | ||||
$status_code, | $status_code, | ||||
json_encode($parameters), | json_encode($parameters), | ||||
time()); | time(), | ||||
1); | |||||
} | } | ||||
return $this; | return $this; | ||||
} | } | ||||
public static function assertValidRemoteURI($uri) { | public static function assertValidRemoteURI($uri) { | ||||
if (trim($uri) != $uri) { | if (trim($uri) != $uri) { | ||||
throw new Exception( | throw new Exception( | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | /* -( Repository URI Management )------------------------------------------ */ | ||||
* spinning on repositories with a silly commit post-dated to some time in | * spinning on repositories with a silly commit post-dated to some time in | ||||
* 2037). We adjust the pull frequency based on when the most recent commit | * 2037). We adjust the pull frequency based on when the most recent commit | ||||
* occurred. | * occurred. | ||||
* | * | ||||
* @param int The minimum update interval to use, in seconds. | * @param int The minimum update interval to use, in seconds. | ||||
* @return int Repository update interval, in seconds. | * @return int Repository update interval, in seconds. | ||||
*/ | */ | ||||
public function loadUpdateInterval($minimum = 15) { | public function loadUpdateInterval($minimum = 15) { | ||||
// First, check if we've hit errors recently. If we have, wait one period | |||||
// for each consecutive error. Normally, this corresponds to a backoff of | |||||
// 15s, 30s, 45s, etc. | |||||
$message_table = new PhabricatorRepositoryStatusMessage(); | |||||
$conn = $message_table->establishConnection('r'); | |||||
$error_count = queryfx_one( | |||||
$conn, | |||||
'SELECT MAX(messageCount) error_count FROM %T | |||||
WHERE repositoryID = %d | |||||
AND statusType IN (%Ls) | |||||
AND statusCode IN (%Ls)', | |||||
$message_table->getTableName(), | |||||
$this->getID(), | |||||
array( | |||||
PhabricatorRepositoryStatusMessage::TYPE_INIT, | |||||
PhabricatorRepositoryStatusMessage::TYPE_FETCH, | |||||
), | |||||
array( | |||||
PhabricatorRepositoryStatusMessage::CODE_ERROR, | |||||
)); | |||||
$error_count = (int)$error_count['error_count']; | |||||
if ($error_count > 0) { | |||||
return (int)($minimum * $error_count); | |||||
} | |||||
// If a repository is still importing, always pull it as frequently as | // If a repository is still importing, always pull it as frequently as | ||||
// possible. This prevents us from hanging for a long time at 99.9% when | // possible. This prevents us from hanging for a long time at 99.9% when | ||||
// importing an inactive repository. | // importing an inactive repository. | ||||
if ($this->isImporting()) { | if ($this->isImporting()) { | ||||
return $minimum; | return $minimum; | ||||
} | } | ||||
$window_start = (PhabricatorTime::getNow() + $minimum); | $window_start = (PhabricatorTime::getNow() + $minimum); | ||||
$table = id(new PhabricatorRepositoryCommit()); | $table = id(new PhabricatorRepositoryCommit()); | ||||
$last_commit = queryfx_one( | $last_commit = queryfx_one( | ||||
$table->establishConnection('r'), | $table->establishConnection('r'), | ||||
'SELECT epoch FROM %T | 'SELECT epoch FROM %T | ||||
WHERE repositoryID = %d AND epoch <= %d | WHERE repositoryID = %d AND epoch <= %d | ||||
ORDER BY epoch DESC LIMIT 1', | ORDER BY epoch DESC LIMIT 1', | ||||
$table->getTableName(), | $table->getTableName(), | ||||
$this->getID(), | $this->getID(), | ||||
$window_start); | $window_start); | ||||
if ($last_commit) { | if ($last_commit) { | ||||
$time_since_commit = ($window_start - $last_commit['epoch']); | $time_since_commit = ($window_start - $last_commit['epoch']); | ||||
} else { | |||||
// If the repository has no commits, treat the creation date as | |||||
// though it were the date of the last commit. This makes empty | |||||
// repositories update quickly at first but slow down over time | |||||
// if they don't see any activity. | |||||
$time_since_commit = ($window_start - $this->getDateCreated()); | |||||
} | |||||
$last_few_days = phutil_units('3 days in seconds'); | $last_few_days = phutil_units('3 days in seconds'); | ||||
if ($time_since_commit <= $last_few_days) { | if ($time_since_commit <= $last_few_days) { | ||||
// For repositories with activity in the recent past, we wait one | // For repositories with activity in the recent past, we wait one | ||||
// extra second for every 10 minutes since the last commit. This | // extra second for every 10 minutes since the last commit. This | ||||
// shorter backoff is intended to handle weekends and other short | // shorter backoff is intended to handle weekends and other short | ||||
// breaks from development. | // breaks from development. | ||||
$smart_wait = ($time_since_commit / 600); | $smart_wait = ($time_since_commit / 600); | ||||
} else { | } else { | ||||
// For repositories without recent activity, we wait one extra second | // For repositories without recent activity, we wait one extra second | ||||
// for every 4 minutes since the last commit. This longer backoff | // for every 4 minutes since the last commit. This longer backoff | ||||
// handles rarely used repositories, up to the maximum. | // handles rarely used repositories, up to the maximum. | ||||
$smart_wait = ($time_since_commit / 240); | $smart_wait = ($time_since_commit / 240); | ||||
} | } | ||||
// We'll never wait more than 6 hours to pull a repository. | // We'll never wait more than 6 hours to pull a repository. | ||||
$longest_wait = phutil_units('6 hours in seconds'); | $longest_wait = phutil_units('6 hours in seconds'); | ||||
$smart_wait = min($smart_wait, $longest_wait); | $smart_wait = min($smart_wait, $longest_wait); | ||||
$smart_wait = max($minimum, $smart_wait); | $smart_wait = max($minimum, $smart_wait); | ||||
} else { | |||||
$smart_wait = $minimum; | |||||
} | |||||
return (int)$smart_wait; | return (int)$smart_wait; | ||||
} | } | ||||
/** | /** | ||||
* Retrieve the sevice URI for the device hosting this repository. | * Retrieve the sevice URI for the device hosting this repository. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 637 Lines • Show Last 20 Lines |