Path: blob/master/src/infrastructure/cluster/PhabricatorClusterServiceHealthRecord.php
12241 views
<?php12class PhabricatorClusterServiceHealthRecord3extends Phobject {45private $cacheKey;6private $shouldCheck;7private $isHealthy;8private $upEventCount;9private $downEventCount;1011public function __construct($cache_key) {12$this->cacheKey = $cache_key;13$this->readState();14}1516/**17* Is the database currently healthy?18*/19public function getIsHealthy() {20return $this->isHealthy;21}222324/**25* Should this request check database health?26*/27public function getShouldCheck() {28return $this->shouldCheck;29}303132/**33* How many recent health checks were successful?34*/35public function getUpEventCount() {36return $this->upEventCount;37}383940/**41* How many recent health checks failed?42*/43public function getDownEventCount() {44return $this->downEventCount;45}464748/**49* Number of failures or successes we need to see in a row before we change50* the state.51*/52public function getRequiredEventCount() {53// NOTE: If you change this value, update the "Cluster: Databases" docs.54return 5;55}565758/**59* Seconds to wait between health checks.60*/61public function getHealthCheckFrequency() {62// NOTE: If you change this value, update the "Cluster: Databases" docs.63return 3;64}656667public function didHealthCheck($result) {68$now = microtime(true);69$check_frequency = $this->getHealthCheckFrequency();70$event_count = $this->getRequiredEventCount();7172$record = $this->readHealthRecord();7374$log = $record['log'];75foreach ($log as $key => $event) {76$when = idx($event, 'timestamp');7778// If the log already has another nearby event, just ignore this one.79// We raced with another process and our result can just be thrown away.80if (($now - $when) <= $check_frequency) {81return $this;82}83}8485$log[] = array(86'timestamp' => $now,87'up' => $result,88);8990// Throw away older events which are now obsolete.91$log = array_slice($log, -$event_count);9293$count_up = 0;94$count_down = 0;95foreach ($log as $event) {96if ($event['up']) {97$count_up++;98} else {99$count_down++;100}101}102103// If all of the events are the same, change the state.104if ($count_up == $event_count) {105$record['up'] = true;106} else if ($count_down == $event_count) {107$record['up'] = false;108}109110$record['log'] = $log;111112$this->writeHealthRecord($record);113114$this->isHealthy = $record['up'];115$this->shouldCheck = false;116$this->updateStatistics($record);117118return $this;119}120121122private function readState() {123$now = microtime(true);124$check_frequency = $this->getHealthCheckFrequency();125126$record = $this->readHealthRecord();127128$last_check = $record['lastCheck'];129130if (($now - $last_check) >= $check_frequency) {131$record['lastCheck'] = $now;132$this->writeHealthRecord($record);133$this->shouldCheck = true;134} else {135$this->shouldCheck = false;136}137138$this->isHealthy = $record['up'];139$this->updateStatistics($record);140}141142private function updateStatistics(array $record) {143$this->upEventCount = 0;144$this->downEventCount = 0;145foreach ($record['log'] as $event) {146if ($event['up']) {147$this->upEventCount++;148} else {149$this->downEventCount++;150}151}152}153154public function getCacheKey() {155return $this->cacheKey;156}157158private function readHealthRecord() {159$cache = PhabricatorCaches::getSetupCache();160$cache_key = $this->getCacheKey();161$health_record = $cache->getKey($cache_key);162163if (!is_array($health_record)) {164$health_record = array(165'up' => true,166'lastCheck' => 0,167'log' => array(),168);169}170171return $health_record;172}173174private function writeHealthRecord(array $record) {175$cache = PhabricatorCaches::getSetupCache();176$cache_key = $this->getCacheKey();177$cache->setKey($cache_key, $record);178}179180}181182183