mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 06:20:56 +01:00
Modernize search engine selection
Summary: Remove the `PhabricatorDefaultSearchEngineSelector` class. This is quite similar to D12053. Test Plan: Went to `/view/PhabricatorSearchApplication/` and saw the storage engine configuration. Set `search.elastic.host` and saw the highlighted storage engine change. Reviewers: #blessed_reviewers, epriestley Reviewed By: #blessed_reviewers, epriestley Subscribers: Korvin, epriestley Differential Revision: https://secure.phabricator.com/D12670
This commit is contained in:
parent
2f80c01236
commit
16a8ed72bd
16 changed files with 263 additions and 78 deletions
|
@ -1744,7 +1744,6 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorDatabaseSetupCheck' => 'applications/config/check/PhabricatorDatabaseSetupCheck.php',
|
'PhabricatorDatabaseSetupCheck' => 'applications/config/check/PhabricatorDatabaseSetupCheck.php',
|
||||||
'PhabricatorDateTimeSettingsPanel' => 'applications/settings/panel/PhabricatorDateTimeSettingsPanel.php',
|
'PhabricatorDateTimeSettingsPanel' => 'applications/settings/panel/PhabricatorDateTimeSettingsPanel.php',
|
||||||
'PhabricatorDebugController' => 'applications/system/controller/PhabricatorDebugController.php',
|
'PhabricatorDebugController' => 'applications/system/controller/PhabricatorDebugController.php',
|
||||||
'PhabricatorDefaultSearchEngineSelector' => 'applications/search/selector/PhabricatorDefaultSearchEngineSelector.php',
|
|
||||||
'PhabricatorDestructibleInterface' => 'applications/system/interface/PhabricatorDestructibleInterface.php',
|
'PhabricatorDestructibleInterface' => 'applications/system/interface/PhabricatorDestructibleInterface.php',
|
||||||
'PhabricatorDestructionEngine' => 'applications/system/engine/PhabricatorDestructionEngine.php',
|
'PhabricatorDestructionEngine' => 'applications/system/engine/PhabricatorDestructionEngine.php',
|
||||||
'PhabricatorDeveloperConfigOptions' => 'applications/config/option/PhabricatorDeveloperConfigOptions.php',
|
'PhabricatorDeveloperConfigOptions' => 'applications/config/option/PhabricatorDeveloperConfigOptions.php',
|
||||||
|
@ -1776,7 +1775,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorEdgeType' => 'infrastructure/edges/type/PhabricatorEdgeType.php',
|
'PhabricatorEdgeType' => 'infrastructure/edges/type/PhabricatorEdgeType.php',
|
||||||
'PhabricatorEditor' => 'infrastructure/PhabricatorEditor.php',
|
'PhabricatorEditor' => 'infrastructure/PhabricatorEditor.php',
|
||||||
'PhabricatorElasticSearchEngine' => 'applications/search/engine/PhabricatorElasticSearchEngine.php',
|
'PhabricatorElasticSearchEngine' => 'applications/search/engine/PhabricatorElasticSearchEngine.php',
|
||||||
'PhabricatorElasticSetupCheck' => 'applications/config/check/PhabricatorElasticSetupCheck.php',
|
'PhabricatorElasticSearchSetupCheck' => 'applications/config/check/PhabricatorElasticSearchSetupCheck.php',
|
||||||
'PhabricatorEmailAddressesSettingsPanel' => 'applications/settings/panel/PhabricatorEmailAddressesSettingsPanel.php',
|
'PhabricatorEmailAddressesSettingsPanel' => 'applications/settings/panel/PhabricatorEmailAddressesSettingsPanel.php',
|
||||||
'PhabricatorEmailFormatSettingsPanel' => 'applications/settings/panel/PhabricatorEmailFormatSettingsPanel.php',
|
'PhabricatorEmailFormatSettingsPanel' => 'applications/settings/panel/PhabricatorEmailFormatSettingsPanel.php',
|
||||||
'PhabricatorEmailLoginController' => 'applications/auth/controller/PhabricatorEmailLoginController.php',
|
'PhabricatorEmailLoginController' => 'applications/auth/controller/PhabricatorEmailLoginController.php',
|
||||||
|
@ -2501,6 +2500,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSearchAbstractDocument' => 'applications/search/index/PhabricatorSearchAbstractDocument.php',
|
'PhabricatorSearchAbstractDocument' => 'applications/search/index/PhabricatorSearchAbstractDocument.php',
|
||||||
'PhabricatorSearchApplication' => 'applications/search/application/PhabricatorSearchApplication.php',
|
'PhabricatorSearchApplication' => 'applications/search/application/PhabricatorSearchApplication.php',
|
||||||
'PhabricatorSearchApplicationSearchEngine' => 'applications/search/query/PhabricatorSearchApplicationSearchEngine.php',
|
'PhabricatorSearchApplicationSearchEngine' => 'applications/search/query/PhabricatorSearchApplicationSearchEngine.php',
|
||||||
|
'PhabricatorSearchApplicationStorageEnginePanel' => 'applications/search/applicationpanel/PhabricatorSearchApplicationStorageEnginePanel.php',
|
||||||
'PhabricatorSearchAttachController' => 'applications/search/controller/PhabricatorSearchAttachController.php',
|
'PhabricatorSearchAttachController' => 'applications/search/controller/PhabricatorSearchAttachController.php',
|
||||||
'PhabricatorSearchBaseController' => 'applications/search/controller/PhabricatorSearchBaseController.php',
|
'PhabricatorSearchBaseController' => 'applications/search/controller/PhabricatorSearchBaseController.php',
|
||||||
'PhabricatorSearchConfigOptions' => 'applications/search/config/PhabricatorSearchConfigOptions.php',
|
'PhabricatorSearchConfigOptions' => 'applications/search/config/PhabricatorSearchConfigOptions.php',
|
||||||
|
@ -2516,7 +2516,6 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSearchDocumentTypeDatasource' => 'applications/search/typeahead/PhabricatorSearchDocumentTypeDatasource.php',
|
'PhabricatorSearchDocumentTypeDatasource' => 'applications/search/typeahead/PhabricatorSearchDocumentTypeDatasource.php',
|
||||||
'PhabricatorSearchEditController' => 'applications/search/controller/PhabricatorSearchEditController.php',
|
'PhabricatorSearchEditController' => 'applications/search/controller/PhabricatorSearchEditController.php',
|
||||||
'PhabricatorSearchEngine' => 'applications/search/engine/PhabricatorSearchEngine.php',
|
'PhabricatorSearchEngine' => 'applications/search/engine/PhabricatorSearchEngine.php',
|
||||||
'PhabricatorSearchEngineSelector' => 'applications/search/selector/PhabricatorSearchEngineSelector.php',
|
|
||||||
'PhabricatorSearchField' => 'applications/search/constants/PhabricatorSearchField.php',
|
'PhabricatorSearchField' => 'applications/search/constants/PhabricatorSearchField.php',
|
||||||
'PhabricatorSearchHovercardController' => 'applications/search/controller/PhabricatorSearchHovercardController.php',
|
'PhabricatorSearchHovercardController' => 'applications/search/controller/PhabricatorSearchHovercardController.php',
|
||||||
'PhabricatorSearchIndexer' => 'applications/search/index/PhabricatorSearchIndexer.php',
|
'PhabricatorSearchIndexer' => 'applications/search/index/PhabricatorSearchIndexer.php',
|
||||||
|
@ -5140,7 +5139,6 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorDatabaseSetupCheck' => 'PhabricatorSetupCheck',
|
'PhabricatorDatabaseSetupCheck' => 'PhabricatorSetupCheck',
|
||||||
'PhabricatorDateTimeSettingsPanel' => 'PhabricatorSettingsPanel',
|
'PhabricatorDateTimeSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorDebugController' => 'PhabricatorController',
|
'PhabricatorDebugController' => 'PhabricatorController',
|
||||||
'PhabricatorDefaultSearchEngineSelector' => 'PhabricatorSearchEngineSelector',
|
|
||||||
'PhabricatorDestructionEngine' => 'Phobject',
|
'PhabricatorDestructionEngine' => 'Phobject',
|
||||||
'PhabricatorDeveloperConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorDeveloperConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
'PhabricatorDeveloperPreferencesSettingsPanel' => 'PhabricatorSettingsPanel',
|
'PhabricatorDeveloperPreferencesSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||||
|
@ -5169,7 +5167,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorEdgeType' => 'Phobject',
|
'PhabricatorEdgeType' => 'Phobject',
|
||||||
'PhabricatorEditor' => 'Phobject',
|
'PhabricatorEditor' => 'Phobject',
|
||||||
'PhabricatorElasticSearchEngine' => 'PhabricatorSearchEngine',
|
'PhabricatorElasticSearchEngine' => 'PhabricatorSearchEngine',
|
||||||
'PhabricatorElasticSetupCheck' => 'PhabricatorSetupCheck',
|
'PhabricatorElasticSearchSetupCheck' => 'PhabricatorSetupCheck',
|
||||||
'PhabricatorEmailAddressesSettingsPanel' => 'PhabricatorSettingsPanel',
|
'PhabricatorEmailAddressesSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorEmailFormatSettingsPanel' => 'PhabricatorSettingsPanel',
|
'PhabricatorEmailFormatSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorEmailLoginController' => 'PhabricatorAuthController',
|
'PhabricatorEmailLoginController' => 'PhabricatorAuthController',
|
||||||
|
@ -5973,6 +5971,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorScheduleTaskTriggerAction' => 'PhabricatorTriggerAction',
|
'PhabricatorScheduleTaskTriggerAction' => 'PhabricatorTriggerAction',
|
||||||
'PhabricatorSearchApplication' => 'PhabricatorApplication',
|
'PhabricatorSearchApplication' => 'PhabricatorApplication',
|
||||||
'PhabricatorSearchApplicationSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'PhabricatorSearchApplicationSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
|
'PhabricatorSearchApplicationStorageEnginePanel' => 'PhabricatorApplicationConfigurationPanel',
|
||||||
'PhabricatorSearchAttachController' => 'PhabricatorSearchBaseController',
|
'PhabricatorSearchAttachController' => 'PhabricatorSearchBaseController',
|
||||||
'PhabricatorSearchBaseController' => 'PhabricatorController',
|
'PhabricatorSearchBaseController' => 'PhabricatorController',
|
||||||
'PhabricatorSearchConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorSearchConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class PhabricatorElasticSetupCheck extends PhabricatorSetupCheck {
|
final class PhabricatorElasticSearchSetupCheck extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
public function getDefaultGroup() {
|
public function getDefaultGroup() {
|
||||||
return self::GROUP_OTHER;
|
return self::GROUP_OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function executeChecks() {
|
protected function executeChecks() {
|
||||||
if (PhabricatorDefaultSearchEngineSelector::shouldUseElasticSearch()) {
|
if ($this->shouldUseElasticSearchEngine()) {
|
||||||
$engine = PhabricatorSearchEngineSelector::newSelector()->newEngine();
|
$engine = new PhabricatorElasticSearchEngine();
|
||||||
|
|
||||||
if (!$engine->indexExists()) {
|
if (!$engine->indexExists()) {
|
||||||
$summary = pht(
|
$summary = pht(
|
||||||
'You enabled Elasticsearch but the index does not exist.');
|
'You enabled Elasticsearch but the index does not exist.');
|
||||||
|
@ -40,4 +41,10 @@ final class PhabricatorElasticSetupCheck extends PhabricatorSetupCheck {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function shouldUseElasticSearchEngine() {
|
||||||
|
$search_engine = PhabricatorSearchEngine::loadEngine();
|
||||||
|
return $search_engine instanceof PhabricatorElasticSearchEngine;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -252,6 +252,10 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
'style.monospace' => $monospace_reason,
|
'style.monospace' => $monospace_reason,
|
||||||
'style.monospace.windows' => $monospace_reason,
|
'style.monospace.windows' => $monospace_reason,
|
||||||
|
|
||||||
|
'search.engine-selector' => pht(
|
||||||
|
'Phabricator now automatically discovers available search engines '.
|
||||||
|
'at runtime.'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $ancient_config;
|
return $ancient_config;
|
||||||
|
|
|
@ -116,7 +116,8 @@ final class PhabricatorMySQLSetupCheck extends PhabricatorSetupCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
$stopword_file = self::loadRawConfigValue('ft_stopword_file');
|
$stopword_file = self::loadRawConfigValue('ft_stopword_file');
|
||||||
if (!PhabricatorDefaultSearchEngineSelector::shouldUseElasticSearch()) {
|
|
||||||
|
if ($this->shouldUseMySQLSearchEngine()) {
|
||||||
if ($stopword_file === null) {
|
if ($stopword_file === null) {
|
||||||
$summary = pht(
|
$summary = pht(
|
||||||
'Your version of MySQL does not support configuration of a '.
|
'Your version of MySQL does not support configuration of a '.
|
||||||
|
@ -190,7 +191,7 @@ final class PhabricatorMySQLSetupCheck extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
$min_len = self::loadRawConfigValue('ft_min_word_len');
|
$min_len = self::loadRawConfigValue('ft_min_word_len');
|
||||||
if ($min_len >= 4) {
|
if ($min_len >= 4) {
|
||||||
if (!PhabricatorDefaultSearchEngineSelector::shouldUseElasticSearch()) {
|
if ($this->shouldUseMySQLSearchEngine()) {
|
||||||
$namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace');
|
$namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace');
|
||||||
|
|
||||||
$summary = pht(
|
$summary = pht(
|
||||||
|
@ -235,8 +236,7 @@ final class PhabricatorMySQLSetupCheck extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
$bool_syntax = self::loadRawConfigValue('ft_boolean_syntax');
|
$bool_syntax = self::loadRawConfigValue('ft_boolean_syntax');
|
||||||
if ($bool_syntax != ' |-><()~*:""&^') {
|
if ($bool_syntax != ' |-><()~*:""&^') {
|
||||||
if (!PhabricatorDefaultSearchEngineSelector::shouldUseElasticSearch()) {
|
if ($this->shouldUseMySQLSearchEngine()) {
|
||||||
|
|
||||||
$summary = pht(
|
$summary = pht(
|
||||||
'MySQL is configured to search on fulltext indexes using "OR" by '.
|
'MySQL is configured to search on fulltext indexes using "OR" by '.
|
||||||
'default. Using "AND" is usually the desired behaviour.');
|
'default. Using "AND" is usually the desired behaviour.');
|
||||||
|
@ -340,4 +340,9 @@ final class PhabricatorMySQLSetupCheck extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function shouldUseMySQLSearchEngine() {
|
||||||
|
$search_engine = PhabricatorSearchEngine::loadEngine();
|
||||||
|
return $search_engine instanceof PhabricatorMySQLSearchEngine;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,6 @@ final class PhabricatorFilesApplicationStorageEnginePanel
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$table =
|
|
||||||
|
|
||||||
$table = id(new AphrontTableView($rows))
|
$table = id(new AphrontTableView($rows))
|
||||||
->setNoDataString(pht('No storage engines available.'))
|
->setNoDataString(pht('No storage engines available.'))
|
||||||
->setHeaders(
|
->setHeaders(
|
||||||
|
|
|
@ -563,7 +563,7 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
$fulltext_query->setParameter('types',
|
$fulltext_query->setParameter('types',
|
||||||
array(ManiphestTaskPHIDType::TYPECONST));
|
array(ManiphestTaskPHIDType::TYPECONST));
|
||||||
|
|
||||||
$engine = PhabricatorSearchEngineSelector::newSelector()->newEngine();
|
$engine = PhabricatorSearchEngine::loadEngine();
|
||||||
$fulltext_results = $engine->executeSearch($fulltext_query);
|
$fulltext_results = $engine->executeSearch($fulltext_query);
|
||||||
|
|
||||||
if (empty($fulltext_results)) {
|
if (empty($fulltext_results)) {
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSearchApplicationStorageEnginePanel
|
||||||
|
extends PhabricatorApplicationConfigurationPanel {
|
||||||
|
|
||||||
|
public function getPanelKey() {
|
||||||
|
return 'search';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldShowForApplication(
|
||||||
|
PhabricatorApplication $application) {
|
||||||
|
return $application instanceof PhabricatorSearchApplication;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildConfigurationPagePanel() {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$application = $this->getApplication();
|
||||||
|
|
||||||
|
$active_engine = PhabricatorSearchEngine::loadEngine();
|
||||||
|
$engines = PhabricatorSearchEngine::loadAllEngines();
|
||||||
|
|
||||||
|
$rows = array();
|
||||||
|
$rowc = array();
|
||||||
|
|
||||||
|
foreach ($engines as $key => $engine) {
|
||||||
|
try {
|
||||||
|
$index_exists = $engine->indexExists() ? pht('Yes') : pht('No');
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$index_exists = pht('N/A');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$index_is_sane = $engine->indexIsSane() ? pht('Yes') : pht('No');
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$index_is_sane = pht('N/A');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($engine == $active_engine) {
|
||||||
|
$rowc[] = 'highlighted';
|
||||||
|
} else {
|
||||||
|
$rowc[] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array(
|
||||||
|
$key,
|
||||||
|
get_class($engine),
|
||||||
|
$index_exists,
|
||||||
|
$index_is_sane,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = id(new AphrontTableView($rows))
|
||||||
|
->setNoDataString(pht('No search engines available.'))
|
||||||
|
->setHeaders(
|
||||||
|
array(
|
||||||
|
pht('Key'),
|
||||||
|
pht('Class'),
|
||||||
|
pht('Index Exists'),
|
||||||
|
pht('Index Is Sane'),
|
||||||
|
))
|
||||||
|
->setRowClasses($rowc)
|
||||||
|
->setColumnClasses(
|
||||||
|
array(
|
||||||
|
'',
|
||||||
|
'wide',
|
||||||
|
'',
|
||||||
|
));
|
||||||
|
|
||||||
|
$box = id(new PHUIObjectBoxView())
|
||||||
|
->setHeaderText(pht('Search Engines'))
|
||||||
|
->appendChild($table);
|
||||||
|
|
||||||
|
return $box;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handlePanelRequest(
|
||||||
|
AphrontRequest $request,
|
||||||
|
PhabricatorController $controller) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,21 +21,6 @@ final class PhabricatorSearchConfigOptions
|
||||||
|
|
||||||
public function getOptions() {
|
public function getOptions() {
|
||||||
return array(
|
return array(
|
||||||
$this->newOption(
|
|
||||||
'search.engine-selector',
|
|
||||||
'class',
|
|
||||||
'PhabricatorDefaultSearchEngineSelector')
|
|
||||||
->setBaseClass('PhabricatorSearchEngineSelector')
|
|
||||||
->setSummary(pht('Search engine selector.'))
|
|
||||||
->setDescription(
|
|
||||||
pht(
|
|
||||||
'Phabricator uses a search engine selector to choose which '.
|
|
||||||
'search engine to use when indexing and reconstructing '.
|
|
||||||
'documents, and when executing queries. You can override the '.
|
|
||||||
'engine selector to provide a new selector class which can '.
|
|
||||||
'select some custom engine you implement, if you want to store '.
|
|
||||||
'your documents in some search engine which does not have '.
|
|
||||||
'default support.')),
|
|
||||||
$this->newOption('search.elastic.host', 'string', null)
|
$this->newOption('search.elastic.host', 'string', null)
|
||||||
->setLocked(true)
|
->setLocked(true)
|
||||||
->setDescription(pht('Elastic Search host.'))
|
->setDescription(pht('Elastic Search host.'))
|
||||||
|
|
|
@ -1,13 +1,31 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class PhabricatorElasticSearchEngine extends PhabricatorSearchEngine {
|
final class PhabricatorElasticSearchEngine extends PhabricatorSearchEngine {
|
||||||
|
|
||||||
private $uri;
|
private $uri;
|
||||||
private $index;
|
private $index;
|
||||||
private $timeout;
|
private $timeout;
|
||||||
|
|
||||||
public function __construct($uri, $index) {
|
public function getEngineIdentifier() {
|
||||||
|
return 'elasticsearch';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEnginePriority() {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEnabled() {
|
||||||
|
return (bool)PhabricatorEnv::getEnvConfig('search.elastic.host');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setURI($uri) {
|
||||||
$this->uri = $uri;
|
$this->uri = $uri;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIndex($index) {
|
||||||
$this->index = $index;
|
$this->index = $index;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTimeout($timeout) {
|
public function setTimeout($timeout) {
|
||||||
|
@ -15,6 +33,14 @@ final class PhabricatorElasticSearchEngine extends PhabricatorSearchEngine {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getURI() {
|
||||||
|
return $this->uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIndex() {
|
||||||
|
return $this->index;
|
||||||
|
}
|
||||||
|
|
||||||
public function getTimeout() {
|
public function getTimeout() {
|
||||||
return $this->timeout;
|
return $this->timeout;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +125,7 @@ final class PhabricatorElasticSearchEngine extends PhabricatorSearchEngine {
|
||||||
$spec[] = array(
|
$spec[] = array(
|
||||||
'simple_query_string' => array(
|
'simple_query_string' => array(
|
||||||
'query' => $query->getParameter('query'),
|
'query' => $query->getParameter('query'),
|
||||||
'fields' => array( 'field.corpus' ),
|
'fields' => array('field.corpus'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,24 @@
|
||||||
|
|
||||||
final class PhabricatorMySQLSearchEngine extends PhabricatorSearchEngine {
|
final class PhabricatorMySQLSearchEngine extends PhabricatorSearchEngine {
|
||||||
|
|
||||||
|
public function getEngineIdentifier() {
|
||||||
|
return 'mysql';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEnginePriority() {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function reindexAbstractDocument(
|
public function reindexAbstractDocument(
|
||||||
PhabricatorSearchAbstractDocument $doc) {
|
PhabricatorSearchAbstractDocument $doc) {
|
||||||
|
|
||||||
$phid = $doc->getPHID();
|
$phid = $doc->getPHID();
|
||||||
if (!$phid) {
|
if (!$phid) {
|
||||||
throw new Exception('Document has no PHID!');
|
throw new Exception(pht('Document has no PHID!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$store = new PhabricatorSearchDocument();
|
$store = new PhabricatorSearchDocument();
|
||||||
|
@ -31,7 +43,7 @@ final class PhabricatorMySQLSearchEngine extends PhabricatorSearchEngine {
|
||||||
queryfx(
|
queryfx(
|
||||||
$conn_w,
|
$conn_w,
|
||||||
'INSERT INTO %T (phid, phidType, field, auxPHID, corpus) '.
|
'INSERT INTO %T (phid, phidType, field, auxPHID, corpus) '.
|
||||||
' VALUES (%s, %s, %s, %ns, %s)',
|
'VALUES (%s, %s, %s, %ns, %s)',
|
||||||
$field_dao->getTableName(),
|
$field_dao->getTableName(),
|
||||||
$phid,
|
$phid,
|
||||||
$doc->getDocumentType(),
|
$doc->getDocumentType(),
|
||||||
|
@ -63,9 +75,9 @@ final class PhabricatorMySQLSearchEngine extends PhabricatorSearchEngine {
|
||||||
if ($sql) {
|
if ($sql) {
|
||||||
queryfx(
|
queryfx(
|
||||||
$conn_w,
|
$conn_w,
|
||||||
'INSERT INTO %T'.
|
'INSERT INTO %T '.
|
||||||
' (phid, relatedPHID, relation, relatedType, relatedTime) '.
|
'(phid, relatedPHID, relation, relatedType, relatedTime) '.
|
||||||
' VALUES %Q',
|
'VALUES %Q',
|
||||||
$rship_dao->getTableName(),
|
$rship_dao->getTableName(),
|
||||||
implode(', ', $sql));
|
implode(', ', $sql));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for Phabricator search engine providers. Each engine must offer
|
* Base class for Phabricator search engine providers. Each engine must offer
|
||||||
* three capabilities: indexing, searching, and reconstruction (this can be
|
* three capabilities: indexing, searching, and reconstruction (this can be
|
||||||
|
@ -8,6 +7,49 @@
|
||||||
*/
|
*/
|
||||||
abstract class PhabricatorSearchEngine {
|
abstract class PhabricatorSearchEngine {
|
||||||
|
|
||||||
|
/* -( Engine Metadata )---------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a unique, nonempty string which identifies this storage engine.
|
||||||
|
*
|
||||||
|
* @return string Unique string for this engine, max length 32.
|
||||||
|
* @task meta
|
||||||
|
*/
|
||||||
|
abstract public function getEngineIdentifier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prioritize this engine relative to other engines.
|
||||||
|
*
|
||||||
|
* Engines with a smaller priority number get an opportunity to write files
|
||||||
|
* first. Generally, lower-latency filestores should have lower priority
|
||||||
|
* numbers, and higher-latency filestores should have higher priority
|
||||||
|
* numbers. Setting priority to approximately the number of milliseconds of
|
||||||
|
* read latency will generally produce reasonable results.
|
||||||
|
*
|
||||||
|
* In conjunction with filesize limits, the goal is to store small files like
|
||||||
|
* profile images, thumbnails, and text snippets in lower-latency engines,
|
||||||
|
* and store large files in higher-capacity engines.
|
||||||
|
*
|
||||||
|
* @return float Engine priority.
|
||||||
|
* @task meta
|
||||||
|
*/
|
||||||
|
abstract public function getEnginePriority();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return `true` if the engine is currently writable.
|
||||||
|
*
|
||||||
|
* Engines that are disabled or missing configuration should return `false`
|
||||||
|
* to prevent new writes. If writes were made with this engine in the past,
|
||||||
|
* the application may still try to perform reads.
|
||||||
|
*
|
||||||
|
* @return bool True if this engine can support new writes.
|
||||||
|
* @task meta
|
||||||
|
*/
|
||||||
|
abstract public function isEnabled();
|
||||||
|
|
||||||
|
|
||||||
|
/* -( Managing Documents )------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the index for an abstract document.
|
* Update the index for an abstract document.
|
||||||
*
|
*
|
||||||
|
@ -17,7 +59,6 @@ abstract class PhabricatorSearchEngine {
|
||||||
abstract public function reindexAbstractDocument(
|
abstract public function reindexAbstractDocument(
|
||||||
PhabricatorSearchAbstractDocument $document);
|
PhabricatorSearchAbstractDocument $document);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reconstruct the document for a given PHID. This is used for debugging
|
* Reconstruct the document for a given PHID. This is used for debugging
|
||||||
* and does not need to be perfect if it is unreasonable to implement it.
|
* and does not need to be perfect if it is unreasonable to implement it.
|
||||||
|
@ -27,7 +68,6 @@ abstract class PhabricatorSearchEngine {
|
||||||
*/
|
*/
|
||||||
abstract public function reconstructDocument($phid);
|
abstract public function reconstructDocument($phid);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a search query.
|
* Execute a search query.
|
||||||
*
|
*
|
||||||
|
@ -53,9 +93,70 @@ abstract class PhabricatorSearchEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do any sort of setup for the search index
|
* Do any sort of setup for the search index.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function initIndex() {}
|
public function initIndex() {}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( Loading Storage Engines )-------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task load
|
||||||
|
*/
|
||||||
|
public static function loadAllEngines() {
|
||||||
|
static $engines;
|
||||||
|
|
||||||
|
if ($engines === null) {
|
||||||
|
$objects = id(new PhutilSymbolLoader())
|
||||||
|
->setAncestorClass(__CLASS__)
|
||||||
|
->loadObjects();
|
||||||
|
|
||||||
|
$map = array();
|
||||||
|
foreach ($objects as $engine) {
|
||||||
|
$key = $engine->getEngineIdentifier();
|
||||||
|
if (empty($map[$key])) {
|
||||||
|
$map[$key] = $engine;
|
||||||
|
} else {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Search engines "%s" and "%s" have the same engine identifier '.
|
||||||
|
'"%s". Each storage engine must have a unique identifier.',
|
||||||
|
get_class($engine),
|
||||||
|
get_class($map[$key]),
|
||||||
|
$key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$map = msort($map, 'getEnginePriority');
|
||||||
|
|
||||||
|
$engines = $map;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $engines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task load
|
||||||
|
*/
|
||||||
|
public static function loadActiveEngines() {
|
||||||
|
$engines = self::loadAllEngines();
|
||||||
|
|
||||||
|
$active = array();
|
||||||
|
foreach ($engines as $key => $engine) {
|
||||||
|
if (!$engine->isEnabled()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$active[$key] = $engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadEngine() {
|
||||||
|
return head(self::loadActiveEngines());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ abstract class PhabricatorSearchDocumentIndexer extends Phobject {
|
||||||
$this->indexProjects($document, $object);
|
$this->indexProjects($document, $object);
|
||||||
}
|
}
|
||||||
|
|
||||||
$engine = PhabricatorSearchEngineSelector::newSelector()->newEngine();
|
$engine = PhabricatorSearchEngine::loadEngine();
|
||||||
try {
|
try {
|
||||||
$engine->reindexAbstractDocument($document);
|
$engine->reindexAbstractDocument($document);
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
|
|
|
@ -13,7 +13,7 @@ final class PhabricatorSearchManagementInitWorkflow
|
||||||
public function execute(PhutilArgumentParser $args) {
|
public function execute(PhutilArgumentParser $args) {
|
||||||
$console = PhutilConsole::getConsole();
|
$console = PhutilConsole::getConsole();
|
||||||
|
|
||||||
$engine = PhabricatorSearchEngineSelector::newSelector()->newEngine();
|
$engine = PhabricatorSearchEngine::loadEngine();
|
||||||
|
|
||||||
$work_done = false;
|
$work_done = false;
|
||||||
if (!$engine->indexExists()) {
|
if (!$engine->indexExists()) {
|
||||||
|
|
|
@ -74,7 +74,7 @@ final class PhabricatorSearchDocumentQuery
|
||||||
->setParameter('offset', $this->getOffset())
|
->setParameter('offset', $this->getOffset())
|
||||||
->setParameter('limit', $this->getRawResultLimit());
|
->setParameter('limit', $this->getRawResultLimit());
|
||||||
|
|
||||||
$engine = PhabricatorSearchEngineSelector::newSelector()->newEngine();
|
$engine = PhabricatorSearchEngine::loadEngine();
|
||||||
|
|
||||||
return $engine->executeSearch($query);
|
return $engine->executeSearch($query);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
final class PhabricatorDefaultSearchEngineSelector
|
|
||||||
extends PhabricatorSearchEngineSelector {
|
|
||||||
|
|
||||||
public function newEngine() {
|
|
||||||
if (self::shouldUseElasticSearch()) {
|
|
||||||
$elastic_host = PhabricatorEnv::getEnvConfig('search.elastic.host');
|
|
||||||
$elastic_index = PhabricatorEnv::getEnvConfig('search.elastic.namespace');
|
|
||||||
return new PhabricatorElasticSearchEngine($elastic_host, $elastic_index);
|
|
||||||
}
|
|
||||||
return new PhabricatorMySQLSearchEngine();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function shouldUseElasticSearch() {
|
|
||||||
return (bool)PhabricatorEnv::getEnvConfig('search.elastic.host');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
abstract class PhabricatorSearchEngineSelector {
|
|
||||||
|
|
||||||
final public function __construct() {
|
|
||||||
// <empty>
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract public function newEngine();
|
|
||||||
|
|
||||||
final public static function newSelector() {
|
|
||||||
return PhabricatorEnv::newObjectFromConfig('search.engine-selector');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in a new issue