1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-23 05:01:13 +01:00

(stable) Promote 2019 Week 26

This commit is contained in:
epriestley 2019-06-28 17:38:58 -07:00
commit 4c242256e4
10 changed files with 202 additions and 455 deletions

View file

@ -10,7 +10,7 @@ return array(
'conpherence.pkg.css' => '3c8a0668', 'conpherence.pkg.css' => '3c8a0668',
'conpherence.pkg.js' => '020aebcf', 'conpherence.pkg.js' => '020aebcf',
'core.pkg.css' => 'af983028', 'core.pkg.css' => 'af983028',
'core.pkg.js' => '8225dc58', 'core.pkg.js' => '5a792749',
'differential.pkg.css' => '8d8360fb', 'differential.pkg.css' => '8d8360fb',
'differential.pkg.js' => '67e02996', 'differential.pkg.js' => '67e02996',
'diffusion.pkg.css' => '42c75c37', 'diffusion.pkg.css' => '42c75c37',
@ -253,7 +253,7 @@ return array(
'rsrc/externals/javelin/lib/URI.js' => '2e255291', 'rsrc/externals/javelin/lib/URI.js' => '2e255291',
'rsrc/externals/javelin/lib/Vector.js' => 'e9c80beb', 'rsrc/externals/javelin/lib/Vector.js' => 'e9c80beb',
'rsrc/externals/javelin/lib/WebSocket.js' => 'fdc13e4e', 'rsrc/externals/javelin/lib/WebSocket.js' => 'fdc13e4e',
'rsrc/externals/javelin/lib/Workflow.js' => '851f642d', 'rsrc/externals/javelin/lib/Workflow.js' => '445e21a8',
'rsrc/externals/javelin/lib/__tests__/Cookie.js' => 'ca686f71', 'rsrc/externals/javelin/lib/__tests__/Cookie.js' => 'ca686f71',
'rsrc/externals/javelin/lib/__tests__/DOM.js' => '4566e249', 'rsrc/externals/javelin/lib/__tests__/DOM.js' => '4566e249',
'rsrc/externals/javelin/lib/__tests__/JSON.js' => '710377ae', 'rsrc/externals/javelin/lib/__tests__/JSON.js' => '710377ae',
@ -752,7 +752,7 @@ return array(
'javelin-workboard-header' => '111bfd2d', 'javelin-workboard-header' => '111bfd2d',
'javelin-workboard-header-template' => 'ebe83a6b', 'javelin-workboard-header-template' => 'ebe83a6b',
'javelin-workboard-order-template' => '03e8891f', 'javelin-workboard-order-template' => '03e8891f',
'javelin-workflow' => '851f642d', 'javelin-workflow' => '445e21a8',
'maniphest-report-css' => '3d53188b', 'maniphest-report-css' => '3d53188b',
'maniphest-task-edit-css' => '272daa84', 'maniphest-task-edit-css' => '272daa84',
'maniphest-task-summary-css' => '61d1667e', 'maniphest-task-summary-css' => '61d1667e',
@ -1294,6 +1294,17 @@ return array(
'43bc9360' => array( '43bc9360' => array(
'javelin-install', 'javelin-install',
), ),
'445e21a8' => array(
'javelin-stratcom',
'javelin-request',
'javelin-dom',
'javelin-vector',
'javelin-install',
'javelin-util',
'javelin-mask',
'javelin-uri',
'javelin-routable',
),
'46116c01' => array( '46116c01' => array(
'javelin-request', 'javelin-request',
'javelin-behavior', 'javelin-behavior',
@ -1607,17 +1618,6 @@ return array(
'javelin-resource', 'javelin-resource',
'javelin-routable', 'javelin-routable',
), ),
'851f642d' => array(
'javelin-stratcom',
'javelin-request',
'javelin-dom',
'javelin-vector',
'javelin-install',
'javelin-util',
'javelin-mask',
'javelin-uri',
'javelin-routable',
),
'87428eb2' => array( '87428eb2' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-diffusion-locate-file-source', 'javelin-diffusion-locate-file-source',

View file

@ -536,6 +536,9 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
'differential.whitespace-matters' => pht( 'differential.whitespace-matters' => pht(
'Whitespace rendering is now handled automatically.'), 'Whitespace rendering is now handled automatically.'),
'phd.pid-directory' => pht(
'Phabricator daemons no longer use PID files.'),
); );
return $ancient_config; return $ancient_config;

View file

@ -21,10 +21,6 @@ final class PhabricatorPHDConfigOptions
public function getOptions() { public function getOptions() {
return array( return array(
$this->newOption('phd.pid-directory', 'string', '/var/tmp/phd/pid')
->setLocked(true)
->setDescription(
pht('Directory that phd should use to track running daemons.')),
$this->newOption('phd.log-directory', 'string', '/var/tmp/phd/log') $this->newOption('phd.log-directory', 'string', '/var/tmp/phd/log')
->setLocked(true) ->setLocked(true)
->setDescription( ->setDescription(

View file

@ -6,7 +6,10 @@ final class PhabricatorDaemonManagementRestartWorkflow
protected function didConstruct() { protected function didConstruct() {
$this $this
->setName('restart') ->setName('restart')
->setSynopsis(pht('Stop, then start the standard daemon loadout.')) ->setSynopsis(
pht(
'Stop daemon processes on this host, then start the standard '.
'daemon loadout.'))
->setArguments( ->setArguments(
array( array(
array( array(
@ -17,17 +20,15 @@ final class PhabricatorDaemonManagementRestartWorkflow
'seconds. Defaults to __15__ seconds.'), 'seconds. Defaults to __15__ seconds.'),
'default' => 15, 'default' => 15,
), ),
array(
'name' => 'gently',
'help' => pht(
'Ignore running processes that look like daemons but do not '.
'have corresponding PID files.'),
),
array( array(
'name' => 'force', 'name' => 'force',
'help' => pht( 'help' => pht(
'Also stop running processes that look like daemons but do '. 'Stop all daemon processes on this host, even if they belong '.
'not have corresponding PID files.'), 'to another Phabricator instance.'),
),
array(
'name' => 'gently',
'help' => pht('Deprecated. Has no effect.'),
), ),
$this->getAutoscaleReserveArgument(), $this->getAutoscaleReserveArgument(),
)); ));
@ -35,12 +36,11 @@ final class PhabricatorDaemonManagementRestartWorkflow
public function execute(PhutilArgumentParser $args) { public function execute(PhutilArgumentParser $args) {
$err = $this->executeStopCommand( $err = $this->executeStopCommand(
array(),
array( array(
'graceful' => $args->getArg('graceful'), 'graceful' => $args->getArg('graceful'),
'force' => $args->getArg('force'), 'force' => $args->getArg('force'),
'gently' => $args->getArg('gently'),
)); ));
if ($err) { if ($err) {
return $err; return $err;
} }

View file

@ -6,101 +6,52 @@ final class PhabricatorDaemonManagementStatusWorkflow
protected function didConstruct() { protected function didConstruct() {
$this $this
->setName('status') ->setName('status')
->setSynopsis(pht('Show status of running daemons.')) ->setSynopsis(pht('Show daemon processes on this host.'));
->setArguments(
array(
array(
'name' => 'local',
'help' => pht('Show only local daemons.'),
),
));
} }
public function execute(PhutilArgumentParser $args) { public function execute(PhutilArgumentParser $args) {
$console = PhutilConsole::getConsole(); $process_refs = $this->getOverseerProcessRefs();
if ($args->getArg('local')) { if (!$process_refs) {
$daemons = $this->loadRunningDaemons(); $instance = $this->getInstance();
} else { if ($instance !== null) {
$daemons = $this->loadAllRunningDaemons(); $this->logInfo(
} pht('NO DAEMONS'),
pht(
'There are no running daemon processes for the current '.
'instance ("%s").',
$instance));
} else {
$this->writeInfo(
pht('NO DAEMONS'),
pht('There are no running daemon processes.'));
}
if (!$daemons) {
$console->writeErr(
"%s\n",
pht('There are no running Phabricator daemons.'));
return 1; return 1;
} }
$status = 0;
$table = id(new PhutilConsoleTable()) $table = id(new PhutilConsoleTable())
->addColumns(array( ->addColumns(
'id' => array( array(
'title' => pht('Log'), 'pid' => array(
), 'title' => pht('PID'),
'daemonID' => array( ),
'title' => pht('Daemon'), 'command' => array(
), 'title' => pht('Command'),
'host' => array( ),
'title' => pht('Host'),
),
'pid' => array(
'title' => pht('Overseer'),
),
'started' => array(
'title' => pht('Started'),
),
'daemon' => array(
'title' => pht('Class'),
),
'argv' => array(
'title' => pht('Arguments'),
),
));
foreach ($daemons as $daemon) {
if ($daemon instanceof PhabricatorDaemonLog) {
$table->addRow(array(
'id' => $daemon->getID(),
'daemonID' => $daemon->getDaemonID(),
'host' => $daemon->getHost(),
'pid' => $daemon->getPID(),
'started' => date('M j Y, g:i:s A', $daemon->getDateCreated()),
'daemon' => $daemon->getDaemon(),
'argv' => csprintf('%LR', $daemon->getExplicitArgv()),
)); ));
} else if ($daemon instanceof PhabricatorDaemonReference) {
$name = $daemon->getName();
if (!$daemon->isRunning()) {
$daemon->updateStatus(PhabricatorDaemonLog::STATUS_DEAD);
$status = 2;
$name = pht('<DEAD> %s', $name);
}
$daemon_log = $daemon->getDaemonLog(); foreach ($process_refs as $process_ref) {
$id = null; $table->addRow(
$daemon_id = null; array(
if ($daemon_log) { 'pid' => $process_ref->getPID(),
$id = $daemon_log->getID(); 'command' => $process_ref->getCommand(),
$daemon_id = $daemon_log->getDaemonID();
}
$table->addRow(array(
'id' => $id,
'daemonID' => $daemon_id,
'host' => 'localhost',
'pid' => $daemon->getPID(),
'started' => $daemon->getEpochStarted()
? date('M j Y, g:i:s A', $daemon->getEpochStarted())
: null,
'daemon' => $name,
'argv' => csprintf('%LR', $daemon->getArgv()),
)); ));
}
} }
$table->draw(); $table->draw();
return 0;
} }
} }

View file

@ -6,11 +6,7 @@ final class PhabricatorDaemonManagementStopWorkflow
protected function didConstruct() { protected function didConstruct() {
$this $this
->setName('stop') ->setName('stop')
->setSynopsis( ->setSynopsis(pht('Stop daemon processes on this host.'))
pht(
'Stop all running daemons, or specific daemons identified by PIDs. '.
'Use **%s** to find PIDs.',
'phd status'))
->setArguments( ->setArguments(
array( array(
array( array(
@ -24,29 +20,21 @@ final class PhabricatorDaemonManagementStopWorkflow
array( array(
'name' => 'force', 'name' => 'force',
'help' => pht( 'help' => pht(
'Also stop running processes that look like daemons but do '. 'Stop all daemon processes on this host, even if they belong '.
'not have corresponding PID files.'), 'to another Phabricator instance.'),
), ),
array( array(
'name' => 'gently', 'name' => 'gently',
'help' => pht( 'help' => pht('Deprecated. Has no effect.'),
'Ignore running processes that look like daemons but do not '.
'have corresponding PID files.'),
),
array(
'name' => 'pids',
'wildcard' => true,
), ),
)); ));
} }
public function execute(PhutilArgumentParser $args) { public function execute(PhutilArgumentParser $args) {
return $this->executeStopCommand( return $this->executeStopCommand(
$args->getArg('pids'),
array( array(
'graceful' => $args->getArg('graceful'), 'graceful' => $args->getArg('graceful'),
'force' => $args->getArg('force'), 'force' => $args->getArg('force'),
'gently' => $args->getArg('gently'),
)); ));
} }

View file

@ -12,11 +12,6 @@ abstract class PhabricatorDaemonManagementWorkflow
->selectSymbolsWithoutLoading(); ->selectSymbolsWithoutLoading();
} }
final protected function getPIDDirectory() {
$path = PhabricatorEnv::getEnvConfig('phd.pid-directory');
return $this->getControlDirectory($path);
}
final protected function getLogDirectory() { final protected function getLogDirectory() {
$path = PhabricatorEnv::getEnvConfig('phd.log-directory'); $path = PhabricatorEnv::getEnvConfig('phd.log-directory');
return $this->getControlDirectory($path); return $this->getControlDirectory($path);
@ -30,56 +25,16 @@ abstract class PhabricatorDaemonManagementWorkflow
pht( pht(
"%s requires the directory '%s' to exist, but it does not exist ". "%s requires the directory '%s' to exist, but it does not exist ".
"and could not be created. Create this directory or update ". "and could not be created. Create this directory or update ".
"'%s' / '%s' in your configuration to point to an existing ". "'%s' in your configuration to point to an existing ".
"directory.", "directory.",
'phd', 'phd',
$path, $path,
'phd.pid-directory',
'phd.log-directory')); 'phd.log-directory'));
} }
} }
return $path; return $path;
} }
final protected function loadRunningDaemons() {
$daemons = array();
$pid_dir = $this->getPIDDirectory();
$pid_files = Filesystem::listDirectory($pid_dir);
foreach ($pid_files as $pid_file) {
$path = $pid_dir.'/'.$pid_file;
$daemons[] = PhabricatorDaemonReference::loadReferencesFromFile($path);
}
return array_mergev($daemons);
}
final protected function loadAllRunningDaemons() {
$local_daemons = $this->loadRunningDaemons();
$local_ids = array();
foreach ($local_daemons as $daemon) {
$daemon_log = $daemon->getDaemonLog();
if ($daemon_log) {
$local_ids[] = $daemon_log->getID();
}
}
$daemon_query = id(new PhabricatorDaemonLogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE);
if ($local_ids) {
$daemon_query->withoutIDs($local_ids);
}
$remote_daemons = $daemon_query->execute();
return array_merge($local_daemons, $remote_daemons);
}
private function findDaemonClass($substring) { private function findDaemonClass($substring) {
$symbols = $this->loadAvailableDaemonClasses(); $symbols = $this->loadAvailableDaemonClasses();
@ -169,7 +124,7 @@ abstract class PhabricatorDaemonManagementWorkflow
$flags[] = '--verbose'; $flags[] = '--verbose';
} }
$instance = PhabricatorEnv::getEnvConfig('cluster.instance'); $instance = $this->getInstance();
if ($instance) { if ($instance) {
$flags[] = '-l'; $flags[] = '-l';
$flags[] = $instance; $flags[] = $instance;
@ -185,14 +140,6 @@ abstract class PhabricatorDaemonManagementWorkflow
$config['log'] = $this->getLogDirectory().'/daemons.log'; $config['log'] = $this->getLogDirectory().'/daemons.log';
} }
$pid_dir = $this->getPIDDirectory();
// TODO: This should be a much better user experience.
Filesystem::assertExists($pid_dir);
Filesystem::assertIsDirectory($pid_dir);
Filesystem::assertWritable($pid_dir);
$config['piddir'] = $pid_dir;
$config['daemons'] = $daemons; $config['daemons'] = $daemons;
$command = csprintf('./phd-daemon %Ls', $flags); $command = csprintf('./phd-daemon %Ls', $flags);
@ -324,28 +271,31 @@ abstract class PhabricatorDaemonManagementWorkflow
$console = PhutilConsole::getConsole(); $console = PhutilConsole::getConsole();
if (!idx($options, 'force')) { if (!idx($options, 'force')) {
$running = $this->loadRunningDaemons(); $process_refs = $this->getOverseerProcessRefs();
if ($process_refs) {
$this->logWarn(
pht('RUNNING DAEMONS'),
pht('Daemons are already running:'));
// This may include daemons which were launched but which are no longer fprintf(STDERR, '%s', "\n");
// running; check that we actually have active daemons before failing. foreach ($process_refs as $process_ref) {
foreach ($running as $daemon) { fprintf(
if ($daemon->isRunning()) { STDERR,
$message = pht( '%s',
"phd start: Unable to start daemons because daemons are already ". tsprintf(
"running.\n\n". " %s %s\n",
"You can view running daemons with '%s'.\n". $process_ref->getPID(),
"You can stop running daemons with '%s'.\n". $process_ref->getCommand()));
"You can use '%s' to stop all daemons before starting ".
"new daemons.\n".
"You can force daemons to start anyway with %s.",
'phd status',
'phd stop',
'phd restart',
'--force');
$console->writeErr("%s\n", $message);
exit(1);
} }
fprintf(STDERR, '%s', "\n");
$this->logFail(
pht('RUNNING DAEMONS'),
pht(
'Use "phd stop" to stop daemons, "phd restart" to restart '.
'daemons, or "phd start --force" to ignore running processes.'));
exit(1);
} }
} }
@ -386,148 +336,115 @@ abstract class PhabricatorDaemonManagementWorkflow
return 0; return 0;
} }
final protected function executeStopCommand( final protected function executeStopCommand(array $options) {
array $pids,
array $options) {
$console = PhutilConsole::getConsole();
$grace_period = idx($options, 'graceful', 15); $grace_period = idx($options, 'graceful', 15);
$force = idx($options, 'force'); $force = idx($options, 'force');
$gently = idx($options, 'gently');
if ($gently && $force) { $query = id(new PhutilProcessQuery())
throw new PhutilArgumentUsageException( ->withIsOverseer(true);
$instance = $this->getInstance();
if ($instance !== null && !$force) {
$query->withInstances(array($instance));
}
try {
$process_refs = $query->execute();
} catch (Exception $ex) {
// See T13321. If this fails for some reason, just continue for now so
// that daemon management still works. In the long run, we don't expect
// this to fail, but I don't want to break this workflow while we iron
// bugs out.
// See T12827. Particularly, this is likely to fail on Solaris.
phlog($ex);
$process_refs = array();
}
if (!$process_refs) {
if ($instance !== null && !$force) {
$this->logInfo(
pht('NO DAEMONS'),
pht(
'There are no running daemons for the current instance ("%s"). '.
'Use "--force" to stop daemons for all instances.',
$instance));
} else {
$this->logInfo(
pht('NO DAEMONS'),
pht('There are no running daemons.'));
}
return 0;
}
$process_refs = mpull($process_refs, null, 'getPID');
$stop_pids = array_keys($process_refs);
$live_pids = $this->sendStopSignals($stop_pids, $grace_period);
$stop_pids = array_fuse($stop_pids);
$live_pids = array_fuse($live_pids);
$dead_pids = array_diff_key($stop_pids, $live_pids);
foreach ($dead_pids as $dead_pid) {
$dead_ref = $process_refs[$dead_pid];
$this->logOkay(
pht('STOP'),
pht( pht(
'You can not specify conflicting options %s and %s together.', 'Stopped PID %d ("%s")',
'--gently', $dead_pid,
'--force')); $dead_ref->getCommand()));
} }
$daemons = $this->loadRunningDaemons(); foreach ($live_pids as $live_pid) {
if (!$daemons) { $live_ref = $process_refs[$live_pid];
$survivors = array(); $this->logFail(
if (!$pids && !$gently) { pht('SURVIVED'),
$survivors = $this->processRogueDaemons( pht(
$grace_period, 'Unable to stop PID %d ("%s").',
$warn = true, $live_pid,
$force); $live_ref->getCommand()));
}
if (!$survivors) {
$console->writeErr(
"%s\n",
pht('There are no running Phabricator daemons.'));
}
return 0;
} }
$stop_pids = $this->selectDaemonPIDs($daemons, $pids); if ($live_pids) {
$this->logWarn(
if (!$stop_pids) { pht('SURVIVORS'),
$console->writeErr("%s\n", pht('No daemons to kill.')); pht(
return 0; 'Unable to stop all daemon processes. You may need to run this '.
} 'command as root with "sudo".'));
$survivors = $this->sendStopSignals($stop_pids, $grace_period);
// Try to clean up PID files for daemons we killed.
$remove = array();
foreach ($daemons as $daemon) {
$pid = $daemon->getPID();
if (empty($stop_pids[$pid])) {
// We did not try to stop this overseer.
continue;
}
if (isset($survivors[$pid])) {
// We weren't able to stop this overseer.
continue;
}
if (!$daemon->getPIDFile()) {
// We don't know where the PID file is.
continue;
}
$remove[] = $daemon->getPIDFile();
}
foreach (array_unique($remove) as $remove_file) {
Filesystem::remove($remove_file);
}
if (!$gently) {
$this->processRogueDaemons($grace_period, !$pids, $force);
} }
return 0; return 0;
} }
final protected function executeReloadCommand(array $pids) { final protected function executeReloadCommand(array $pids) {
$console = PhutilConsole::getConsole(); $process_refs = $this->getOverseerProcessRefs();
if (!$process_refs) {
$this->logInfo(
pht('NO DAEMONS'),
pht('There are no running daemon processes to reload.'));
$daemons = $this->loadRunningDaemons();
if (!$daemons) {
$console->writeErr(
"%s\n",
pht('There are no running daemons to reload.'));
return 0; return 0;
} }
$reload_pids = $this->selectDaemonPIDs($daemons, $pids); foreach ($process_refs as $process_ref) {
if (!$reload_pids) { $pid = $process_ref->getPID();
$console->writeErr(
"%s\n",
pht('No daemons to reload.'));
return 0;
}
foreach ($reload_pids as $pid) { $this->logInfo(
$console->writeOut( pht('RELOAD'),
"%s\n",
pht('Reloading process %d...', $pid)); pht('Reloading process %d...', $pid));
posix_kill($pid, SIGHUP); posix_kill($pid, SIGHUP);
} }
return 0; return 0;
} }
private function processRogueDaemons($grace_period, $warn, $force_stop) {
$console = PhutilConsole::getConsole();
$rogue_daemons = PhutilDaemonOverseer::findRunningDaemons();
if ($rogue_daemons) {
if ($force_stop) {
$rogue_pids = ipull($rogue_daemons, 'pid');
$survivors = $this->sendStopSignals($rogue_pids, $grace_period);
if ($survivors) {
$console->writeErr(
"%s\n",
pht(
'Unable to stop processes running without PID files. '.
'Try running this command again with sudo.'));
}
} else if ($warn) {
$console->writeErr("%s\n", $this->getForceStopHint($rogue_daemons));
}
}
return $rogue_daemons;
}
private function getForceStopHint($rogue_daemons) {
$debug_output = '';
foreach ($rogue_daemons as $rogue) {
$debug_output .= $rogue['pid'].' '.$rogue['command']."\n";
}
return pht(
"There are processes running that look like Phabricator daemons but ".
"have no corresponding PID files:\n\n%s\n\n".
"Stop these processes by re-running this command with the %s parameter.",
$debug_output,
'--force');
}
private function sendStopSignals($pids, $grace_period) { private function sendStopSignals($pids, $grace_period) {
// If we're doing a graceful shutdown, try SIGINT first. // If we're doing a graceful shutdown, try SIGINT first.
if ($grace_period) { if ($grace_period) {
@ -674,4 +591,21 @@ abstract class PhabricatorDaemonManagementWorkflow
return $select_pids; return $select_pids;
} }
protected function getOverseerProcessRefs() {
$query = id(new PhutilProcessQuery())
->withIsOverseer(true);
$instance = PhabricatorEnv::getEnvConfig('cluster.instance');
if ($instance !== null) {
$query->withInstances(array($instance));
}
return $query->execute();
}
protected function getInstance() {
return PhabricatorEnv::getEnvConfig('cluster.instance');
}
} }

View file

@ -1375,16 +1375,16 @@ abstract class PhabricatorApplicationTransaction
public function getActionStrength() { public function getActionStrength() {
if ($this->isInlineCommentTransaction()) { if ($this->isInlineCommentTransaction()) {
return 250; return 25;
} }
switch ($this->getTransactionType()) { switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT: case PhabricatorTransactions::TYPE_COMMENT:
return 500; return 50;
case PhabricatorTransactions::TYPE_SUBSCRIBERS: case PhabricatorTransactions::TYPE_SUBSCRIBERS:
if ($this->isSelfSubscription()) { if ($this->isSelfSubscription()) {
// Make this weaker than TYPE_COMMENT. // Make this weaker than TYPE_COMMENT.
return 250; return 25;
} }
if ($this->isApplicationAuthor()) { if ($this->isApplicationAuthor()) {
@ -1396,14 +1396,14 @@ abstract class PhabricatorApplicationTransaction
// In other cases, subscriptions are more interesting than comments // In other cases, subscriptions are more interesting than comments
// (which are shown anyway) but less interesting than any other type of // (which are shown anyway) but less interesting than any other type of
// transaction. // transaction.
return 750; return 75;
case PhabricatorTransactions::TYPE_MFA: case PhabricatorTransactions::TYPE_MFA:
// We want MFA signatures to render at the top of transaction groups, // We want MFA signatures to render at the top of transaction groups,
// on top of the things they signed. // on top of the things they signed.
return 10000; return 1000;
} }
return 1000; return 100;
} }
public function isCommentTransaction() { public function isCommentTransaction() {

View file

@ -1,128 +1,10 @@
<?php <?php
// TODO: See T13321. After the removal of daemon PID files this class
// no longer makes as much sense as it once did.
final class PhabricatorDaemonReference extends Phobject { final class PhabricatorDaemonReference extends Phobject {
private $name;
private $argv;
private $pid;
private $start;
private $pidFile;
private $daemonLog;
public static function loadReferencesFromFile($path) {
$pid_data = Filesystem::readFile($path);
try {
$dict = phutil_json_decode($pid_data);
} catch (PhutilJSONParserException $ex) {
$dict = array();
}
$refs = array();
$daemons = idx($dict, 'daemons', array());
$logs = array();
$daemon_ids = ipull($daemons, 'id');
if ($daemon_ids) {
try {
$logs = id(new PhabricatorDaemonLogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withDaemonIDs($daemon_ids)
->execute();
} catch (AphrontQueryException $ex) {
// Ignore any issues here; getting this information only allows us
// to provide a more complete picture of daemon status, and we want
// these commands to work if the database is inaccessible.
}
$logs = mpull($logs, null, 'getDaemonID');
}
// Support PID files that use the old daemon format, where each overseer
// had exactly one daemon. We can eventually remove this; they will still
// be stopped by `phd stop --force` even if we don't identify them here.
if (!$daemons && idx($dict, 'name')) {
$daemons = array(
array(
'config' => array(
'class' => idx($dict, 'name'),
'argv' => idx($dict, 'argv', array()),
),
),
);
}
foreach ($daemons as $daemon) {
$ref = new PhabricatorDaemonReference();
// NOTE: This is the overseer PID, not the actual daemon process PID.
// This is correct for checking status and sending signals (the only
// things we do with it), but might be confusing. $daemon['pid'] has
// the daemon PID, and we could expose that if we had some use for it.
$ref->pid = idx($dict, 'pid');
$ref->start = idx($dict, 'start');
$config = idx($daemon, 'config', array());
$ref->name = idx($config, 'class');
$ref->argv = idx($config, 'argv', array());
$log = idx($logs, idx($daemon, 'id'));
if ($log) {
$ref->daemonLog = $log;
}
$ref->pidFile = $path;
$refs[] = $ref;
}
return $refs;
}
public function updateStatus($new_status) {
if (!$this->daemonLog) {
return;
}
try {
$this->daemonLog
->setStatus($new_status)
->save();
} catch (AphrontQueryException $ex) {
// Ignore anything that goes wrong here.
}
}
public function getPID() {
return $this->pid;
}
public function getName() {
return $this->name;
}
public function getArgv() {
return $this->argv;
}
public function getEpochStarted() {
return $this->start;
}
public function getPIDFile() {
return $this->pidFile;
}
public function getDaemonLog() {
return $this->daemonLog;
}
public function isRunning() {
return self::isProcessRunning($this->getPID());
}
public static function isProcessRunning($pid) { public static function isProcessRunning($pid) {
if (!$pid) { if (!$pid) {
return false; return false;
@ -148,15 +30,4 @@ final class PhabricatorDaemonReference extends Phobject {
return $is_running; return $is_running;
} }
public function waitForExit($seconds) {
$start = time();
while (time() < $start + $seconds) {
usleep(100000);
if (!$this->isRunning()) {
return true;
}
}
return !$this->isRunning();
}
} }

View file

@ -104,7 +104,11 @@ JX.install('Workflow', {
var link = event.getNode('tag:a'); var link = event.getNode('tag:a');
// If the link is an anchor, or does not go anywhere, ignore the event. // If the link is an anchor, or does not go anywhere, ignore the event.
var href = '' + link.getAttribute('href'); var href = link.getAttribute('href');
if (typeof href !== 'string') {
return;
}
if (!href.length || href[0] === '#') { if (!href.length || href[0] === '#') {
return; return;
} }