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
This commit is contained in:
@@ -29,6 +29,7 @@ final class PhabricatorDatabaseRef
|
||||
private $connectionLatency;
|
||||
private $connectionStatus;
|
||||
private $connectionMessage;
|
||||
private $connectionException;
|
||||
|
||||
private $replicaStatus;
|
||||
private $replicaMessage;
|
||||
@@ -453,6 +454,7 @@ final class PhabricatorDatabaseRef
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->connectionException = null;
|
||||
try {
|
||||
$connection->openConnection();
|
||||
$reachable = true;
|
||||
@@ -463,6 +465,7 @@ final class PhabricatorDatabaseRef
|
||||
// yet.
|
||||
throw $ex;
|
||||
} catch (Exception $ex) {
|
||||
$this->connectionException = $ex;
|
||||
$reachable = false;
|
||||
}
|
||||
|
||||
@@ -506,6 +509,10 @@ final class PhabricatorDatabaseRef
|
||||
return $this->healthRecord;
|
||||
}
|
||||
|
||||
public function getConnectionException() {
|
||||
return $this->connectionException;
|
||||
}
|
||||
|
||||
public static function getActiveDatabaseRefs() {
|
||||
$refs = array();
|
||||
|
||||
|
||||
@@ -80,6 +80,8 @@ abstract class PhabricatorLiskDAO extends LiskDAO {
|
||||
$master = PhabricatorDatabaseRef::getMasterDatabaseRefForApplication(
|
||||
$application);
|
||||
|
||||
$master_exception = null;
|
||||
|
||||
if ($master && !$master->isSevered()) {
|
||||
$connection = $master->newApplicationConnection($database);
|
||||
if ($master->isReachable($connection)) {
|
||||
@@ -91,6 +93,8 @@ abstract class PhabricatorLiskDAO extends LiskDAO {
|
||||
PhabricatorEnv::setReadOnly(
|
||||
true,
|
||||
PhabricatorEnv::READONLY_UNREACHABLE);
|
||||
|
||||
$master_exception = $master->getConnectionException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +112,7 @@ abstract class PhabricatorLiskDAO extends LiskDAO {
|
||||
$this->raiseUnconfigured($database);
|
||||
}
|
||||
|
||||
$this->raiseUnreachable($database);
|
||||
$this->raiseUnreachable($database, $master_exception);
|
||||
}
|
||||
|
||||
private function raiseImproperWrite($database) {
|
||||
@@ -136,13 +140,22 @@ abstract class PhabricatorLiskDAO extends LiskDAO {
|
||||
$database));
|
||||
}
|
||||
|
||||
private function raiseUnreachable($database) {
|
||||
throw new PhabricatorClusterStrandedException(
|
||||
pht(
|
||||
'Unable to establish a connection to any database host '.
|
||||
'(while trying "%s"). All masters and replicas are completely '.
|
||||
'unreachable.',
|
||||
$database));
|
||||
private function raiseUnreachable($database, Exception $proxy = null) {
|
||||
$message = pht(
|
||||
'Unable to establish a connection to any database host '.
|
||||
'(while trying "%s"). All masters and replicas are completely '.
|
||||
'unreachable.',
|
||||
$database);
|
||||
|
||||
if ($proxy) {
|
||||
$proxy_message = pht(
|
||||
'%s: %s',
|
||||
get_class($proxy),
|
||||
$proxy->getMessage());
|
||||
$message = $message."\n\n".$proxy_message;
|
||||
}
|
||||
|
||||
throw new PhabricatorClusterStrandedException($message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user