mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-18 11:30:55 +01:00
Add a friendlier "in flight" error page
Summary: Ref T11589. When we hit a fatal setup issue (essentially always a connection failure) //after// we've already survived them on at least one request, we can be pretty sure a server went down and that the problem is not a setup/configuration issue. In this case, show a friendlier error page instead of the fairly detailed technical one. Test Plan: - Broke MySQL config. - Restarted Apache. - Got the "admin/setup" error page: {F1803268} - Fixed the MySQL config. - Loaded any page, to put us "in flight". - Broke MySQL config. - Loaded any page. - Got the friendly "in flight" error page: {F1803271} If you want to design this better, easiest way to get to it is: - Set `mysql.port` to `9999` in `conf/local/local.json`. - Reload any page while already running (don't restart). Reviewers: chad Reviewed By: chad Maniphest Tasks: T11589 Differential Revision: https://secure.phabricator.com/D16503
This commit is contained in:
parent
0e8ceeb690
commit
f82adbf0c8
7 changed files with 104 additions and 4 deletions
|
@ -41,7 +41,7 @@ return array(
|
|||
'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4',
|
||||
'rsrc/css/application/config/config-options.css' => '0ede4c9b',
|
||||
'rsrc/css/application/config/config-page.css' => '8798e14f',
|
||||
'rsrc/css/application/config/config-template.css' => '8e6c6fcd',
|
||||
'rsrc/css/application/config/config-template.css' => '8f18fa41',
|
||||
'rsrc/css/application/config/setup-issue.css' => 'f794cfc3',
|
||||
'rsrc/css/application/config/unhandled-exception.css' => '4c96257a',
|
||||
'rsrc/css/application/conpherence/durable-column.css' => '86396117',
|
||||
|
@ -777,7 +777,7 @@ return array(
|
|||
'phabricator-dashboard-css' => 'bc6f2127',
|
||||
'phabricator-drag-and-drop-file-upload' => '58dea2fa',
|
||||
'phabricator-draggable-list' => '5a13c79f',
|
||||
'phabricator-fatal-config-template-css' => '8e6c6fcd',
|
||||
'phabricator-fatal-config-template-css' => '8f18fa41',
|
||||
'phabricator-feed-css' => 'ecd4ec57',
|
||||
'phabricator-file-upload' => '680ea2c8',
|
||||
'phabricator-filetree-view-css' => 'fccf9f82',
|
||||
|
|
|
@ -2685,6 +2685,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorImageMacroRemarkupRule' => 'applications/macro/markup/PhabricatorImageMacroRemarkupRule.php',
|
||||
'PhabricatorImageTransformer' => 'applications/files/PhabricatorImageTransformer.php',
|
||||
'PhabricatorImagemagickSetupCheck' => 'applications/config/check/PhabricatorImagemagickSetupCheck.php',
|
||||
'PhabricatorInFlightErrorView' => 'applications/config/view/PhabricatorInFlightErrorView.php',
|
||||
'PhabricatorIndexEngine' => 'applications/search/index/PhabricatorIndexEngine.php',
|
||||
'PhabricatorIndexEngineExtension' => 'applications/search/index/PhabricatorIndexEngineExtension.php',
|
||||
'PhabricatorIndexEngineExtensionModule' => 'applications/search/index/PhabricatorIndexEngineExtensionModule.php',
|
||||
|
@ -7509,6 +7510,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorImageMacroRemarkupRule' => 'PhutilRemarkupRule',
|
||||
'PhabricatorImageTransformer' => 'Phobject',
|
||||
'PhabricatorImagemagickSetupCheck' => 'PhabricatorSetupCheck',
|
||||
'PhabricatorInFlightErrorView' => 'AphrontView',
|
||||
'PhabricatorIndexEngine' => 'Phobject',
|
||||
'PhabricatorIndexEngineExtension' => 'Phobject',
|
||||
'PhabricatorIndexEngineExtensionModule' => 'PhabricatorConfigModule',
|
||||
|
|
|
@ -192,6 +192,21 @@ abstract class PhabricatorSetupCheck extends Phobject {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if we've survived through setup on at least one normal request
|
||||
* without fataling.
|
||||
*
|
||||
* If we've made it through setup without hitting any fatals, we switch
|
||||
* to render a more friendly error page when encountering issues like
|
||||
* database connection failures. This gives users a smoother experience in
|
||||
* the face of intermittent failures.
|
||||
*
|
||||
* @return bool True if we've made it through setup since the last restart.
|
||||
*/
|
||||
final public static function isInFlight() {
|
||||
return (self::getOpenSetupIssueKeys() !== null);
|
||||
}
|
||||
|
||||
final public static function loadAllChecks() {
|
||||
return id(new PhutilClassMapQuery())
|
||||
->setAncestorClass(__CLASS__)
|
||||
|
|
|
@ -25,11 +25,21 @@ final class PhabricatorConfigResponse extends AphrontStandaloneHTMLResponse {
|
|||
}
|
||||
|
||||
protected function getResponseBodyClass() {
|
||||
return 'setup-fatal';
|
||||
if (PhabricatorSetupCheck::isInFlight()) {
|
||||
return 'setup-fatal in-flight';
|
||||
} else {
|
||||
return 'setup-fatal';
|
||||
}
|
||||
}
|
||||
|
||||
protected function getResponseBody() {
|
||||
return $this->view->render();
|
||||
$view = $this->view;
|
||||
|
||||
if (PhabricatorSetupCheck::isInFlight()) {
|
||||
return $view->renderInFlight();
|
||||
} else {
|
||||
return $view->render();
|
||||
}
|
||||
}
|
||||
|
||||
protected function buildPlainTextResponseString() {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorInFlightErrorView extends AphrontView {
|
||||
|
||||
private $message;
|
||||
|
||||
public function setMessage($message) {
|
||||
$this->message = $message;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMessage() {
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
return phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'in-flight-error-detail',
|
||||
),
|
||||
array(
|
||||
phutil_tag(
|
||||
'h1',
|
||||
array(
|
||||
'class' => 'in-flight-error-title',
|
||||
),
|
||||
pht('A Troublesome Encounter!')),
|
||||
phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'in-flight-error-body',
|
||||
),
|
||||
pht(
|
||||
'Woe! This request had its journey cut short by unexpected '.
|
||||
'circumstances (%s).',
|
||||
$this->getMessage())),
|
||||
));
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,14 @@ final class PhabricatorSetupIssueView extends AphrontView {
|
|||
return $this->issue;
|
||||
}
|
||||
|
||||
public function renderInFlight() {
|
||||
$issue = $this->getIssue();
|
||||
|
||||
return id(new PhabricatorInFlightErrorView())
|
||||
->setMessage($issue->getName())
|
||||
->render();
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$issue = $this->getIssue();
|
||||
|
||||
|
|
|
@ -11,3 +11,27 @@ body {
|
|||
text-align: left;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
body.in-flight {
|
||||
background: #41506e;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
.in-flight-error-detail {
|
||||
max-width: 760px;
|
||||
margin: 72px auto;
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
border-radius: 3px;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
|
||||
.in-flight-error-title {
|
||||
padding: 12px 8px;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.in-flight-error-body {
|
||||
padding: 4px 12px 12px;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue