mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-18 11:30:55 +01:00
Add "Manual Activities", to tell administrators to rebuild the search index
Summary: Ref T11922. After updating to HEAD of `master`, you need to manually rebuild the index. We don't do this during `bin/storage upgrade` because it can take a very long time (`secure.phabricator.com` took roughly an hour) and can happen while Phabricator is running. However, if we don't warn users about this they'll just get a broken index unless they go read the changelog (or file an issue, then we tell them to go read the changelog). This adds a very simple table for notes to administrators so we can write a "you need to go rebuild the index" note, then adds one. Administrators clear the note by completing the activity and running `bin/config done reindex`. This isn't automatic because there are various strategies you can use to approach the issue, which I'll discuss in greater detail in the linked documentation. Also, fix an issue where `bin/storage upgrade --apply <patch>` could try to re-mark an already-applied patch as applied. Test Plan: - Ran storage ugrades. - Got instructions to rebuild search index. - Cleared instructions with `bin/config done reindex`. Reviewers: chad Reviewed By: chad Subscribers: avivey Maniphest Tasks: T11922 Differential Revision: https://secure.phabricator.com/D16965
This commit is contained in:
parent
eeb80ba96b
commit
29a3cd5121
7 changed files with 208 additions and 1 deletions
6
resources/sql/autopatches/20161130.search.01.manual.sql
Normal file
6
resources/sql/autopatches/20161130.search.01.manual.sql
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
CREATE TABLE {$NAMESPACE}_config.config_manualactivity (
|
||||||
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
activityType VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||||
|
parameters LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
|
||||||
|
UNIQUE KEY `key_type` (activityType)
|
||||||
|
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
26
resources/sql/autopatches/20161130.search.02.rebuild.php
Normal file
26
resources/sql/autopatches/20161130.search.02.rebuild.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$search_engine = PhabricatorFulltextStorageEngine::loadEngine();
|
||||||
|
$use_mysql = ($search_engine instanceof PhabricatorMySQLFulltextStorageEngine);
|
||||||
|
|
||||||
|
if ($use_mysql) {
|
||||||
|
$field = new PhabricatorSearchDocumentField();
|
||||||
|
$conn = $field->establishConnection('r');
|
||||||
|
|
||||||
|
// We're only going to require this if the index isn't empty: if you're on a
|
||||||
|
// fresh install, you don't have to do anything.
|
||||||
|
$any_documents = queryfx_one(
|
||||||
|
$conn,
|
||||||
|
'SELECT * FROM %T LIMIT 1',
|
||||||
|
$field->getTableName());
|
||||||
|
|
||||||
|
if ($any_documents) {
|
||||||
|
try {
|
||||||
|
id(new PhabricatorConfigManualActivity())
|
||||||
|
->setActivityType(PhabricatorConfigManualActivity::TYPE_REINDEX)
|
||||||
|
->save();
|
||||||
|
} catch (AphrontDuplicateKeyQueryException $ex) {
|
||||||
|
// If we've already noted that this activity is required, just move on.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2272,11 +2272,13 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php',
|
'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php',
|
||||||
'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php',
|
'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php',
|
||||||
'PhabricatorConfigManagementDeleteWorkflow' => 'applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php',
|
'PhabricatorConfigManagementDeleteWorkflow' => 'applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php',
|
||||||
|
'PhabricatorConfigManagementDoneWorkflow' => 'applications/config/management/PhabricatorConfigManagementDoneWorkflow.php',
|
||||||
'PhabricatorConfigManagementGetWorkflow' => 'applications/config/management/PhabricatorConfigManagementGetWorkflow.php',
|
'PhabricatorConfigManagementGetWorkflow' => 'applications/config/management/PhabricatorConfigManagementGetWorkflow.php',
|
||||||
'PhabricatorConfigManagementListWorkflow' => 'applications/config/management/PhabricatorConfigManagementListWorkflow.php',
|
'PhabricatorConfigManagementListWorkflow' => 'applications/config/management/PhabricatorConfigManagementListWorkflow.php',
|
||||||
'PhabricatorConfigManagementMigrateWorkflow' => 'applications/config/management/PhabricatorConfigManagementMigrateWorkflow.php',
|
'PhabricatorConfigManagementMigrateWorkflow' => 'applications/config/management/PhabricatorConfigManagementMigrateWorkflow.php',
|
||||||
'PhabricatorConfigManagementSetWorkflow' => 'applications/config/management/PhabricatorConfigManagementSetWorkflow.php',
|
'PhabricatorConfigManagementSetWorkflow' => 'applications/config/management/PhabricatorConfigManagementSetWorkflow.php',
|
||||||
'PhabricatorConfigManagementWorkflow' => 'applications/config/management/PhabricatorConfigManagementWorkflow.php',
|
'PhabricatorConfigManagementWorkflow' => 'applications/config/management/PhabricatorConfigManagementWorkflow.php',
|
||||||
|
'PhabricatorConfigManualActivity' => 'applications/config/storage/PhabricatorConfigManualActivity.php',
|
||||||
'PhabricatorConfigModule' => 'applications/config/module/PhabricatorConfigModule.php',
|
'PhabricatorConfigModule' => 'applications/config/module/PhabricatorConfigModule.php',
|
||||||
'PhabricatorConfigModuleController' => 'applications/config/controller/PhabricatorConfigModuleController.php',
|
'PhabricatorConfigModuleController' => 'applications/config/controller/PhabricatorConfigModuleController.php',
|
||||||
'PhabricatorConfigOption' => 'applications/config/option/PhabricatorConfigOption.php',
|
'PhabricatorConfigOption' => 'applications/config/option/PhabricatorConfigOption.php',
|
||||||
|
@ -2896,6 +2898,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorManiphestApplication' => 'applications/maniphest/application/PhabricatorManiphestApplication.php',
|
'PhabricatorManiphestApplication' => 'applications/maniphest/application/PhabricatorManiphestApplication.php',
|
||||||
'PhabricatorManiphestConfigOptions' => 'applications/maniphest/config/PhabricatorManiphestConfigOptions.php',
|
'PhabricatorManiphestConfigOptions' => 'applications/maniphest/config/PhabricatorManiphestConfigOptions.php',
|
||||||
'PhabricatorManiphestTaskTestDataGenerator' => 'applications/maniphest/lipsum/PhabricatorManiphestTaskTestDataGenerator.php',
|
'PhabricatorManiphestTaskTestDataGenerator' => 'applications/maniphest/lipsum/PhabricatorManiphestTaskTestDataGenerator.php',
|
||||||
|
'PhabricatorManualActivitySetupCheck' => 'applications/config/check/PhabricatorManualActivitySetupCheck.php',
|
||||||
'PhabricatorMarkupCache' => 'applications/cache/storage/PhabricatorMarkupCache.php',
|
'PhabricatorMarkupCache' => 'applications/cache/storage/PhabricatorMarkupCache.php',
|
||||||
'PhabricatorMarkupEngine' => 'infrastructure/markup/PhabricatorMarkupEngine.php',
|
'PhabricatorMarkupEngine' => 'infrastructure/markup/PhabricatorMarkupEngine.php',
|
||||||
'PhabricatorMarkupEngineTestCase' => 'infrastructure/markup/__tests__/PhabricatorMarkupEngineTestCase.php',
|
'PhabricatorMarkupEngineTestCase' => 'infrastructure/markup/__tests__/PhabricatorMarkupEngineTestCase.php',
|
||||||
|
@ -7178,11 +7181,13 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorConfigListController' => 'PhabricatorConfigController',
|
'PhabricatorConfigListController' => 'PhabricatorConfigController',
|
||||||
'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource',
|
'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource',
|
||||||
'PhabricatorConfigManagementDeleteWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
'PhabricatorConfigManagementDeleteWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
||||||
|
'PhabricatorConfigManagementDoneWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
||||||
'PhabricatorConfigManagementGetWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
'PhabricatorConfigManagementGetWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
||||||
'PhabricatorConfigManagementListWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
'PhabricatorConfigManagementListWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
||||||
'PhabricatorConfigManagementMigrateWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
'PhabricatorConfigManagementMigrateWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
||||||
'PhabricatorConfigManagementSetWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
'PhabricatorConfigManagementSetWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
||||||
'PhabricatorConfigManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
'PhabricatorConfigManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||||
|
'PhabricatorConfigManualActivity' => 'PhabricatorConfigEntryDAO',
|
||||||
'PhabricatorConfigModule' => 'Phobject',
|
'PhabricatorConfigModule' => 'Phobject',
|
||||||
'PhabricatorConfigModuleController' => 'PhabricatorConfigController',
|
'PhabricatorConfigModuleController' => 'PhabricatorConfigController',
|
||||||
'PhabricatorConfigOption' => array(
|
'PhabricatorConfigOption' => array(
|
||||||
|
@ -7877,6 +7882,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorManiphestApplication' => 'PhabricatorApplication',
|
'PhabricatorManiphestApplication' => 'PhabricatorApplication',
|
||||||
'PhabricatorManiphestConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorManiphestConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
'PhabricatorManiphestTaskTestDataGenerator' => 'PhabricatorTestDataGenerator',
|
'PhabricatorManiphestTaskTestDataGenerator' => 'PhabricatorTestDataGenerator',
|
||||||
|
'PhabricatorManualActivitySetupCheck' => 'PhabricatorSetupCheck',
|
||||||
'PhabricatorMarkupCache' => 'PhabricatorCacheDAO',
|
'PhabricatorMarkupCache' => 'PhabricatorCacheDAO',
|
||||||
'PhabricatorMarkupEngine' => 'Phobject',
|
'PhabricatorMarkupEngine' => 'Phobject',
|
||||||
'PhabricatorMarkupEngineTestCase' => 'PhabricatorTestCase',
|
'PhabricatorMarkupEngineTestCase' => 'PhabricatorTestCase',
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorManualActivitySetupCheck
|
||||||
|
extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
|
public function getDefaultGroup() {
|
||||||
|
return self::GROUP_OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function executeChecks() {
|
||||||
|
$activities = id(new PhabricatorConfigManualActivity())->loadAll();
|
||||||
|
|
||||||
|
foreach ($activities as $activity) {
|
||||||
|
$type = $activity->getActivityType();
|
||||||
|
|
||||||
|
// For now, there is only one type of manual activity. It's not clear
|
||||||
|
// if we're really going to have too much more of this stuff so this
|
||||||
|
// is a bit under-designed for now.
|
||||||
|
|
||||||
|
$activity_name = pht('Rebuild Search Index');
|
||||||
|
$activity_summary = pht(
|
||||||
|
'The search index algorithm has been updated and the index needs '.
|
||||||
|
'be rebuilt.');
|
||||||
|
|
||||||
|
$message = array();
|
||||||
|
|
||||||
|
$message[] = pht(
|
||||||
|
'The indexing algorithm for the fulltext search index has been '.
|
||||||
|
'updated and the index needs to be rebuilt. Until you rebuild the '.
|
||||||
|
'index, global search (and other fulltext search) will not '.
|
||||||
|
'function correctly.');
|
||||||
|
|
||||||
|
$message[] = pht(
|
||||||
|
'You can rebuild the search index while Phabricator is running.');
|
||||||
|
|
||||||
|
$message[] = pht(
|
||||||
|
'To rebuild the index, run this command:');
|
||||||
|
|
||||||
|
$message[] = phutil_tag(
|
||||||
|
'pre',
|
||||||
|
array(),
|
||||||
|
(string)csprintf(
|
||||||
|
'phabricator/ $ ./bin/search index --all --force --background'));
|
||||||
|
|
||||||
|
$message[] = pht(
|
||||||
|
'You can find more information about rebuilding the search '.
|
||||||
|
'index here: %s',
|
||||||
|
phutil_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => 'https://phurl.io/u/reindex',
|
||||||
|
'target' => '_blank',
|
||||||
|
),
|
||||||
|
'https://phurl.io/u/reindex'));
|
||||||
|
|
||||||
|
$message[] = pht(
|
||||||
|
'After rebuilding the index, run this command to clear this setup '.
|
||||||
|
'warning:');
|
||||||
|
|
||||||
|
$message[] = phutil_tag(
|
||||||
|
'pre',
|
||||||
|
array(),
|
||||||
|
(string)csprintf('phabricator/ $ ./bin/config done %R', $type));
|
||||||
|
|
||||||
|
$activity_message = phutil_implode_html("\n\n", $message);
|
||||||
|
|
||||||
|
$this->newIssue('manual.'.$type)
|
||||||
|
->setName($activity_name)
|
||||||
|
->setSummary($activity_summary)
|
||||||
|
->setMessage($activity_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorConfigManagementDoneWorkflow
|
||||||
|
extends PhabricatorConfigManagementWorkflow {
|
||||||
|
|
||||||
|
protected function didConstruct() {
|
||||||
|
$this
|
||||||
|
->setName('done')
|
||||||
|
->setExamples('**done** __activity__')
|
||||||
|
->setSynopsis(pht('Mark a manual upgrade activity as complete.'))
|
||||||
|
->setArguments(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'name' => 'activities',
|
||||||
|
'wildcard' => true,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(PhutilArgumentParser $args) {
|
||||||
|
$activities = $args->getArg('activities');
|
||||||
|
if (!$activities) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht('Specify an activity to mark as completed.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($activities as $type) {
|
||||||
|
$activity = id(new PhabricatorConfigManualActivity())->loadOneWhere(
|
||||||
|
'activityType = %s',
|
||||||
|
$type);
|
||||||
|
if (!$activity) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht(
|
||||||
|
'Activity "%s" is not currently marked as required, so there '.
|
||||||
|
'is no need to complete it.',
|
||||||
|
$type));
|
||||||
|
} else {
|
||||||
|
$activity->delete();
|
||||||
|
echo tsprintf(
|
||||||
|
"%s\n",
|
||||||
|
pht(
|
||||||
|
'Marked activity "%s" as completed.',
|
||||||
|
$type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo tsprintf(
|
||||||
|
"%s\n",
|
||||||
|
pht('Done.'));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorConfigManualActivity
|
||||||
|
extends PhabricatorConfigEntryDAO {
|
||||||
|
|
||||||
|
protected $activityType;
|
||||||
|
protected $parameters = array();
|
||||||
|
|
||||||
|
const TYPE_REINDEX = 'reindex';
|
||||||
|
|
||||||
|
protected function getConfiguration() {
|
||||||
|
return array(
|
||||||
|
self::CONFIG_TIMESTAMPS => false,
|
||||||
|
self::CONFIG_SERIALIZATION => array(
|
||||||
|
'parameters' => self::SERIALIZATION_JSON,
|
||||||
|
),
|
||||||
|
self::CONFIG_COLUMN_SCHEMA => array(
|
||||||
|
'activityType' => 'text64',
|
||||||
|
),
|
||||||
|
self::CONFIG_KEY_SCHEMA => array(
|
||||||
|
'key_type' => array(
|
||||||
|
'columns' => array('activityType'),
|
||||||
|
'unique' => true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) + parent::getConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setParameter($key, $value) {
|
||||||
|
$this->parameters[$key] = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParameter($key, $default = null) {
|
||||||
|
return idx($this->parameters, $key, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -929,6 +929,7 @@ abstract class PhabricatorStorageManagementWorkflow
|
||||||
}
|
}
|
||||||
|
|
||||||
$applied_map = array();
|
$applied_map = array();
|
||||||
|
$state_map = array();
|
||||||
foreach ($api_map as $ref_key => $api) {
|
foreach ($api_map as $ref_key => $api) {
|
||||||
$applied = $api->getAppliedPatches();
|
$applied = $api->getAppliedPatches();
|
||||||
|
|
||||||
|
@ -946,6 +947,7 @@ abstract class PhabricatorStorageManagementWorkflow
|
||||||
}
|
}
|
||||||
|
|
||||||
$applied = array_fuse($applied);
|
$applied = array_fuse($applied);
|
||||||
|
$state_map[$ref_key] = $applied;
|
||||||
|
|
||||||
if ($apply_only) {
|
if ($apply_only) {
|
||||||
if (isset($applied[$apply_only])) {
|
if (isset($applied[$apply_only])) {
|
||||||
|
@ -1097,7 +1099,7 @@ abstract class PhabricatorStorageManagementWorkflow
|
||||||
|
|
||||||
// If we're explicitly reapplying this patch, we don't need to
|
// If we're explicitly reapplying this patch, we don't need to
|
||||||
// mark it as applied.
|
// mark it as applied.
|
||||||
if (!isset($applied_map[$ref_key][$key])) {
|
if (!isset($state_map[$ref_key][$key])) {
|
||||||
$api->markPatchApplied($key, ($t_end - $t_begin));
|
$api->markPatchApplied($key, ($t_end - $t_begin));
|
||||||
$applied_map[$ref_key][$key] = true;
|
$applied_map[$ref_key][$key] = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue