/** * Load the pull frequency for this repository, based on the time since the * last activity. * * We pull rarely used repositories less frequently. This finds the most * recent commit which is older than the current time (which prevents us from * 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 * occurred. * * @param int The minimum update interval to use, in seconds. * @return int Repository update interval, in seconds. */ 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 // possible. This prevents us from hanging for a long time at 99.9% when // importing an inactive repository. if ($this->isImporting()) { return $minimum; } $window_start = PhabricatorTime::getNow() + $minimum; $table = id(new PhabricatorRepositoryCommit()); $last_commit = queryfx_one($table->establishConnection('r'), 'SELECT epoch FROM %T WHERE repositoryID = %d AND epoch <= %d ORDER BY epoch DESC LIMIT 1', $table->getTableName(), $this->getID(), $window_start); if ($last_commit) { $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'); if ($time_since_commit <= $last_few_days) { // For repositories with activity in the recent past, we wait one // extra second for every 10 minutes since the last commit. This // shorter backoff is intended to handle weekends and other short // breaks from development. $smart_wait = $time_since_commit / 600; } else { // For repositories without recent activity, we wait one extra second // for every 4 minutes since the last commit. This longer backoff // handles rarely used repositories, up to the maximum. $smart_wait = $time_since_commit / 240; } // We'll never wait more than 6 hours to pull a repository. $longest_wait = phutil_units('6 hours in seconds'); $smart_wait = min($smart_wait, $longest_wait); $smart_wait = max($minimum, $smart_wait); return (int) $smart_wait; }
public function writeStatusMessage($status_type, $status_code, array $parameters = array()) { $table = new PhabricatorRepositoryStatusMessage(); $conn_w = $table->establishConnection('w'); $table_name = $table->getTableName(); if ($status_code === null) { queryfx($conn_w, 'DELETE FROM %T WHERE repositoryID = %d AND statusType = %s', $table_name, $this->getID(), $status_type); } else { queryfx($conn_w, 'INSERT INTO %T (repositoryID, statusType, statusCode, parameters, epoch) VALUES (%d, %s, %s, %s, %d) ON DUPLICATE KEY UPDATE statusCode = VALUES(statusCode), parameters = VALUES(parameters), epoch = VALUES(epoch)', $table_name, $this->getID(), $status_type, $status_code, json_encode($parameters), time()); } return $this; }
/** * @task pull */ private function loadLastUpdate(PhabricatorRepository $repository) { $table = new PhabricatorRepositoryStatusMessage(); $conn = $table->establishConnection('r'); $epoch = queryfx_one($conn, 'SELECT MAX(epoch) last_update FROM %T WHERE repositoryID = %d AND statusType IN (%Ls)', $table->getTableName(), $repository->getID(), array(PhabricatorRepositoryStatusMessage::TYPE_INIT, PhabricatorRepositoryStatusMessage::TYPE_FETCH)); if ($epoch) { return (int) $epoch['last_update']; } return PhabricatorTime::getNow(); }