diff --git a/src/applications/config/check/PhabricatorSetupCheck.php b/src/applications/config/check/PhabricatorSetupCheck.php --- a/src/applications/config/check/PhabricatorSetupCheck.php +++ b/src/applications/config/check/PhabricatorSetupCheck.php @@ -50,9 +50,35 @@ return $cache->getKey('phabricator.setup.issue-keys'); } - final public static function setOpenSetupIssueKeys(array $keys) { + final public static function setOpenSetupIssueKeys( + array $keys, + $update_database) { $cache = PhabricatorCaches::getSetupCache(); $cache->setKey('phabricator.setup.issue-keys', $keys); + + if ($update_database) { + $db_cache = new PhabricatorKeyValueDatabaseCache(); + try { + $json = phutil_json_encode($keys); + $db_cache->setKey('phabricator.setup.issue-keys', $json); + } catch (Exception $ex) { + // Ignore any write failures, since they likely just indicate that we + // have a database-related setup issue that needs to be resolved. + } + } + } + + final public static function getOpenSetupIssueKeysFromDatabase() { + $db_cache = new PhabricatorKeyValueDatabaseCache(); + try { + $value = $db_cache->getKey('phabricator.setup.issue-keys'); + if (!strlen($value)) { + return null; + } + return phutil_json_decode($value); + } catch (Exception $ex) { + return null; + } } final public static function getUnignoredIssueKeys(array $all_issues) { @@ -97,7 +123,21 @@ ->setView($view); } } - self::setOpenSetupIssueKeys(self::getUnignoredIssueKeys($issues)); + $issue_keys = self::getUnignoredIssueKeys($issues); + self::setOpenSetupIssueKeys($issue_keys, $update_database = true); + } else if ($issue_keys) { + // If Phabricator is configured in a cluster with multiple web devices, + // we can end up with setup issues cached on every device. This can cause + // a warning banner to show on every device so that each one needs to + // be dismissed individually, which is pretty annoying. See T10876. + + // To avoid this, check if the issues we found have already been cleared + // in the database. If they have, we'll just wipe out our own cache and + // move on. + $issue_keys = self::getOpenSetupIssueKeysFromDatabase(); + if ($issue_keys !== null) { + self::setOpenSetupIssueKeys($issue_keys, $update_database = false); + } } // Try to repair configuration unless we have a clean bill of health on it. diff --git a/src/applications/config/controller/PhabricatorConfigIssueListController.php b/src/applications/config/controller/PhabricatorConfigIssueListController.php --- a/src/applications/config/controller/PhabricatorConfigIssueListController.php +++ b/src/applications/config/controller/PhabricatorConfigIssueListController.php @@ -11,7 +11,8 @@ $issues = PhabricatorSetupCheck::runAllChecks(); PhabricatorSetupCheck::setOpenSetupIssueKeys( - PhabricatorSetupCheck::getUnignoredIssueKeys($issues)); + PhabricatorSetupCheck::getUnignoredIssueKeys($issues), + $update_database = true); $important = $this->buildIssueList( $issues, PhabricatorSetupCheck::GROUP_IMPORTANT); diff --git a/src/applications/config/controller/PhabricatorConfigIssueViewController.php b/src/applications/config/controller/PhabricatorConfigIssueViewController.php --- a/src/applications/config/controller/PhabricatorConfigIssueViewController.php +++ b/src/applications/config/controller/PhabricatorConfigIssueViewController.php @@ -9,7 +9,8 @@ $issues = PhabricatorSetupCheck::runAllChecks(); PhabricatorSetupCheck::setOpenSetupIssueKeys( - PhabricatorSetupCheck::getUnignoredIssueKeys($issues)); + PhabricatorSetupCheck::getUnignoredIssueKeys($issues), + $update_database = true); if (empty($issues[$issue_key])) { $content = id(new PHUIInfoView())