diff --git a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php --- a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php +++ b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php @@ -346,6 +346,49 @@ } $sleep_for = (int)$repository->getDetail('pull-frequency', $min_sleep); + + // Smart wait: pull rarely used repositories less frequently. Find the + // most recent commit which is older than the current time (this keeps us + // from spinning on repositories with a silly commit post-dated to some time + // in 2037), and adjust how frequently we pull based on how frequently this + // repository updates. + + $table = id(new PhabricatorRepositoryCommit()); + $last_commit = queryfx_one( + $table->establishConnection('w'), + 'SELECT epoch FROM %T + WHERE repositoryID = %d AND epoch <= %d + ORDER BY epoch DESC LIMIT 1', + $table->getTableName(), + $repository->getID(), + time() + $min_sleep); + if ($last_commit) { + $time_since_commit = (time() + $min_sleep) - $last_commit['epoch']; + + // Wait 0.5% of the time since the last commit before we pull. This gives + // us these wait times: + // + // 50 minutes or less: 15 seconds + // about 3 hours: 1 minute + // about 16 hours: 5 minutes + // about 2 days: 15 minutes + // 50 days or more: 6 hours + + $smart_wait = ($time_since_commit / 200); + $smart_wait = min($smart_wait, phutil_units('6 hours in seconds')); + + $this->log( + pht( + 'Last commit to repository "%s" was %s seconds ago; considering '. + 'a wait of %s seconds before update.', + $repository->getMonogram(), + new PhutilNumber($time_since_commit), + new PhutilNumber($smart_wait))); + + $smart_wait = max(15, $smart_wait); + $sleep_for = max($smart_wait, $sleep_for); + } + if ($sleep_for < $min_sleep) { $sleep_for = $min_sleep; }