@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
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Make cluster repositories more chatty

Summary:
Ref T10860. At least in Git over SSH, we can freely echo a bunch of stuff to stderr and Git will print it to the console, so we can tell users what's going on.

This should make debugging, etc., easier. We could tone this down a little bit once things are more stable if it's a little too chatty.

Test Plan:
```
$ echo D >> record && git commit -am D && git push
[master ca5efff] D
1 file changed, 1 insertion(+)
# Push received by "local001.phacility.net", forwarding to cluster host.
# Waiting up to 120 second(s) for a cluster write lock...
# Acquired write lock immediately.
# Waiting up to 120 second(s) for a cluster read lock on "local001.phacility.net"...
# Acquired read lock immediately.
# Device "local001.phacility.net" is already a cluster leader and does not need to be synchronized.
# Ready to receive on cluster host "local001.phacility.net".
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 256 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To ssh://local@localvault.phacility.com/diffusion/26/locktopia.git
8616189..ca5efff master -> master
```

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10860

Differential Revision: https://secure.phabricator.com/D15791

+161 -9
+5 -1
src/__phutil_library_map__.php
··· 746 746 'DiffusionRepositoryBasicsManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryBasicsManagementPanel.php', 747 747 'DiffusionRepositoryByIDRemarkupRule' => 'applications/diffusion/remarkup/DiffusionRepositoryByIDRemarkupRule.php', 748 748 'DiffusionRepositoryClusterEngine' => 'applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php', 749 + 'DiffusionRepositoryClusterEngineLogInterface' => 'applications/diffusion/protocol/DiffusionRepositoryClusterEngineLogInterface.php', 749 750 'DiffusionRepositoryClusterManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryClusterManagementPanel.php', 750 751 'DiffusionRepositoryController' => 'applications/diffusion/controller/DiffusionRepositoryController.php', 751 752 'DiffusionRepositoryCreateController' => 'applications/diffusion/controller/DiffusionRepositoryCreateController.php', ··· 4854 4855 'DiffusionGitReceivePackSSHWorkflow' => 'DiffusionGitSSHWorkflow', 4855 4856 'DiffusionGitRequest' => 'DiffusionRequest', 4856 4857 'DiffusionGitResponse' => 'AphrontResponse', 4857 - 'DiffusionGitSSHWorkflow' => 'DiffusionSSHWorkflow', 4858 + 'DiffusionGitSSHWorkflow' => array( 4859 + 'DiffusionSSHWorkflow', 4860 + 'DiffusionRepositoryClusterEngineLogInterface', 4861 + ), 4858 4862 'DiffusionGitUploadPackSSHWorkflow' => 'DiffusionGitSSHWorkflow', 4859 4863 'DiffusionHistoryController' => 'DiffusionController', 4860 4864 'DiffusionHistoryQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
+109 -6
src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php
··· 13 13 private $viewer; 14 14 private $clusterWriteLock; 15 15 private $clusterWriteVersion; 16 + private $logger; 16 17 17 18 18 19 /* -( Configuring Synchronization )---------------------------------------- */ ··· 34 35 35 36 public function getViewer() { 36 37 return $this->viewer; 38 + } 39 + 40 + public function setLog(DiffusionRepositoryClusterEngineLogInterface $log) { 41 + $this->logger = $log; 42 + return $this; 37 43 } 38 44 39 45 ··· 92 98 $repository_phid, 93 99 $device_phid); 94 100 95 - // TODO: Raise a more useful exception if we fail to grab this lock. 96 - $read_lock->lock(phutil_units('2 minutes in seconds')); 101 + $lock_wait = phutil_units('2 minutes in seconds'); 102 + 103 + $this->logLine( 104 + pht( 105 + 'Waiting up to %s second(s) for a cluster read lock on "%s"...', 106 + new PhutilNumber($lock_wait), 107 + $device->getName())); 108 + 109 + try { 110 + $start = PhabricatorTime::getNow(); 111 + $read_lock->lock($lock_wait); 112 + $waited = (PhabricatorTime::getNow() - $start); 113 + 114 + if ($waited) { 115 + $this->logLine( 116 + pht( 117 + 'Acquired read lock after %s second(s).', 118 + new PhutilNumber($waited))); 119 + } else { 120 + $this->logLine( 121 + pht( 122 + 'Acquired read lock immediately.')); 123 + } 124 + } catch (Exception $ex) { 125 + throw new PhutilProxyException( 126 + pht( 127 + 'Failed to acquire read lock after waiting %s second(s). You '. 128 + 'may be able to retry later.', 129 + new PhutilNumber($lock_wait))); 130 + } 97 131 98 132 $versions = PhabricatorRepositoryWorkingCopyVersion::loadVersions( 99 133 $repository_phid); ··· 126 160 $repository_phid, 127 161 $device_phid, 128 162 $max_version); 163 + } else { 164 + $this->logLine( 165 + pht( 166 + 'Device "%s" is already a cluster leader and does not need '. 167 + 'to be synchronized.', 168 + $device->getName())); 129 169 } 130 170 131 171 $result_version = $max_version; ··· 210 250 $write_lock = PhabricatorRepositoryWorkingCopyVersion::getWriteLock( 211 251 $repository_phid); 212 252 213 - // TODO: Raise a more useful exception if we fail to grab this lock. 214 - $write_lock->lock(phutil_units('2 minutes in seconds')); 253 + $lock_wait = phutil_units('2 minutes in seconds'); 254 + 255 + $this->logLine( 256 + pht( 257 + 'Waiting up to %s second(s) for a cluster write lock...', 258 + new PhutilNumber($lock_wait))); 259 + 260 + try { 261 + $start = PhabricatorTime::getNow(); 262 + $write_lock->lock($lock_wait); 263 + $waited = (PhabricatorTime::getNow() - $start); 264 + 265 + if ($waited) { 266 + $this->logLine( 267 + pht( 268 + 'Acquired write lock after %s second(s).', 269 + new PhutilNumber($waited))); 270 + } else { 271 + $this->logLine( 272 + pht( 273 + 'Acquired write lock immediately.')); 274 + } 275 + } catch (Exception $ex) { 276 + throw new PhutilProxyException( 277 + pht( 278 + 'Failed to acquire write lock after waiting %s second(s). You '. 279 + 'may be able to retry later.', 280 + new PhutilNumber($lock_wait))); 281 + } 215 282 216 283 $versions = PhabricatorRepositoryWorkingCopyVersion::loadVersions( 217 284 $repository_phid); ··· 393 460 */ 394 461 private function synchronizeWorkingCopyFromBinding($binding) { 395 462 $repository = $this->getRepository(); 463 + $device = AlmanacKeys::getLiveDevice(); 464 + 465 + $this->logLine( 466 + pht( 467 + 'Synchronizing this device ("%s") from cluster leader ("%s") before '. 468 + 'read.', 469 + $device->getName(), 470 + $binding->getDevice()->getName())); 396 471 397 472 $fetch_uri = $repository->getClusterRepositoryURIFromBinding($binding); 398 473 $local_path = $repository->getLocalPath(); 399 474 400 475 if ($repository->isGit()) { 401 476 if (!Filesystem::pathExists($local_path)) { 402 - $device = AlmanacKeys::getLiveDevice(); 403 477 throw new Exception( 404 478 pht( 405 479 'Repository "%s" does not have a working copy on this device '. ··· 429 503 430 504 $future->setCWD($local_path); 431 505 432 - $future->resolvex(); 506 + try { 507 + $future->resolvex(); 508 + } catch (Exception $ex) { 509 + $this->logLine( 510 + pht( 511 + 'Synchronization of "%s" from leader "%s" failed: %s', 512 + $device->getName(), 513 + $binding->getDevice()->getName(), 514 + $ex->getMessage())); 515 + throw $ex; 516 + } 433 517 } 434 518 519 + 520 + /** 521 + * @task internal 522 + */ 523 + private function logLine($message) { 524 + return $this->logText("# {$message}\n"); 525 + } 526 + 527 + 528 + /** 529 + * @task internal 530 + */ 531 + private function logText($message) { 532 + $log = $this->logger; 533 + if ($log) { 534 + $log->writeClusterEngineLogMessage($message); 535 + } 536 + return $this; 537 + } 435 538 }
+7
src/applications/diffusion/protocol/DiffusionRepositoryClusterEngineLogInterface.php
··· 1 + <?php 2 + 3 + interface DiffusionRepositoryClusterEngineLogInterface { 4 + 5 + public function writeClusterEngineLogMessage($message); 6 + 7 + }
+17 -1
src/applications/diffusion/ssh/DiffusionGitReceivePackSSHWorkflow.php
··· 16 16 protected function executeRepositoryOperations() { 17 17 $repository = $this->getRepository(); 18 18 $viewer = $this->getViewer(); 19 + $device = AlmanacKeys::getLiveDevice(); 19 20 20 21 // This is a write, and must have write access. 21 22 $this->requireWriteAccess(); 22 23 23 24 $cluster_engine = id(new DiffusionRepositoryClusterEngine()) 24 25 ->setViewer($viewer) 25 - ->setRepository($repository); 26 + ->setRepository($repository) 27 + ->setLog($this); 26 28 27 29 if ($this->shouldProxy()) { 28 30 $command = $this->getProxyCommand(); 29 31 $did_synchronize = false; 32 + 33 + if ($device) { 34 + $this->writeClusterEngineLogMessage( 35 + pht( 36 + "# Push received by \"%s\", forwarding to cluster host.\n", 37 + $device->getName())); 38 + } 30 39 } else { 31 40 $command = csprintf('git-receive-pack %s', $repository->getLocalPath()); 32 41 $did_synchronize = true; 33 42 $cluster_engine->synchronizeWorkingCopyBeforeWrite(); 43 + 44 + if ($device) { 45 + $this->writeClusterEngineLogMessage( 46 + pht( 47 + "# Ready to receive on cluster host \"%s\".\n", 48 + $device->getName())); 49 + } 34 50 } 35 51 36 52 $caught = null;
+7 -1
src/applications/diffusion/ssh/DiffusionGitSSHWorkflow.php
··· 1 1 <?php 2 2 3 - abstract class DiffusionGitSSHWorkflow extends DiffusionSSHWorkflow { 3 + abstract class DiffusionGitSSHWorkflow 4 + extends DiffusionSSHWorkflow 5 + implements DiffusionRepositoryClusterEngineLogInterface { 4 6 5 7 protected function writeError($message) { 6 8 // Git assumes we'll add our own newlines. 7 9 return parent::writeError($message."\n"); 10 + } 11 + 12 + public function writeClusterEngineLogMessage($message) { 13 + parent::writeError($message); 8 14 } 9 15 10 16 protected function identifyRepository() {
+16
src/applications/diffusion/ssh/DiffusionGitUploadPackSSHWorkflow.php
··· 16 16 protected function executeRepositoryOperations() { 17 17 $repository = $this->getRepository(); 18 18 $viewer = $this->getUser(); 19 + $device = AlmanacKeys::getLiveDevice(); 19 20 20 21 $skip_sync = $this->shouldSkipReadSynchronization(); 21 22 22 23 if ($this->shouldProxy()) { 23 24 $command = $this->getProxyCommand(); 25 + 26 + if ($device) { 27 + $this->writeClusterEngineLogMessage( 28 + pht( 29 + "# Fetch received by \"%s\", forwarding to cluster host.\n", 30 + $device->getName())); 31 + } 24 32 } else { 25 33 $command = csprintf('git-upload-pack -- %s', $repository->getLocalPath()); 26 34 if (!$skip_sync) { 27 35 $cluster_engine = id(new DiffusionRepositoryClusterEngine()) 28 36 ->setViewer($viewer) 29 37 ->setRepository($repository) 38 + ->setLog($this) 30 39 ->synchronizeWorkingCopyBeforeRead(); 40 + 41 + if ($device) { 42 + $this->writeClusterEngineLogMessage( 43 + pht( 44 + "# Cleared to fetch on cluster host \"%s\".\n", 45 + $device->getName())); 46 + } 31 47 } 32 48 } 33 49 $command = PhabricatorDaemon::sudoCommandAsDaemonUser($command);