3 class PhabricatorClusterServiceHealthRecord
10 private $downEventCount;
12 public function __construct($cache_key) {
13 $this->cacheKey
= $cache_key;
18 * Is the database currently healthy?
20 public function getIsHealthy() {
21 return $this->isHealthy
;
26 * Should this request check database health?
28 public function getShouldCheck() {
29 return $this->shouldCheck
;
34 * How many recent health checks were successful?
36 public function getUpEventCount() {
37 return $this->upEventCount
;
42 * How many recent health checks failed?
44 public function getDownEventCount() {
45 return $this->downEventCount
;
50 * Number of failures or successes we need to see in a row before we change
53 public function getRequiredEventCount() {
54 // NOTE: If you change this value, update the "Cluster: Databases" docs.
60 * Seconds to wait between health checks.
62 public function getHealthCheckFrequency() {
63 // NOTE: If you change this value, update the "Cluster: Databases" docs.
68 public function didHealthCheck($result) {
69 $now = microtime(true);
70 $check_frequency = $this->getHealthCheckFrequency();
71 $event_count = $this->getRequiredEventCount();
73 $record = $this->readHealthRecord();
75 $log = $record['log'];
76 foreach ($log as $key => $event) {
77 $when = idx($event, 'timestamp');
79 // If the log already has another nearby event, just ignore this one.
80 // We raced with another process and our result can just be thrown away.
81 if (($now - $when) <= $check_frequency) {
91 // Throw away older events which are now obsolete.
92 $log = array_slice($log, -$event_count);
96 foreach ($log as $event) {
104 // If all of the events are the same, change the state.
105 if ($count_up == $event_count) {
106 $record['up'] = true;
107 } else if ($count_down == $event_count) {
108 $record['up'] = false;
111 $record['log'] = $log;
113 $this->writeHealthRecord($record);
115 $this->isHealthy
= $record['up'];
116 $this->shouldCheck
= false;
117 $this->updateStatistics($record);
123 private function readState() {
124 $now = microtime(true);
125 $check_frequency = $this->getHealthCheckFrequency();
127 $record = $this->readHealthRecord();
129 $last_check = $record['lastCheck'];
131 if (($now - $last_check) >= $check_frequency) {
132 $record['lastCheck'] = $now;
133 $this->writeHealthRecord($record);
134 $this->shouldCheck
= true;
136 $this->shouldCheck
= false;
139 $this->isHealthy
= $record['up'];
140 $this->updateStatistics($record);
143 private function updateStatistics(array $record) {
144 $this->upEventCount
= 0;
145 $this->downEventCount
= 0;
146 foreach ($record['log'] as $event) {
148 $this->upEventCount++
;
150 $this->downEventCount++
;
155 public function getCacheKey() {
156 return $this->cacheKey
;
159 private function readHealthRecord() {
160 $cache = PhabricatorCaches
::getSetupCache();
161 $cache_key = $this->getCacheKey();
162 $health_record = $cache->getKey($cache_key);
164 if (!is_array($health_record)) {
165 $health_record = array(
172 return $health_record;
175 private function writeHealthRecord(array $record) {
176 $cache = PhabricatorCaches
::getSetupCache();
177 $cache_key = $this->getCacheKey();
178 $cache->setKey($cache_key, $record);