Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/cluster/PhabricatorDatabaseRef.php
<?php | <?php | ||||
final class PhabricatorDatabaseRef | final class PhabricatorDatabaseRef | ||||
extends Phobject { | extends Phobject { | ||||
const STATUS_OKAY = 'okay'; | const STATUS_OKAY = 'okay'; | ||||
const STATUS_FAIL = 'fail'; | const STATUS_FAIL = 'fail'; | ||||
const STATUS_AUTH = 'auth'; | const STATUS_AUTH = 'auth'; | ||||
const STATUS_REPLICATION_CLIENT = 'replication-client'; | const STATUS_REPLICATION_CLIENT = 'replication-client'; | ||||
const REPLICATION_OKAY = 'okay'; | const REPLICATION_OKAY = 'okay'; | ||||
const REPLICATION_MASTER_REPLICA = 'master-replica'; | const REPLICATION_MASTER_REPLICA = 'master-replica'; | ||||
const REPLICATION_REPLICA_NONE = 'replica-none'; | const REPLICATION_REPLICA_NONE = 'replica-none'; | ||||
const REPLICATION_SLOW = 'replica-slow'; | const REPLICATION_SLOW = 'replica-slow'; | ||||
const KEY_REFS = 'cluster.db.refs'; | const KEY_REFS = 'cluster.db.refs'; | ||||
const KEY_INDIVIDUAL = 'cluster.db.individual'; | |||||
private $host; | private $host; | ||||
private $port; | private $port; | ||||
private $user; | private $user; | ||||
private $pass; | private $pass; | ||||
private $disabled; | private $disabled; | ||||
private $isMaster; | private $isMaster; | ||||
private $isIndividual; | |||||
private $connectionLatency; | private $connectionLatency; | ||||
private $connectionStatus; | private $connectionStatus; | ||||
private $connectionMessage; | private $connectionMessage; | ||||
private $replicaStatus; | private $replicaStatus; | ||||
private $replicaMessage; | private $replicaMessage; | ||||
private $replicaDelay; | private $replicaDelay; | ||||
▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | public function setReplicaDelay($replica_delay) { | ||||
$this->replicaDelay = $replica_delay; | $this->replicaDelay = $replica_delay; | ||||
return $this; | return $this; | ||||
} | } | ||||
public function getReplicaDelay() { | public function getReplicaDelay() { | ||||
return $this->replicaDelay; | return $this->replicaDelay; | ||||
} | } | ||||
public function setIsIndividual($is_individual) { | |||||
$this->isIndividual = $is_individual; | |||||
return $this; | |||||
} | |||||
public function getIsIndividual() { | |||||
return $this->isIndividual; | |||||
} | |||||
public static function getConnectionStatusMap() { | public static function getConnectionStatusMap() { | ||||
return array( | return array( | ||||
self::STATUS_OKAY => array( | self::STATUS_OKAY => array( | ||||
'icon' => 'fa-exchange', | 'icon' => 'fa-exchange', | ||||
'color' => 'green', | 'color' => 'green', | ||||
'label' => pht('Okay'), | 'label' => pht('Okay'), | ||||
), | ), | ||||
self::STATUS_FAIL => array( | self::STATUS_FAIL => array( | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | public static function getLiveRefs() { | ||||
if (!$refs) { | if (!$refs) { | ||||
$refs = self::newRefs(); | $refs = self::newRefs(); | ||||
$cache->setKey(self::KEY_REFS, $refs); | $cache->setKey(self::KEY_REFS, $refs); | ||||
} | } | ||||
return $refs; | return $refs; | ||||
} | } | ||||
public static function getLiveIndividualRef() { | |||||
$cache = PhabricatorCaches::getRequestCache(); | |||||
$ref = $cache->getKey(self::KEY_INDIVIDUAL); | |||||
if (!$ref) { | |||||
$ref = self::newIndividualRef(); | |||||
$cache->setKey(self::KEY_INDIVIDUAL, $ref); | |||||
} | |||||
return $ref; | |||||
} | |||||
public static function newRefs() { | public static function newRefs() { | ||||
$refs = array(); | $refs = array(); | ||||
$default_port = PhabricatorEnv::getEnvConfig('mysql.port'); | $default_port = PhabricatorEnv::getEnvConfig('mysql.port'); | ||||
$default_port = nonempty($default_port, 3306); | $default_port = nonempty($default_port, 3306); | ||||
$default_user = PhabricatorEnv::getEnvConfig('mysql.user'); | $default_user = PhabricatorEnv::getEnvConfig('mysql.user'); | ||||
▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | final class PhabricatorDatabaseRef | ||||
public function newApplicationConnection($database) { | public function newApplicationConnection($database) { | ||||
return $this->newConnection( | return $this->newConnection( | ||||
array( | array( | ||||
'database' => $database, | 'database' => $database, | ||||
)); | )); | ||||
} | } | ||||
public function isSevered() { | public function isSevered() { | ||||
// If we only have an individual database, never sever our connection to | |||||
// it, at least for now. It's possible that using the same severing rules | |||||
// might eventually make sense to help alleviate load-related failures, | |||||
// but we should wait for all the cluster stuff to stabilize first. | |||||
if ($this->getIsIndividual()) { | |||||
return false; | |||||
} | |||||
if ($this->didFailToConnect) { | if ($this->didFailToConnect) { | ||||
return true; | return true; | ||||
} | } | ||||
$record = $this->getHealthRecord(); | $record = $this->getHealthRecord(); | ||||
$is_healthy = $record->getIsHealthy(); | $is_healthy = $record->getIsHealthy(); | ||||
if (!$is_healthy) { | if (!$is_healthy) { | ||||
return true; | return true; | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | public function getHealthRecord() { | ||||
} | } | ||||
return $this->healthRecord; | return $this->healthRecord; | ||||
} | } | ||||
public static function getMasterDatabaseRef() { | public static function getMasterDatabaseRef() { | ||||
$refs = self::getLiveRefs(); | $refs = self::getLiveRefs(); | ||||
if (!$refs) { | if (!$refs) { | ||||
$conf = PhabricatorEnv::newObjectFromConfig( | return self::getLiveIndividualRef(); | ||||
'mysql.configuration-provider', | |||||
array(null, 'w', null)); | |||||
return id(new self()) | |||||
->setHost($conf->getHost()) | |||||
->setPort($conf->getPort()) | |||||
->setUser($conf->getUser()) | |||||
->setPass($conf->getPassword()) | |||||
->setIsMaster(true); | |||||
} | } | ||||
$master = null; | $master = null; | ||||
foreach ($refs as $ref) { | foreach ($refs as $ref) { | ||||
if ($ref->getDisabled()) { | if ($ref->getDisabled()) { | ||||
continue; | continue; | ||||
} | } | ||||
if ($ref->getIsMaster()) { | if ($ref->getIsMaster()) { | ||||
return $ref; | return $ref; | ||||
} | } | ||||
} | } | ||||
return null; | return null; | ||||
} | } | ||||
public static function newIndividualRef() { | |||||
$conf = PhabricatorEnv::newObjectFromConfig( | |||||
'mysql.configuration-provider', | |||||
array(null, 'w', null)); | |||||
return id(new self()) | |||||
->setHost($conf->getHost()) | |||||
->setPort($conf->getPort()) | |||||
->setUser($conf->getUser()) | |||||
->setPass($conf->getPassword()) | |||||
->setIsIndividual(true) | |||||
->setIsMaster(true); | |||||
} | |||||
public static function getReplicaDatabaseRef() { | public static function getReplicaDatabaseRef() { | ||||
$refs = self::getLiveRefs(); | $refs = self::getLiveRefs(); | ||||
if (!$refs) { | if (!$refs) { | ||||
return null; | return null; | ||||
} | } | ||||
// TODO: We may have multiple replicas to choose from, and could make | // TODO: We may have multiple replicas to choose from, and could make | ||||
▲ Show 20 Lines • Show All 48 Lines • Show Last 20 Lines |