Differential D15703 Diff 37833 src/applications/notification/client/PhabricatorNotificationServerRef.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/notification/client/PhabricatorNotificationServerRef.php
- This file was added.
<?php | |||||
final class PhabricatorNotificationServerRef | |||||
extends Phobject { | |||||
private $type; | |||||
private $host; | |||||
private $port; | |||||
private $protocol; | |||||
private $path; | |||||
private $isDisabled; | |||||
const KEY_REFS = 'notification.refs'; | |||||
public function setType($type) { | |||||
$this->type = $type; | |||||
return $this; | |||||
} | |||||
public function getType() { | |||||
return $this->type; | |||||
} | |||||
public function setHost($host) { | |||||
$this->host = $host; | |||||
return $this; | |||||
} | |||||
public function getHost() { | |||||
return $this->host; | |||||
} | |||||
public function setPort($port) { | |||||
$this->port = $port; | |||||
return $this; | |||||
} | |||||
public function getPort() { | |||||
return $this->port; | |||||
} | |||||
public function setProtocol($protocol) { | |||||
$this->protocol = $protocol; | |||||
return $this; | |||||
} | |||||
public function getProtocol() { | |||||
return $this->protocol; | |||||
} | |||||
public function setPath($path) { | |||||
$this->path = $path; | |||||
return $this; | |||||
} | |||||
public function getPath() { | |||||
return $this->path; | |||||
} | |||||
public function setIsDisabled($is_disabled) { | |||||
$this->isDisabled = $is_disabled; | |||||
return $this; | |||||
} | |||||
public function getIsDisabled() { | |||||
return $this->isDisabled; | |||||
} | |||||
public static function getLiveServers() { | |||||
$cache = PhabricatorCaches::getRequestCache(); | |||||
$refs = $cache->getKey(self::KEY_REFS); | |||||
if (!$refs) { | |||||
$refs = self::newRefs(); | |||||
$cache->setKey(self::KEY_REFS, $refs); | |||||
} | |||||
return $refs; | |||||
} | |||||
public static function newRefs() { | |||||
$configs = PhabricatorEnv::getEnvConfig('notification.servers'); | |||||
$refs = array(); | |||||
foreach ($configs as $config) { | |||||
$ref = id(new self()) | |||||
->setType($config['type']) | |||||
->setHost($config['host']) | |||||
->setPort($config['port']) | |||||
->setProtocol($config['protocol']) | |||||
->setPath(idx($config, 'path')) | |||||
->setIsDisabled(idx($config, 'disabled', false)); | |||||
$refs[] = $ref; | |||||
} | |||||
return $refs; | |||||
} | |||||
public static function getEnabledServers() { | |||||
$servers = self::getLiveServers(); | |||||
foreach ($servers as $key => $server) { | |||||
if ($server->getIsDisabled()) { | |||||
unset($servers[$key]); | |||||
} | |||||
} | |||||
return array_values($servers); | |||||
} | |||||
public static function getEnabledAdminServers() { | |||||
$servers = self::getEnabledServers(); | |||||
foreach ($servers as $key => $server) { | |||||
if (!$server->isAdminServer()) { | |||||
unset($servers[$key]); | |||||
} | |||||
} | |||||
return array_values($servers); | |||||
} | |||||
public static function getEnabledClientServers($with_protocol) { | |||||
$servers = self::getEnabledServers(); | |||||
foreach ($servers as $key => $server) { | |||||
if ($server->isAdminServer()) { | |||||
unset($servers[$key]); | |||||
continue; | |||||
} | |||||
$protocol = $server->getProtocol(); | |||||
if ($protocol != $with_protocol) { | |||||
unset($servers[$key]); | |||||
continue; | |||||
} | |||||
} | |||||
return array_values($servers); | |||||
} | |||||
public function isAdminServer() { | |||||
return ($this->type == 'admin'); | |||||
} | |||||
public function getURI($to_path = null) { | |||||
$full_path = rtrim($this->getPath(), '/').'/'.ltrim($to_path, '/'); | |||||
$uri = id(new PhutilURI('http://'.$this->getHost())) | |||||
->setProtocol($this->getProtocol()) | |||||
->setPort($this->getPort()) | |||||
->setPath($full_path); | |||||
$instance = PhabricatorEnv::getEnvConfig('cluster.instance'); | |||||
if (strlen($instance)) { | |||||
$uri->setQueryParam('instance', $instance); | |||||
} | |||||
return $uri; | |||||
} | |||||
public function getWebsocketURI($to_path = null) { | |||||
$instance = PhabricatorEnv::getEnvConfig('cluster.instance'); | |||||
if (strlen($instance)) { | |||||
$to_path = $to_path.$instance.'/'; | |||||
} | |||||
$uri = $this->getURI($to_path); | |||||
if ($this->getProtocol() == 'https') { | |||||
$uri->setProtocol('wss'); | |||||
} else { | |||||
$uri->setProtocol('ws'); | |||||
} | |||||
return $uri; | |||||
} | |||||
public function testClient() { | |||||
if ($this->isAdminServer()) { | |||||
throw new Exception( | |||||
pht('Unable to test client on an admin server!')); | |||||
} | |||||
$server_uri = $this->getURI(); | |||||
try { | |||||
id(new HTTPSFuture($server_uri)) | |||||
->setTimeout(2) | |||||
->resolvex(); | |||||
} catch (HTTPFutureHTTPResponseStatus $ex) { | |||||
// This is what we expect when things are working correctly. | |||||
if ($ex->getStatusCode() == 501) { | |||||
return true; | |||||
} | |||||
throw $ex; | |||||
} | |||||
throw new Exception( | |||||
pht('Got HTTP 200, but expected HTTP 501 (WebSocket Upgrade)!')); | |||||
} | |||||
public function loadServerStatus() { | |||||
if (!$this->isAdminServer()) { | |||||
throw new Exception( | |||||
pht( | |||||
'Unable to load server status: this is not an admin server!')); | |||||
} | |||||
$server_uri = $this->getURI('/status/'); | |||||
list($body) = id(new HTTPSFuture($server_uri)) | |||||
->setTimeout(2) | |||||
->resolvex(); | |||||
return phutil_json_decode($body); | |||||
} | |||||
public function postMessage(array $data) { | |||||
if (!$this->isAdminServer()) { | |||||
throw new Exception( | |||||
pht('Unable to post message: this is not an admin server!')); | |||||
} | |||||
$server_uri = $this->getURI('/'); | |||||
$payload = phutil_json_encode($data); | |||||
id(new HTTPSFuture($server_uri, $payload)) | |||||
->setMethod('POST') | |||||
->setTimeout(2) | |||||
->resolvex(); | |||||
} | |||||
} |