@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+208 -1
+6
resources/sql/autopatches/20161130.search.01.manual.sql
··· 1 + CREATE TABLE {$NAMESPACE}_config.config_manualactivity ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + activityType VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT}, 4 + parameters LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}, 5 + UNIQUE KEY `key_type` (activityType) 6 + ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+26
resources/sql/autopatches/20161130.search.02.rebuild.php
··· 1 + <?php 2 + 3 + $search_engine = PhabricatorFulltextStorageEngine::loadEngine(); 4 + $use_mysql = ($search_engine instanceof PhabricatorMySQLFulltextStorageEngine); 5 + 6 + if ($use_mysql) { 7 + $field = new PhabricatorSearchDocumentField(); 8 + $conn = $field->establishConnection('r'); 9 + 10 + // We're only going to require this if the index isn't empty: if you're on a 11 + // fresh install, you don't have to do anything. 12 + $any_documents = queryfx_one( 13 + $conn, 14 + 'SELECT * FROM %T LIMIT 1', 15 + $field->getTableName()); 16 + 17 + if ($any_documents) { 18 + try { 19 + id(new PhabricatorConfigManualActivity()) 20 + ->setActivityType(PhabricatorConfigManualActivity::TYPE_REINDEX) 21 + ->save(); 22 + } catch (AphrontDuplicateKeyQueryException $ex) { 23 + // If we've already noted that this activity is required, just move on. 24 + } 25 + } 26 + }
+6
src/__phutil_library_map__.php
··· 2272 2272 'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php', 2273 2273 'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php', 2274 2274 'PhabricatorConfigManagementDeleteWorkflow' => 'applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php', 2275 + 'PhabricatorConfigManagementDoneWorkflow' => 'applications/config/management/PhabricatorConfigManagementDoneWorkflow.php', 2275 2276 'PhabricatorConfigManagementGetWorkflow' => 'applications/config/management/PhabricatorConfigManagementGetWorkflow.php', 2276 2277 'PhabricatorConfigManagementListWorkflow' => 'applications/config/management/PhabricatorConfigManagementListWorkflow.php', 2277 2278 'PhabricatorConfigManagementMigrateWorkflow' => 'applications/config/management/PhabricatorConfigManagementMigrateWorkflow.php', 2278 2279 'PhabricatorConfigManagementSetWorkflow' => 'applications/config/management/PhabricatorConfigManagementSetWorkflow.php', 2279 2280 'PhabricatorConfigManagementWorkflow' => 'applications/config/management/PhabricatorConfigManagementWorkflow.php', 2281 + 'PhabricatorConfigManualActivity' => 'applications/config/storage/PhabricatorConfigManualActivity.php', 2280 2282 'PhabricatorConfigModule' => 'applications/config/module/PhabricatorConfigModule.php', 2281 2283 'PhabricatorConfigModuleController' => 'applications/config/controller/PhabricatorConfigModuleController.php', 2282 2284 'PhabricatorConfigOption' => 'applications/config/option/PhabricatorConfigOption.php', ··· 2896 2898 'PhabricatorManiphestApplication' => 'applications/maniphest/application/PhabricatorManiphestApplication.php', 2897 2899 'PhabricatorManiphestConfigOptions' => 'applications/maniphest/config/PhabricatorManiphestConfigOptions.php', 2898 2900 'PhabricatorManiphestTaskTestDataGenerator' => 'applications/maniphest/lipsum/PhabricatorManiphestTaskTestDataGenerator.php', 2901 + 'PhabricatorManualActivitySetupCheck' => 'applications/config/check/PhabricatorManualActivitySetupCheck.php', 2899 2902 'PhabricatorMarkupCache' => 'applications/cache/storage/PhabricatorMarkupCache.php', 2900 2903 'PhabricatorMarkupEngine' => 'infrastructure/markup/PhabricatorMarkupEngine.php', 2901 2904 'PhabricatorMarkupEngineTestCase' => 'infrastructure/markup/__tests__/PhabricatorMarkupEngineTestCase.php', ··· 7178 7181 'PhabricatorConfigListController' => 'PhabricatorConfigController', 7179 7182 'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource', 7180 7183 'PhabricatorConfigManagementDeleteWorkflow' => 'PhabricatorConfigManagementWorkflow', 7184 + 'PhabricatorConfigManagementDoneWorkflow' => 'PhabricatorConfigManagementWorkflow', 7181 7185 'PhabricatorConfigManagementGetWorkflow' => 'PhabricatorConfigManagementWorkflow', 7182 7186 'PhabricatorConfigManagementListWorkflow' => 'PhabricatorConfigManagementWorkflow', 7183 7187 'PhabricatorConfigManagementMigrateWorkflow' => 'PhabricatorConfigManagementWorkflow', 7184 7188 'PhabricatorConfigManagementSetWorkflow' => 'PhabricatorConfigManagementWorkflow', 7185 7189 'PhabricatorConfigManagementWorkflow' => 'PhabricatorManagementWorkflow', 7190 + 'PhabricatorConfigManualActivity' => 'PhabricatorConfigEntryDAO', 7186 7191 'PhabricatorConfigModule' => 'Phobject', 7187 7192 'PhabricatorConfigModuleController' => 'PhabricatorConfigController', 7188 7193 'PhabricatorConfigOption' => array( ··· 7877 7882 'PhabricatorManiphestApplication' => 'PhabricatorApplication', 7878 7883 'PhabricatorManiphestConfigOptions' => 'PhabricatorApplicationConfigOptions', 7879 7884 'PhabricatorManiphestTaskTestDataGenerator' => 'PhabricatorTestDataGenerator', 7885 + 'PhabricatorManualActivitySetupCheck' => 'PhabricatorSetupCheck', 7880 7886 'PhabricatorMarkupCache' => 'PhabricatorCacheDAO', 7881 7887 'PhabricatorMarkupEngine' => 'Phobject', 7882 7888 'PhabricatorMarkupEngineTestCase' => 'PhabricatorTestCase',
+75
src/applications/config/check/PhabricatorManualActivitySetupCheck.php
··· 1 + <?php 2 + 3 + final class PhabricatorManualActivitySetupCheck 4 + extends PhabricatorSetupCheck { 5 + 6 + public function getDefaultGroup() { 7 + return self::GROUP_OTHER; 8 + } 9 + 10 + protected function executeChecks() { 11 + $activities = id(new PhabricatorConfigManualActivity())->loadAll(); 12 + 13 + foreach ($activities as $activity) { 14 + $type = $activity->getActivityType(); 15 + 16 + // For now, there is only one type of manual activity. It's not clear 17 + // if we're really going to have too much more of this stuff so this 18 + // is a bit under-designed for now. 19 + 20 + $activity_name = pht('Rebuild Search Index'); 21 + $activity_summary = pht( 22 + 'The search index algorithm has been updated and the index needs '. 23 + 'be rebuilt.'); 24 + 25 + $message = array(); 26 + 27 + $message[] = pht( 28 + 'The indexing algorithm for the fulltext search index has been '. 29 + 'updated and the index needs to be rebuilt. Until you rebuild the '. 30 + 'index, global search (and other fulltext search) will not '. 31 + 'function correctly.'); 32 + 33 + $message[] = pht( 34 + 'You can rebuild the search index while Phabricator is running.'); 35 + 36 + $message[] = pht( 37 + 'To rebuild the index, run this command:'); 38 + 39 + $message[] = phutil_tag( 40 + 'pre', 41 + array(), 42 + (string)csprintf( 43 + 'phabricator/ $ ./bin/search index --all --force --background')); 44 + 45 + $message[] = pht( 46 + 'You can find more information about rebuilding the search '. 47 + 'index here: %s', 48 + phutil_tag( 49 + 'a', 50 + array( 51 + 'href' => 'https://phurl.io/u/reindex', 52 + 'target' => '_blank', 53 + ), 54 + 'https://phurl.io/u/reindex')); 55 + 56 + $message[] = pht( 57 + 'After rebuilding the index, run this command to clear this setup '. 58 + 'warning:'); 59 + 60 + $message[] = phutil_tag( 61 + 'pre', 62 + array(), 63 + (string)csprintf('phabricator/ $ ./bin/config done %R', $type)); 64 + 65 + $activity_message = phutil_implode_html("\n\n", $message); 66 + 67 + $this->newIssue('manual.'.$type) 68 + ->setName($activity_name) 69 + ->setSummary($activity_summary) 70 + ->setMessage($activity_message); 71 + } 72 + 73 + } 74 + 75 + }
+54
src/applications/config/management/PhabricatorConfigManagementDoneWorkflow.php
··· 1 + <?php 2 + 3 + final class PhabricatorConfigManagementDoneWorkflow 4 + extends PhabricatorConfigManagementWorkflow { 5 + 6 + protected function didConstruct() { 7 + $this 8 + ->setName('done') 9 + ->setExamples('**done** __activity__') 10 + ->setSynopsis(pht('Mark a manual upgrade activity as complete.')) 11 + ->setArguments( 12 + array( 13 + array( 14 + 'name' => 'activities', 15 + 'wildcard' => true, 16 + ), 17 + )); 18 + } 19 + 20 + public function execute(PhutilArgumentParser $args) { 21 + $activities = $args->getArg('activities'); 22 + if (!$activities) { 23 + throw new PhutilArgumentUsageException( 24 + pht('Specify an activity to mark as completed.')); 25 + } 26 + 27 + foreach ($activities as $type) { 28 + $activity = id(new PhabricatorConfigManualActivity())->loadOneWhere( 29 + 'activityType = %s', 30 + $type); 31 + if (!$activity) { 32 + throw new PhutilArgumentUsageException( 33 + pht( 34 + 'Activity "%s" is not currently marked as required, so there '. 35 + 'is no need to complete it.', 36 + $type)); 37 + } else { 38 + $activity->delete(); 39 + echo tsprintf( 40 + "%s\n", 41 + pht( 42 + 'Marked activity "%s" as completed.', 43 + $type)); 44 + } 45 + } 46 + 47 + echo tsprintf( 48 + "%s\n", 49 + pht('Done.')); 50 + 51 + return 0; 52 + } 53 + 54 + }
+38
src/applications/config/storage/PhabricatorConfigManualActivity.php
··· 1 + <?php 2 + 3 + final class PhabricatorConfigManualActivity 4 + extends PhabricatorConfigEntryDAO { 5 + 6 + protected $activityType; 7 + protected $parameters = array(); 8 + 9 + const TYPE_REINDEX = 'reindex'; 10 + 11 + protected function getConfiguration() { 12 + return array( 13 + self::CONFIG_TIMESTAMPS => false, 14 + self::CONFIG_SERIALIZATION => array( 15 + 'parameters' => self::SERIALIZATION_JSON, 16 + ), 17 + self::CONFIG_COLUMN_SCHEMA => array( 18 + 'activityType' => 'text64', 19 + ), 20 + self::CONFIG_KEY_SCHEMA => array( 21 + 'key_type' => array( 22 + 'columns' => array('activityType'), 23 + 'unique' => true, 24 + ), 25 + ), 26 + ) + parent::getConfiguration(); 27 + } 28 + 29 + public function setParameter($key, $value) { 30 + $this->parameters[$key] = $value; 31 + return $this; 32 + } 33 + 34 + public function getParameter($key, $default = null) { 35 + return idx($this->parameters, $key, $default); 36 + } 37 + 38 + }
+3 -1
src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php
··· 929 929 } 930 930 931 931 $applied_map = array(); 932 + $state_map = array(); 932 933 foreach ($api_map as $ref_key => $api) { 933 934 $applied = $api->getAppliedPatches(); 934 935 ··· 946 947 } 947 948 948 949 $applied = array_fuse($applied); 950 + $state_map[$ref_key] = $applied; 949 951 950 952 if ($apply_only) { 951 953 if (isset($applied[$apply_only])) { ··· 1097 1099 1098 1100 // If we're explicitly reapplying this patch, we don't need to 1099 1101 // mark it as applied. 1100 - if (!isset($applied_map[$ref_key][$key])) { 1102 + if (!isset($state_map[$ref_key][$key])) { 1101 1103 $api->markPatchApplied($key, ($t_end - $t_begin)); 1102 1104 $applied_map[$ref_key][$key] = true; 1103 1105 }