Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15516815
D17384.id41801.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
25 KB
Referenced Files
None
Subscribers
None
D17384.id41801.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2245,6 +2245,9 @@
'PhabricatorClusterExceptionHandler' => 'infrastructure/cluster/PhabricatorClusterExceptionHandler.php',
'PhabricatorClusterImpossibleWriteException' => 'infrastructure/cluster/PhabricatorClusterImpossibleWriteException.php',
'PhabricatorClusterImproperWriteException' => 'infrastructure/cluster/PhabricatorClusterImproperWriteException.php',
+ 'PhabricatorClusterRef' => 'infrastructure/cluster/PhabricatorClusterRef.php',
+ 'PhabricatorClusterSearchConfigOptionType' => 'infrastructure/cluster/PhabricatorClusterSearchConfigOptionType.php',
+ 'PhabricatorClusterSearchRef' => 'infrastructure/cluster/PhabricatorClusterSearchRef.php',
'PhabricatorClusterStrandedException' => 'infrastructure/cluster/PhabricatorClusterStrandedException.php',
'PhabricatorColumnProxyInterface' => 'applications/project/interface/PhabricatorColumnProxyInterface.php',
'PhabricatorColumnsEditField' => 'applications/transactions/editfield/PhabricatorColumnsEditField.php',
@@ -2291,6 +2294,7 @@
'PhabricatorConfigClusterDatabasesController' => 'applications/config/controller/PhabricatorConfigClusterDatabasesController.php',
'PhabricatorConfigClusterNotificationsController' => 'applications/config/controller/PhabricatorConfigClusterNotificationsController.php',
'PhabricatorConfigClusterRepositoriesController' => 'applications/config/controller/PhabricatorConfigClusterRepositoriesController.php',
+ 'PhabricatorConfigClusterSearchController' => 'applications/config/controller/PhabricatorConfigClusterSearchController.php',
'PhabricatorConfigCollectorsModule' => 'applications/config/module/PhabricatorConfigCollectorsModule.php',
'PhabricatorConfigColumnSchema' => 'applications/config/schema/PhabricatorConfigColumnSchema.php',
'PhabricatorConfigConfigPHIDType' => 'applications/config/phid/PhabricatorConfigConfigPHIDType.php',
@@ -2620,6 +2624,7 @@
'PhabricatorEditorMultipleSetting' => 'applications/settings/setting/PhabricatorEditorMultipleSetting.php',
'PhabricatorEditorSetting' => 'applications/settings/setting/PhabricatorEditorSetting.php',
'PhabricatorElasticFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php',
+ 'PhabricatorElasticSearchServerRef' => 'infrastructure/cluster/PhabricatorElasticSearchServerRef.php',
'PhabricatorElasticSearchSetupCheck' => 'applications/config/check/PhabricatorElasticSearchSetupCheck.php',
'PhabricatorEmailAddressesSettingsPanel' => 'applications/settings/panel/PhabricatorEmailAddressesSettingsPanel.php',
'PhabricatorEmailContentSource' => 'applications/metamta/contentsource/PhabricatorEmailContentSource.php',
@@ -3041,6 +3046,7 @@
'PhabricatorMySQLFileStorageEngine' => 'applications/files/engine/PhabricatorMySQLFileStorageEngine.php',
'PhabricatorMySQLFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorMySQLFulltextStorageEngine.php',
'PhabricatorMySQLSetupCheck' => 'applications/config/check/PhabricatorMySQLSetupCheck.php',
+ 'PhabricatorMysqlSearchServerRef' => 'infrastructure/cluster/PhabricatorMysqlSearchServerRef.php',
'PhabricatorNamedQuery' => 'applications/search/storage/PhabricatorNamedQuery.php',
'PhabricatorNamedQueryQuery' => 'applications/search/query/PhabricatorNamedQueryQuery.php',
'PhabricatorNavigationRemarkupRule' => 'infrastructure/markup/rule/PhabricatorNavigationRemarkupRule.php',
@@ -7225,6 +7231,9 @@
'PhabricatorClusterExceptionHandler' => 'PhabricatorRequestExceptionHandler',
'PhabricatorClusterImpossibleWriteException' => 'PhabricatorClusterException',
'PhabricatorClusterImproperWriteException' => 'PhabricatorClusterException',
+ 'PhabricatorClusterRef' => 'Phobject',
+ 'PhabricatorClusterSearchConfigOptionType' => 'PhabricatorConfigJSONOptionType',
+ 'PhabricatorClusterSearchRef' => 'PhabricatorClusterRef',
'PhabricatorClusterStrandedException' => 'PhabricatorClusterException',
'PhabricatorColumnsEditField' => 'PhabricatorPHIDListEditField',
'PhabricatorCommentEditEngineExtension' => 'PhabricatorEditEngineExtension',
@@ -7276,6 +7285,7 @@
'PhabricatorConfigClusterDatabasesController' => 'PhabricatorConfigController',
'PhabricatorConfigClusterNotificationsController' => 'PhabricatorConfigController',
'PhabricatorConfigClusterRepositoriesController' => 'PhabricatorConfigController',
+ 'PhabricatorConfigClusterSearchController' => 'PhabricatorConfigController',
'PhabricatorConfigCollectorsModule' => 'PhabricatorConfigModule',
'PhabricatorConfigColumnSchema' => 'PhabricatorConfigStorageSchema',
'PhabricatorConfigConfigPHIDType' => 'PhabricatorPHIDType',
@@ -7545,7 +7555,7 @@
'PhabricatorDataCacheSpec' => 'PhabricatorCacheSpec',
'PhabricatorDataNotAttachedException' => 'Exception',
'PhabricatorDatabaseHealthRecord' => 'Phobject',
- 'PhabricatorDatabaseRef' => 'Phobject',
+ 'PhabricatorDatabaseRef' => 'PhabricatorClusterRef',
'PhabricatorDatabaseRefParser' => 'Phobject',
'PhabricatorDatabaseSetupCheck' => 'PhabricatorSetupCheck',
'PhabricatorDatasourceEditField' => 'PhabricatorTokenizerEditField',
@@ -7647,6 +7657,7 @@
'PhabricatorEditorMultipleSetting' => 'PhabricatorSelectSetting',
'PhabricatorEditorSetting' => 'PhabricatorStringSetting',
'PhabricatorElasticFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine',
+ 'PhabricatorElasticSearchServerRef' => 'PhabricatorClusterSearchRef',
'PhabricatorElasticSearchSetupCheck' => 'PhabricatorSetupCheck',
'PhabricatorEmailAddressesSettingsPanel' => 'PhabricatorSettingsPanel',
'PhabricatorEmailContentSource' => 'PhabricatorContentSource',
@@ -8116,6 +8127,7 @@
'PhabricatorMySQLFileStorageEngine' => 'PhabricatorFileStorageEngine',
'PhabricatorMySQLFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine',
'PhabricatorMySQLSetupCheck' => 'PhabricatorSetupCheck',
+ 'PhabricatorMysqlSearchServerRef' => 'PhabricatorClusterSearchRef',
'PhabricatorNamedQuery' => array(
'PhabricatorSearchDAO',
'PhabricatorPolicyInterface',
diff --git a/src/applications/config/application/PhabricatorConfigApplication.php b/src/applications/config/application/PhabricatorConfigApplication.php
--- a/src/applications/config/application/PhabricatorConfigApplication.php
+++ b/src/applications/config/application/PhabricatorConfigApplication.php
@@ -69,6 +69,7 @@
'databases/' => 'PhabricatorConfigClusterDatabasesController',
'notifications/' => 'PhabricatorConfigClusterNotificationsController',
'repositories/' => 'PhabricatorConfigClusterRepositoriesController',
+ 'search/' => 'PhabricatorConfigClusterSearchController',
),
),
);
diff --git a/src/applications/config/check/PhabricatorElasticSearchSetupCheck.php b/src/applications/config/check/PhabricatorElasticSearchSetupCheck.php
--- a/src/applications/config/check/PhabricatorElasticSearchSetupCheck.php
+++ b/src/applications/config/check/PhabricatorElasticSearchSetupCheck.php
@@ -70,8 +70,14 @@
}
protected function shouldUseElasticSearchEngine() {
- $search_engine = PhabricatorFulltextStorageEngine::loadEngine();
- return ($search_engine instanceof PhabricatorElasticFulltextStorageEngine);
+ $engines = PhabricatorFulltextStorageEngine::loadAllEngines();
+ foreach ($engines as $engine) {
+ if ($engine instanceof PhabricatorElasticFulltextStorageEngine
+ && $engine->isEnabled()) {
+ return true;
+ }
+ }
+ return false;
}
}
diff --git a/src/applications/config/controller/PhabricatorConfigClusterSearchController.php b/src/applications/config/controller/PhabricatorConfigClusterSearchController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/config/controller/PhabricatorConfigClusterSearchController.php
@@ -0,0 +1,143 @@
+<?php
+
+final class PhabricatorConfigClusterSearchController
+ extends PhabricatorConfigController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $nav = $this->buildSideNavView();
+ $nav->selectFilter('cluster/search/');
+
+ $title = pht('Cluster Search');
+ $doc_href = PhabricatorEnv::getDoclink('Cluster: Search');
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader($title)
+ ->setProfileHeader(true)
+ ->addActionLink(
+ id(new PHUIButtonView())
+ ->setIcon('fa-book')
+ ->setHref($doc_href)
+ ->setTag('a')
+ ->setText(pht('Documentation')));
+
+ $crumbs = $this
+ ->buildApplicationCrumbs($nav)
+ ->addTextCrumb($title)
+ ->setBorder(true);
+
+ $search_status = $this->buildClusterSearchStatus();
+
+ $content = id(new PhabricatorConfigPageView())
+ ->setHeader($header)
+ ->setContent($search_status);
+
+ return $this->newPage()
+ ->setTitle($title)
+ ->setCrumbs($crumbs)
+ ->setNavigation($nav)
+ ->appendChild($content)
+ ->addClass('white-background');
+ }
+
+ private function buildClusterSearchStatus() {
+ $viewer = $this->getViewer();
+
+ $servers = PhabricatorClusterSearchRef::newRefs();
+ Javelin::initBehavior('phabricator-tooltips');
+ $status_map = PhabricatorDatabaseRef::getConnectionStatusMap();
+
+ $rows = array();
+ foreach ($servers as $server) {
+
+ try {
+ $status = $server->loadServerStatus();
+ $status = idx($status_map, $status, array());
+ } catch (Exception $ex) {
+ $status['icon'] = 'fa-times';
+ $status['label'] = pht('Connection Error');
+ $status['color'] = 'red';
+ }
+
+ $engine = $server->getEngine();
+
+ $type_icon = 'fa-search sky';
+ $type_tip = $server->getDisplayName();
+
+ $type_icon = id(new PHUIIconView())
+ ->setIcon($type_icon)
+ ->addSigil('has-tooltip')
+ ->setMetadata(
+ array(
+ 'tip' => $type_tip,
+ ));
+
+ $status_view = array(
+ id(new PHUIIconView())->setIcon("{$status['icon']} {$status['color']}"),
+ ' ',
+ $status['label'],
+ );
+
+ $rows[] = array(
+ array($type_icon, ' '.$type_tip),
+ $server->getProtocol(),
+ $server->getHost(),
+ $server->getPort(),
+ $status_view,
+ get_class($engine),
+ $this->checkicon($engine->isEnabled(), 'Enabled', 'Disabled'),
+ $this->checkicon($server->isWritable(), 'Writable', 'Read-only'),
+ $engine->getEnginePriority(),
+ );
+ }
+
+ $table = id(new AphrontTableView($rows))
+ ->setNoDataString(
+ pht('No search servers are configured.'))
+ ->setHeaders(
+ array(
+ pht('Type'),
+ pht('Protocol'),
+ pht('Host'),
+ pht('Port'),
+ pht('Status'),
+ pht('Engine'),
+ pht('Enabled'),
+ pht('Writable'),
+ pht('Priority'),
+ null,
+ ))
+ ->setColumnClasses(
+ array(
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 'wide',
+ ));
+
+ return $table;
+ }
+
+ private function checkicon($check, $true = 'Yes', $false = 'No') {
+ $icon = $check
+ ? 'fa-check green'
+ : 'fa-times red';
+ $label = $check
+ ? pht($true)
+ : pht($false);
+ $view = id(new PHUIIconView())
+ ->setIcon($icon)
+ ->addSigil('has-tooltip')
+ ->setMetadata(
+ array(
+ 'tip' => $label,
+ ));
+
+ return $view;
+ }
+}
diff --git a/src/applications/config/controller/PhabricatorConfigController.php b/src/applications/config/controller/PhabricatorConfigController.php
--- a/src/applications/config/controller/PhabricatorConfigController.php
+++ b/src/applications/config/controller/PhabricatorConfigController.php
@@ -42,8 +42,11 @@
pht('Notification Servers'), null, 'fa-bell-o');
$nav->addFilter('cluster/repositories/',
pht('Repository Servers'), null, 'fa-code');
+ $nav->addFilter('cluster/search/',
+ pht('Search Servers'), null, 'fa-search');
$nav->addLabel(pht('Modules'));
+
$modules = PhabricatorConfigModule::getAllModules();
foreach ($modules as $key => $module) {
$nav->addFilter('module/'.$key.'/',
diff --git a/src/applications/search/config/PhabricatorSearchConfigOptions.php b/src/applications/search/config/PhabricatorSearchConfigOptions.php
--- a/src/applications/search/config/PhabricatorSearchConfigOptions.php
+++ b/src/applications/search/config/PhabricatorSearchConfigOptions.php
@@ -20,7 +20,15 @@
}
public function getOptions() {
+ $servers_type = 'custom:PhabricatorClusterSearchConfigOptionType';
+ $servers_help = 'TODO';
+
return array(
+ $this->newOption('search.servers', $servers_type, array())
+ ->setLocked(true)
+ ->setSummary(
+ pht('Configure full-text search servers.'))
+ ->setDescription($servers_help),
$this->newOption('search.elastic.host', 'string', null)
->setLocked(true)
->setDescription(pht('Elastic Search host.'))
diff --git a/src/applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php b/src/applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php
--- a/src/applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php
+++ b/src/applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php
@@ -3,13 +3,25 @@
final class PhabricatorElasticFulltextStorageEngine
extends PhabricatorFulltextStorageEngine {
- private $uri;
+ private $ref;
private $index;
+ private $uri;
private $timeout;
- public function __construct() {
- $this->uri = PhabricatorEnv::getEnvConfig('search.elastic.host');
- $this->index = PhabricatorEnv::getEnvConfig('search.elastic.namespace');
+ public function setRef(PhabricatorElasticSearchServerRef $ref) {
+ $this->uri = (string)$ref->getURI();
+ $this->index = str_replace('/', '', $ref->getPath());
+ $this->version = (int)$ref->getVersion();
+
+ $this->timestampFieldKey = $this->version < 2
+ ? '_timestamp'
+ : 'lastModified';
+
+ $this->textFieldType = $this->version >= 5
+ ? 'text'
+ : 'string';
+
+ $this->enabled = true;
}
public function getEngineIdentifier() {
@@ -336,6 +348,7 @@
}
public function indexIsSane() {
+
if (!$this->indexExists()) {
return false;
}
diff --git a/src/infrastructure/cluster/PhabricatorClusterRef.php b/src/infrastructure/cluster/PhabricatorClusterRef.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/cluster/PhabricatorClusterRef.php
@@ -0,0 +1,69 @@
+<?php
+
+abstract class PhabricatorClusterRef
+ extends Phobject {
+
+ protected $disabled;
+ protected $host;
+ protected $port;
+
+ const STATUS_OKAY = 'okay';
+ const STATUS_FAIL = 'fail';
+ const STATUS_AUTH = 'auth';
+ const STATUS_REPLICATION_CLIENT = 'replication-client';
+
+ const KEY_REFS = 'cluster.refs';
+
+ public function setDisabled($is_disabled) {
+ $this->disabled = $is_disabled;
+ return $this;
+ }
+
+ public function getDisabled() {
+ return $this->disabled;
+ }
+
+ 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 static function getConnectionStatusMap() {
+ return array(
+ self::STATUS_OKAY => array(
+ 'icon' => 'fa-exchange',
+ 'color' => 'green',
+ 'label' => pht('Okay'),
+ ),
+ self::STATUS_FAIL => array(
+ 'icon' => 'fa-times',
+ 'color' => 'red',
+ 'label' => pht('Failed'),
+ ),
+ self::STATUS_AUTH => array(
+ 'icon' => 'fa-key',
+ 'color' => 'red',
+ 'label' => pht('Invalid Credentials'),
+ ),
+ self::STATUS_REPLICATION_CLIENT => array(
+ 'icon' => 'fa-eye-slash',
+ 'color' => 'yellow',
+ 'label' => pht('Missing Permission'),
+ ),
+ );
+ }
+
+}
diff --git a/src/infrastructure/cluster/PhabricatorClusterSearchConfigOptionType.php b/src/infrastructure/cluster/PhabricatorClusterSearchConfigOptionType.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/cluster/PhabricatorClusterSearchConfigOptionType.php
@@ -0,0 +1,49 @@
+<?php
+
+final class PhabricatorClusterSearchConfigOptionType
+ extends PhabricatorConfigJSONOptionType {
+
+ public function validateOption(PhabricatorConfigOption $option, $value) {
+ if (!is_array($value)) {
+ throw new Exception(
+ pht(
+ 'Search cluster configuration is not valid: value must be a '.
+ 'list of search hosts.'));
+ }
+
+ foreach ($value as $index => $spec) {
+ if (!is_array($spec)) {
+ throw new Exception(
+ pht(
+ 'Search cluster configuration is not valid: each entry in the '.
+ 'list must be a dictionary describing a search host, but '.
+ 'the value with index "%s" is not a dictionary.',
+ $index));
+ }
+ }
+
+ $map = array();
+ foreach ($value as $index => $spec) {
+ try {
+ PhutilTypeSpec::checkMap(
+ $spec,
+ array(
+ 'type' => 'string',
+ 'host' => 'string',
+ 'port' => 'optional int',
+ 'path' => 'optional string',
+ 'protocol' => 'optional string',
+ 'disabled' => 'optional bool',
+ 'version' => 'optional int',
+ ));
+ } catch (Exception $ex) {
+ throw new Exception(
+ pht(
+ 'Search cluster configuration has an invalid host '.
+ 'specification (at index "%s"): %s.',
+ $index,
+ $ex->getMessage()));
+ }
+ }
+ }
+}
diff --git a/src/infrastructure/cluster/PhabricatorClusterSearchRef.php b/src/infrastructure/cluster/PhabricatorClusterSearchRef.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/cluster/PhabricatorClusterSearchRef.php
@@ -0,0 +1,91 @@
+<?php
+
+abstract class PhabricatorClusterSearchRef
+ extends PhabricatorClusterRef {
+
+ const KEY_REFS = 'cluster.search.refs';
+ const KEY_HEALTH = 'cluster.search.health';
+
+ protected $writable = true;
+
+ public function isWritable() {
+ return $this->writable;
+ }
+ public function setWritable($value) {
+ $this->writable = $value;
+ return $this;
+ }
+
+ 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() {
+ $builtin_ref = new PhabricatorMysqlSearchServerRef();
+ $refs = array($builtin_ref);
+ // try to load custom fulltext search service configuration.
+ $configs = PhabricatorEnv::getEnvConfigIfExists('search.servers');
+ if (!$configs) {
+ // if nothing is configured, just return a reference to the built-in
+ // fulltext search.
+ return $refs;
+ }
+
+ $types = id(new PhutilClassMapQuery())
+ ->setAncestorClass(__CLASS__)
+ ->setUniqueMethod('getEngineIdentifier')
+ ->execute();
+
+ foreach ($configs as $config) {
+ if (!isset($types[$config['type']])) {
+ throw new Exception(pht('configured search server type is invalid %s',
+ $config['type']));
+ }
+ $type = $types[$config['type']];
+ if ($config['type'] == 'mysql') {
+ // if there is a config for mysql, then it overrides the built-in ref
+ $ref = $builtin_ref;
+ } else {
+ // otherwise it's a custom type, clone the prototype ref
+ $ref = @id(clone($type));
+ $refs[] = $ref;
+ }
+
+ foreach ($config as $key => $val) {
+ $setter = 'set'.ucfirst($key);
+ if (method_exists($ref, $setter)) {
+ call_user_func(array($ref, $setter), $val);
+ }
+ }
+ $ref->initEngine();
+ }
+
+ return $refs;
+ }
+
+ public static function getEnabledServers() {
+ $servers = self::getLiveServers();
+
+ foreach ($servers as $key => $server) {
+ if ($server->getDisabled()) {
+ unset($servers[$key]);
+ }
+ }
+
+ return array_values($servers);
+ }
+
+ public function initEngine() {}
+
+ abstract public function getEngine();
+ abstract public function loadServerStatus();
+
+}
diff --git a/src/infrastructure/cluster/PhabricatorDatabaseHealthRecord.php b/src/infrastructure/cluster/PhabricatorDatabaseHealthRecord.php
--- a/src/infrastructure/cluster/PhabricatorDatabaseHealthRecord.php
+++ b/src/infrastructure/cluster/PhabricatorDatabaseHealthRecord.php
@@ -1,6 +1,6 @@
<?php
-final class PhabricatorDatabaseHealthRecord
+class PhabricatorDatabaseHealthRecord
extends Phobject {
private $ref;
@@ -158,8 +158,9 @@
$host = $ref->getHost();
$port = $ref->getPort();
+ $key = $ref::KEY_HEALTH;
- return "cluster.db.health({$host}, {$port})";
+ return "{$key}({$host}, {$port})";
}
private function readHealthRecord() {
diff --git a/src/infrastructure/cluster/PhabricatorDatabaseRef.php b/src/infrastructure/cluster/PhabricatorDatabaseRef.php
--- a/src/infrastructure/cluster/PhabricatorDatabaseRef.php
+++ b/src/infrastructure/cluster/PhabricatorDatabaseRef.php
@@ -1,7 +1,7 @@
<?php
final class PhabricatorDatabaseRef
- extends Phobject {
+ extends PhabricatorClusterRef {
const STATUS_OKAY = 'okay';
const STATUS_FAIL = 'fail';
@@ -16,12 +16,10 @@
const KEY_REFS = 'cluster.db.refs';
const KEY_INDIVIDUAL = 'cluster.db.individual';
+ const KEY_HEALTH = 'cluster.db.health';
- private $host;
- private $port;
private $user;
private $pass;
- private $disabled;
private $isMaster;
private $isIndividual;
@@ -232,17 +230,8 @@
}
public static function getConnectionStatusMap() {
- return array(
- self::STATUS_OKAY => array(
- 'icon' => 'fa-exchange',
- 'color' => 'green',
- 'label' => pht('Okay'),
- ),
- self::STATUS_FAIL => array(
- 'icon' => 'fa-times',
- 'color' => 'red',
- 'label' => pht('Failed'),
- ),
+ $map = parent::getConnectionStatusMap();
+ return $map + array(
self::STATUS_AUTH => array(
'icon' => 'fa-key',
'color' => 'red',
diff --git a/src/infrastructure/cluster/PhabricatorElasticSearchServerRef.php b/src/infrastructure/cluster/PhabricatorElasticSearchServerRef.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/cluster/PhabricatorElasticSearchServerRef.php
@@ -0,0 +1,87 @@
+<?php
+
+final class PhabricatorElasticSearchServerRef
+ extends PhabricatorClusterSearchRef {
+
+ private $engine;
+ private $version;
+ private $path;
+ private $protocol;
+ protected $port;
+
+ const KEY_REFS = 'search.elastic.refs';
+
+ public function __construct() {
+ $this->engine = new PhabricatorElasticFulltextStorageEngine();
+ }
+
+ public function getDisplayName() {
+ return 'ElasticSearch';
+ }
+
+ 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 setVersion($version) {
+ $this->version = $version;
+ return $this;
+ }
+
+ public function getVersion() {
+ return $this->version;
+ }
+
+ public function getPort() {
+ return $this->port;
+ }
+ public function setPort($value) {
+ $this->port = $value;
+ return $this;
+ }
+
+ 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);
+
+ return $uri;
+ }
+
+ public function initEngine() {
+ $this->engine->setRef($this);
+ }
+
+ public function getEngineIdentifier() {
+ return $this->engine->getEngineIdentifier();
+ }
+
+ public function getEngine() {
+ return $this->engine;
+ }
+
+ public function loadServerStatus() {
+ $status = $this->getEngine()->indexIsSane()
+ ? 'okay'
+ : 'fail';
+ return $status;
+ }
+
+}
diff --git a/src/infrastructure/cluster/PhabricatorMysqlSearchServerRef.php b/src/infrastructure/cluster/PhabricatorMysqlSearchServerRef.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/cluster/PhabricatorMysqlSearchServerRef.php
@@ -0,0 +1,35 @@
+<?php
+
+final class PhabricatorMysqlSearchServerRef
+ extends PhabricatorClusterSearchRef {
+
+ private $engine;
+
+ public function __construct() {
+ $this->engine = new PhabricatorMySQLFulltextStorageEngine();
+ }
+
+ public function getDisplayName() {
+ return 'MySQL';
+ }
+
+ public function getEngineIdentifier() {
+ return $this->engine->getEngineIdentifier();
+ }
+
+ public function getEngine() {
+ return $this->engine;
+ }
+
+ public function getProtocol() {
+ return 'mysql';
+ }
+
+ public function loadServerStatus() {
+ PhabricatorDatabaseRef::queryAll();
+ $ref = PhabricatorDatabaseRef::getMasterDatabaseRefForApplication('search');
+ $status = $ref->getConnectionStatus();
+ return $status;
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 19, 9:34 PM (3 d, 5 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7797189
Default Alt Text
D17384.id41801.diff (25 KB)
Attached To
Mode
D17384: Support multiple fulltext search clusters with 'cluster.search' config
Attached
Detach File
Event Timeline
Log In to Comment