@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at recaptime-dev/main 200 lines 5.5 kB view raw
1<?php 2 3/** 4 * @task config Configuring Repository Engines 5 * @task internal Internals 6 */ 7abstract class PhabricatorRepositoryEngine extends Phobject { 8 9 private $repository; 10 private $verbose; 11 12 /** 13 * @task config 14 */ 15 public function setRepository(PhabricatorRepository $repository) { 16 $this->repository = $repository; 17 return $this; 18 } 19 20 21 /** 22 * @task config 23 */ 24 protected function getRepository() { 25 if ($this->repository === null) { 26 throw new PhutilInvalidStateException('setRepository'); 27 } 28 29 return $this->repository; 30 } 31 32 33 /** 34 * @task config 35 */ 36 public function setVerbose($verbose) { 37 $this->verbose = $verbose; 38 return $this; 39 } 40 41 42 /** 43 * @task config 44 */ 45 public function getVerbose() { 46 return $this->verbose; 47 } 48 49 50 public function getViewer() { 51 return PhabricatorUser::getOmnipotentUser(); 52 } 53 54 protected function newRepositoryLock( 55 PhabricatorRepository $repository, 56 $lock_key, 57 $lock_device_only) { 58 59 $lock_parts = array( 60 'repositoryPHID' => $repository->getPHID(), 61 ); 62 63 if ($lock_device_only) { 64 $device = AlmanacKeys::getLiveDevice(); 65 if ($device) { 66 $lock_parts['devicePHID'] = $device->getPHID(); 67 } 68 } 69 70 return PhabricatorGlobalLock::newLock($lock_key, $lock_parts); 71 } 72 73 /** 74 * @task internal 75 */ 76 protected function log($pattern /* ... */) { 77 if ($this->getVerbose()) { 78 $console = PhutilConsole::getConsole(); 79 $argv = func_get_args(); 80 array_unshift($argv, "%s\n"); 81 call_user_func_array(array($console, 'writeOut'), $argv); 82 } 83 return $this; 84 } 85 86 final protected function queueCommitImportTask( 87 PhabricatorRepository $repository, 88 $commit_phid, 89 $task_priority, 90 $via) { 91 92 $vcs = $repository->getVersionControlSystem(); 93 switch ($vcs) { 94 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 95 $class = 'PhabricatorRepositoryGitCommitMessageParserWorker'; 96 break; 97 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 98 $class = 'PhabricatorRepositorySvnCommitMessageParserWorker'; 99 break; 100 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 101 $class = 'PhabricatorRepositoryMercurialCommitMessageParserWorker'; 102 break; 103 default: 104 throw new Exception( 105 pht( 106 'Unknown repository type "%s"!', 107 $vcs)); 108 } 109 110 $data = array( 111 'commitPHID' => $commit_phid, 112 ); 113 114 if ($via !== null) { 115 $data['via'] = $via; 116 } 117 118 $options = array( 119 'priority' => $task_priority, 120 'objectPHID' => $commit_phid, 121 'containerPHID' => $repository->getPHID(), 122 ); 123 124 PhabricatorWorker::scheduleTask($class, $data, $options); 125 } 126 127 /** 128 * @param PhabricatorRepository $repository 129 * @param array<PhabricatorRepositoryCommitRef> $refs 130 */ 131 final protected function getImportTaskPriority( 132 PhabricatorRepository $repository, 133 array $refs) { 134 assert_instances_of($refs, PhabricatorRepositoryCommitRef::class); 135 136 // If the repository is importing for the first time, we schedule tasks 137 // at IMPORT priority, which is very low. Making progress on importing a 138 // new repository for the first time is less important than any other 139 // daemon task. 140 141 // If the repository has finished importing and we're just catching up 142 // on recent commits, we usually schedule discovery at COMMIT priority, 143 // which is slightly below the default priority. 144 145 // Note that followup tasks and triggered tasks (like those generated by 146 // Herald or Harbormaster) will queue at DEFAULT priority, so that each 147 // commit tends to fully import before we start the next one. This tends 148 // to give imports fairly predictable progress. See T11677 for some 149 // discussion. 150 151 if ($repository->isImporting()) { 152 $this->log( 153 pht( 154 'Importing %s commit(s) at low priority ("PRIORITY_IMPORT") '. 155 'because this repository is still importing.', 156 phutil_count($refs))); 157 158 return PhabricatorWorker::PRIORITY_IMPORT; 159 } 160 161 // See T13369. If we've discovered a lot of commits at once, import them 162 // at lower priority. 163 164 // This is mostly aimed at reducing the impact that synchronizing thousands 165 // of commits from a remote upstream has on other repositories. The queue 166 // is "mostly FIFO", so queueing a thousand commit imports can stall other 167 // repositories. 168 169 // In a perfect world we'd probably give repositories round-robin queue 170 // priority, but we don't currently have the primitives for this and there 171 // isn't a strong case for building them. 172 173 // Use "a whole lot of commits showed up at once" as a heuristic for 174 // detecting "someone synchronized an upstream", and import them at a lower 175 // priority to more closely approximate fair scheduling. 176 177 if (count($refs) >= PhabricatorRepository::LOWPRI_THRESHOLD) { 178 $this->log( 179 pht( 180 'Importing %s commits at low priority ("PRIORITY_IMPORT") '. 181 'because many commits were discovered at once.', 182 phutil_count($refs))); 183 184 return PhabricatorWorker::PRIORITY_IMPORT; 185 } 186 187 // Otherwise, import at normal priority. 188 189 if ($refs) { 190 $this->log( 191 pht( 192 'Importing %s commit(s) at normal priority ("PRIORITY_COMMIT").', 193 phutil_count($refs))); 194 } 195 196 return PhabricatorWorker::PRIORITY_COMMIT; 197 } 198 199 200}