@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.

When database connection exceptions occur, raise them to the setup layer

Summary:
Ref T13141. Currently, during first-time setup we don't surface all the details about connection exceptions that we could: the underlying exception is discarded inside cluster connection management.

This isn't a huge issue since the reason for connection problems is usually fairly obvious, but in at least one case (see T13141) we hit a less-than-obvious exception.

Instead, store the original exception and propagate the message up the stack so users have more information about the problem.

Test Plan:
- Configured an intentionally bad MySQL username.
- Restarted Apache and loaded Phabricator.
- Got a more helpful exception with a specific authentication error message.

{F5622361}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13141

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

+28 -8
+7
src/infrastructure/cluster/PhabricatorDatabaseRef.php
··· 29 29 private $connectionLatency; 30 30 private $connectionStatus; 31 31 private $connectionMessage; 32 + private $connectionException; 32 33 33 34 private $replicaStatus; 34 35 private $replicaMessage; ··· 453 454 return false; 454 455 } 455 456 457 + $this->connectionException = null; 456 458 try { 457 459 $connection->openConnection(); 458 460 $reachable = true; ··· 463 465 // yet. 464 466 throw $ex; 465 467 } catch (Exception $ex) { 468 + $this->connectionException = $ex; 466 469 $reachable = false; 467 470 } 468 471 ··· 504 507 $this->getHealthRecordCacheKey()); 505 508 } 506 509 return $this->healthRecord; 510 + } 511 + 512 + public function getConnectionException() { 513 + return $this->connectionException; 507 514 } 508 515 509 516 public static function getActiveDatabaseRefs() {
+21 -8
src/infrastructure/storage/lisk/PhabricatorLiskDAO.php
··· 80 80 $master = PhabricatorDatabaseRef::getMasterDatabaseRefForApplication( 81 81 $application); 82 82 83 + $master_exception = null; 84 + 83 85 if ($master && !$master->isSevered()) { 84 86 $connection = $master->newApplicationConnection($database); 85 87 if ($master->isReachable($connection)) { ··· 91 93 PhabricatorEnv::setReadOnly( 92 94 true, 93 95 PhabricatorEnv::READONLY_UNREACHABLE); 96 + 97 + $master_exception = $master->getConnectionException(); 94 98 } 95 99 } 96 100 ··· 108 112 $this->raiseUnconfigured($database); 109 113 } 110 114 111 - $this->raiseUnreachable($database); 115 + $this->raiseUnreachable($database, $master_exception); 112 116 } 113 117 114 118 private function raiseImproperWrite($database) { ··· 136 140 $database)); 137 141 } 138 142 139 - private function raiseUnreachable($database) { 140 - throw new PhabricatorClusterStrandedException( 141 - pht( 142 - 'Unable to establish a connection to any database host '. 143 - '(while trying "%s"). All masters and replicas are completely '. 144 - 'unreachable.', 145 - $database)); 143 + private function raiseUnreachable($database, Exception $proxy = null) { 144 + $message = pht( 145 + 'Unable to establish a connection to any database host '. 146 + '(while trying "%s"). All masters and replicas are completely '. 147 + 'unreachable.', 148 + $database); 149 + 150 + if ($proxy) { 151 + $proxy_message = pht( 152 + '%s: %s', 153 + get_class($proxy), 154 + $proxy->getMessage()); 155 + $message = $message."\n\n".$proxy_message; 156 + } 157 + 158 + throw new PhabricatorClusterStrandedException($message); 146 159 } 147 160 148 161