mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-24 20:49:06 +01:00
(stable) Promote 2020 Week 29
This commit is contained in:
commit
1b54f45c4c
10 changed files with 158 additions and 104 deletions
|
@ -8,14 +8,21 @@ final class PhabricatorDaemonsSetupCheck extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
protected function executeChecks() {
|
protected function executeChecks() {
|
||||||
|
|
||||||
$task_daemon = id(new PhabricatorDaemonLogQuery())
|
try {
|
||||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
$task_daemons = id(new PhabricatorDaemonLogQuery())
|
||||||
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
->withDaemonClasses(array('PhabricatorTaskmasterDaemon'))
|
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
|
||||||
->setLimit(1)
|
->withDaemonClasses(array('PhabricatorTaskmasterDaemon'))
|
||||||
->execute();
|
->setLimit(1)
|
||||||
|
->execute();
|
||||||
|
|
||||||
if (!$task_daemon) {
|
$no_daemons = !$task_daemons;
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
// Just skip this warning if the query fails for some reason.
|
||||||
|
$no_daemons = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($no_daemons) {
|
||||||
$doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd');
|
$doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd');
|
||||||
|
|
||||||
$summary = pht(
|
$summary = pht(
|
||||||
|
|
|
@ -322,6 +322,9 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
|
||||||
'directly supported. Prefixes and other strings may be customized with '.
|
'directly supported. Prefixes and other strings may be customized with '.
|
||||||
'"translation.override".');
|
'"translation.override".');
|
||||||
|
|
||||||
|
$phd_reason = pht(
|
||||||
|
'Use "bin/phd debug ..." to get a detailed daemon execution log.');
|
||||||
|
|
||||||
$ancient_config += array(
|
$ancient_config += array(
|
||||||
'phid.external-loaders' =>
|
'phid.external-loaders' =>
|
||||||
pht(
|
pht(
|
||||||
|
@ -539,6 +542,9 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
'phd.pid-directory' => pht(
|
'phd.pid-directory' => pht(
|
||||||
'Phabricator daemons no longer use PID files.'),
|
'Phabricator daemons no longer use PID files.'),
|
||||||
|
|
||||||
|
'phd.trace' => $phd_reason,
|
||||||
|
'phd.verbose' => $phd_reason,
|
||||||
);
|
);
|
||||||
|
|
||||||
return $ancient_config;
|
return $ancient_config;
|
||||||
|
|
|
@ -43,22 +43,6 @@ final class PhabricatorPHDConfigOptions
|
||||||
"configuration changes are picked up by the daemons ".
|
"configuration changes are picked up by the daemons ".
|
||||||
"automatically, but pool sizes can not be changed without a ".
|
"automatically, but pool sizes can not be changed without a ".
|
||||||
"restart.")),
|
"restart.")),
|
||||||
$this->newOption('phd.verbose', 'bool', false)
|
|
||||||
->setLocked(true)
|
|
||||||
->setBoolOptions(
|
|
||||||
array(
|
|
||||||
pht('Verbose mode'),
|
|
||||||
pht('Normal mode'),
|
|
||||||
))
|
|
||||||
->setSummary(pht("Launch daemons in 'verbose' mode by default."))
|
|
||||||
->setDescription(
|
|
||||||
pht(
|
|
||||||
"Launch daemons in 'verbose' mode by default. This creates a lot ".
|
|
||||||
"of output, but can help debug issues. Daemons launched in debug ".
|
|
||||||
"mode with '%s' are always launched in verbose mode. ".
|
|
||||||
"See also '%s'.",
|
|
||||||
'phd debug',
|
|
||||||
'phd.trace')),
|
|
||||||
$this->newOption('phd.user', 'string', null)
|
$this->newOption('phd.user', 'string', null)
|
||||||
->setLocked(true)
|
->setLocked(true)
|
||||||
->setSummary(pht('System user to run daemons as.'))
|
->setSummary(pht('System user to run daemons as.'))
|
||||||
|
@ -68,22 +52,6 @@ final class PhabricatorPHDConfigOptions
|
||||||
'user will own the working copies of any repositories that '.
|
'user will own the working copies of any repositories that '.
|
||||||
'Phabricator imports or manages. This option is new and '.
|
'Phabricator imports or manages. This option is new and '.
|
||||||
'experimental.')),
|
'experimental.')),
|
||||||
$this->newOption('phd.trace', 'bool', false)
|
|
||||||
->setLocked(true)
|
|
||||||
->setBoolOptions(
|
|
||||||
array(
|
|
||||||
pht('Trace mode'),
|
|
||||||
pht('Normal mode'),
|
|
||||||
))
|
|
||||||
->setSummary(pht("Launch daemons in 'trace' mode by default."))
|
|
||||||
->setDescription(
|
|
||||||
pht(
|
|
||||||
"Launch daemons in 'trace' mode by default. This creates an ".
|
|
||||||
"ENORMOUS amount of output, but can help debug issues. Daemons ".
|
|
||||||
"launched in debug mode with '%s' are always launched in ".
|
|
||||||
"trace mode. See also '%s'.",
|
|
||||||
'phd debug',
|
|
||||||
'phd.verbose')),
|
|
||||||
$this->newOption('phd.garbage-collection', 'wild', array())
|
$this->newOption('phd.garbage-collection', 'wild', array())
|
||||||
->setLocked(true)
|
->setLocked(true)
|
||||||
->setLockedMessage(
|
->setLockedMessage(
|
||||||
|
|
|
@ -116,11 +116,11 @@ abstract class PhabricatorDaemonManagementWorkflow
|
||||||
$trace = PhutilArgumentParser::isTraceModeEnabled();
|
$trace = PhutilArgumentParser::isTraceModeEnabled();
|
||||||
|
|
||||||
$flags = array();
|
$flags = array();
|
||||||
if ($trace || PhabricatorEnv::getEnvConfig('phd.trace')) {
|
if ($trace) {
|
||||||
$flags[] = '--trace';
|
$flags[] = '--trace';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($debug || PhabricatorEnv::getEnvConfig('phd.verbose')) {
|
if ($debug) {
|
||||||
$flags[] = '--verbose';
|
$flags[] = '--verbose';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ final class PhutilDaemonHandle extends Phobject {
|
||||||
private $restartAt;
|
private $restartAt;
|
||||||
private $busyEpoch;
|
private $busyEpoch;
|
||||||
|
|
||||||
private $pid;
|
|
||||||
private $daemonID;
|
private $daemonID;
|
||||||
private $deadline;
|
private $deadline;
|
||||||
private $heartbeat;
|
private $heartbeat;
|
||||||
|
@ -104,7 +103,7 @@ final class PhutilDaemonHandle extends Phobject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isRunning() {
|
public function isRunning() {
|
||||||
return (bool)$this->future;
|
return (bool)$this->getFuture();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isHibernating() {
|
public function isHibernating() {
|
||||||
|
@ -134,10 +133,6 @@ final class PhutilDaemonHandle extends Phobject {
|
||||||
return (!$this->shouldRestart && !$this->isRunning());
|
return (!$this->shouldRestart && !$this->isRunning());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFuture() {
|
|
||||||
return $this->future;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update() {
|
public function update() {
|
||||||
if (!$this->isRunning()) {
|
if (!$this->isRunning()) {
|
||||||
if (!$this->shouldRestart) {
|
if (!$this->shouldRestart) {
|
||||||
|
@ -152,11 +147,19 @@ final class PhutilDaemonHandle extends Phobject {
|
||||||
$this->startDaemonProcess();
|
$this->startDaemonProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
$future = $this->future;
|
$future = $this->getFuture();
|
||||||
|
|
||||||
$result = null;
|
$result = null;
|
||||||
if ($future->isReady()) {
|
$caught = null;
|
||||||
$result = $future->resolve();
|
if ($future->canResolve()) {
|
||||||
|
$this->future = null;
|
||||||
|
try {
|
||||||
|
$result = $future->resolve();
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$caught = $ex;
|
||||||
|
} catch (Throwable $ex) {
|
||||||
|
$caught = $ex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list($stdout, $stderr) = $future->read();
|
list($stdout, $stderr) = $future->read();
|
||||||
|
@ -173,16 +176,22 @@ final class PhutilDaemonHandle extends Phobject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($result !== null) {
|
if ($result !== null || $caught !== null) {
|
||||||
list($err) = $result;
|
|
||||||
|
|
||||||
if ($err) {
|
if ($caught) {
|
||||||
$this->logMessage('FAIL', pht('Process exited with error %s.', $err));
|
$message = pht(
|
||||||
|
'Process failed with exception: %s',
|
||||||
|
$caught->getMessage());
|
||||||
|
$this->logMessage('FAIL', $message);
|
||||||
} else {
|
} else {
|
||||||
$this->logMessage('DONE', pht('Process exited normally.'));
|
list($err) = $result;
|
||||||
}
|
|
||||||
|
|
||||||
$this->future = null;
|
if ($err) {
|
||||||
|
$this->logMessage('FAIL', pht('Process exited with error %s.', $err));
|
||||||
|
} else {
|
||||||
|
$this->logMessage('DONE', pht('Process exited normally.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->shouldShutdown) {
|
if ($this->shouldShutdown) {
|
||||||
$this->restartAt = null;
|
$this->restartAt = null;
|
||||||
|
@ -244,8 +253,22 @@ final class PhutilDaemonHandle extends Phobject {
|
||||||
return $this->daemonID;
|
return $this->daemonID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPID() {
|
private function getFuture() {
|
||||||
return $this->pid;
|
return $this->future;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPID() {
|
||||||
|
$future = $this->getFuture();
|
||||||
|
|
||||||
|
if (!$future) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$future->hasPID()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $future->getPID();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getCaptureBufferSize() {
|
private function getCaptureBufferSize() {
|
||||||
|
@ -327,13 +350,14 @@ final class PhutilDaemonHandle extends Phobject {
|
||||||
|
|
||||||
private function annihilateProcessGroup() {
|
private function annihilateProcessGroup() {
|
||||||
$pid = $this->getPID();
|
$pid = $this->getPID();
|
||||||
|
if ($pid) {
|
||||||
$pgid = posix_getpgid($pid);
|
$pgid = posix_getpgid($pid);
|
||||||
if ($pid && $pgid) {
|
if ($pgid) {
|
||||||
posix_kill(-$pgid, SIGTERM);
|
posix_kill(-$pgid, SIGTERM);
|
||||||
sleep($this->getKillDelay());
|
sleep($this->getKillDelay());
|
||||||
posix_kill(-$pgid, SIGKILL);
|
posix_kill(-$pgid, SIGKILL);
|
||||||
$this->pid = null;
|
$this->pid = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,10 +369,12 @@ final class PhutilDaemonHandle extends Phobject {
|
||||||
$this->stdoutBuffer = '';
|
$this->stdoutBuffer = '';
|
||||||
$this->hibernating = false;
|
$this->hibernating = false;
|
||||||
|
|
||||||
$this->future = $this->newExecFuture();
|
$future = $this->newExecFuture();
|
||||||
$this->future->start();
|
$this->future = $future;
|
||||||
|
|
||||||
$this->pid = $this->future->getPID();
|
$pool = $this->getDaemonPool();
|
||||||
|
$overseer = $pool->getOverseer();
|
||||||
|
$overseer->addFutureToPool($future);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function didReadStdout($data) {
|
private function didReadStdout($data) {
|
||||||
|
@ -440,7 +466,10 @@ final class PhutilDaemonHandle extends Phobject {
|
||||||
// naturally be restarted after it exits, as though it had exited after an
|
// naturally be restarted after it exits, as though it had exited after an
|
||||||
// unhandled exception.
|
// unhandled exception.
|
||||||
|
|
||||||
posix_kill($this->getPID(), SIGINT);
|
$pid = $this->getPID();
|
||||||
|
if ($pid) {
|
||||||
|
posix_kill($pid, SIGINT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function didReceiveGracefulSignal($signo) {
|
public function didReceiveGracefulSignal($signo) {
|
||||||
|
@ -461,7 +490,10 @@ final class PhutilDaemonHandle extends Phobject {
|
||||||
|
|
||||||
$this->logMessage('DONE', $sigmsg, $signo);
|
$this->logMessage('DONE', $sigmsg, $signo);
|
||||||
|
|
||||||
posix_kill($this->getPID(), SIGINT);
|
$pid = $this->getPID();
|
||||||
|
if ($pid) {
|
||||||
|
posix_kill($pid, SIGINT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function didReceiveTerminateSignal($signo) {
|
public function didReceiveTerminateSignal($signo) {
|
||||||
|
|
|
@ -181,10 +181,6 @@ EOHELP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($pool->getFutures() as $future) {
|
|
||||||
$future_pool->addFuture($future);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($pool->getDaemons()) {
|
if ($pool->getDaemons()) {
|
||||||
$running_pools = true;
|
$running_pools = true;
|
||||||
}
|
}
|
||||||
|
@ -210,6 +206,11 @@ EOHELP
|
||||||
exit($this->err);
|
exit($this->err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addFutureToPool(Future $future) {
|
||||||
|
$this->getFuturePool()->addFuture($future);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
private function getFuturePool() {
|
private function getFuturePool() {
|
||||||
if (!$this->futurePool) {
|
if (!$this->futurePool) {
|
||||||
$pool = new FuturePool();
|
$pool = new FuturePool();
|
||||||
|
|
|
@ -111,18 +111,6 @@ final class PhutilDaemonPool extends Phobject {
|
||||||
return $this->daemons;
|
return $this->daemons;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFutures() {
|
|
||||||
$futures = array();
|
|
||||||
foreach ($this->getDaemons() as $daemon) {
|
|
||||||
$future = $daemon->getFuture();
|
|
||||||
if ($future) {
|
|
||||||
$futures[] = $future;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $futures;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function didReceiveSignal($signal, $signo) {
|
public function didReceiveSignal($signal, $signo) {
|
||||||
switch ($signal) {
|
switch ($signal) {
|
||||||
case PhutilDaemonOverseer::SIGNAL_GRACEFUL:
|
case PhutilDaemonOverseer::SIGNAL_GRACEFUL:
|
||||||
|
|
|
@ -24,7 +24,7 @@ final class PhabricatorTaskmasterDaemon extends PhabricatorDaemon {
|
||||||
if ($ex) {
|
if ($ex) {
|
||||||
if ($ex instanceof PhabricatorWorkerPermanentFailureException) {
|
if ($ex instanceof PhabricatorWorkerPermanentFailureException) {
|
||||||
// NOTE: Make sure these reach the daemon log, even when not
|
// NOTE: Make sure these reach the daemon log, even when not
|
||||||
// running in "phd.verbose" mode. See T12803 for discussion.
|
// running in verbose mode. See T12803 for discussion.
|
||||||
$log_exception = new PhutilProxyException(
|
$log_exception = new PhutilProxyException(
|
||||||
pht(
|
pht(
|
||||||
'Task "%s" encountered a permanent failure and was '.
|
'Task "%s" encountered a permanent failure and was '.
|
||||||
|
|
|
@ -142,22 +142,9 @@ final class PhutilProseDifferenceEngine extends Phobject {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($level < 2) {
|
if ($level < 2) {
|
||||||
// Split pieces into separate text and whitespace sections: make one
|
$trimmed_pieces = $this->trimApart($result);
|
||||||
// piece out of all the whitespace at the beginning, one piece out of
|
foreach ($trimmed_pieces as $trimmed_piece) {
|
||||||
// all the actual text in the middle, and one piece out of all the
|
$results[] = $trimmed_piece;
|
||||||
// whitespace at the end.
|
|
||||||
|
|
||||||
$matches = null;
|
|
||||||
preg_match('/^(\s*)(.*?)(\s*)\z/s', $result, $matches);
|
|
||||||
|
|
||||||
if (strlen($matches[1])) {
|
|
||||||
$results[] = $matches[1];
|
|
||||||
}
|
|
||||||
if (strlen($matches[2])) {
|
|
||||||
$results[] = $matches[2];
|
|
||||||
}
|
|
||||||
if (strlen($matches[3])) {
|
|
||||||
$results[] = $matches[3];
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$results[] = $result;
|
$results[] = $result;
|
||||||
|
@ -272,4 +259,36 @@ final class PhutilProseDifferenceEngine extends Phobject {
|
||||||
return $blocks;
|
return $blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function trimApart($input) {
|
||||||
|
// Split pieces into separate text and whitespace sections: make one
|
||||||
|
// piece out of all the whitespace at the beginning, one piece out of
|
||||||
|
// all the actual text in the middle, and one piece out of all the
|
||||||
|
// whitespace at the end.
|
||||||
|
|
||||||
|
$parts = array();
|
||||||
|
|
||||||
|
$length = strlen($input);
|
||||||
|
|
||||||
|
$corpus = ltrim($input);
|
||||||
|
$l_length = strlen($corpus);
|
||||||
|
if ($l_length !== $length) {
|
||||||
|
$parts[] = substr($input, 0, $length - $l_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
$corpus = rtrim($corpus);
|
||||||
|
$lr_length = strlen($corpus);
|
||||||
|
|
||||||
|
if ($lr_length) {
|
||||||
|
$parts[] = $corpus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($lr_length !== $l_length) {
|
||||||
|
// NOTE: This will be a negative value; we're slicing from the end of
|
||||||
|
// the input string.
|
||||||
|
$parts[] = substr($input, $lr_length - $l_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parts;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,39 @@
|
||||||
final class PhutilProseDiffTestCase
|
final class PhutilProseDiffTestCase
|
||||||
extends PhabricatorTestCase {
|
extends PhabricatorTestCase {
|
||||||
|
|
||||||
|
public function testTrimApart() {
|
||||||
|
$map = array(
|
||||||
|
'' => array(),
|
||||||
|
'a' => array('a'),
|
||||||
|
' a ' => array(
|
||||||
|
' ',
|
||||||
|
'a',
|
||||||
|
' ',
|
||||||
|
),
|
||||||
|
' a' => array(
|
||||||
|
' ',
|
||||||
|
'a',
|
||||||
|
),
|
||||||
|
'a ' => array(
|
||||||
|
'a',
|
||||||
|
' ',
|
||||||
|
),
|
||||||
|
' a b ' => array(
|
||||||
|
' ',
|
||||||
|
'a b',
|
||||||
|
' ',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($map as $input => $expect) {
|
||||||
|
$actual = PhutilProseDifferenceEngine::trimApart($input);
|
||||||
|
$this->assertEqual(
|
||||||
|
$expect,
|
||||||
|
$actual,
|
||||||
|
pht('Trim Apart: %s', $input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function testProseDiffsDistance() {
|
public function testProseDiffsDistance() {
|
||||||
$this->assertProseParts(
|
$this->assertProseParts(
|
||||||
'',
|
'',
|
||||||
|
|
Loading…
Add table
Reference in a new issue