Page MenuHomePhabricator

D11438.id27511.diff
No OneTemporary

D11438.id27511.diff

diff --git a/bin/trigger b/bin/trigger
new file mode 120000
--- /dev/null
+++ b/bin/trigger
@@ -0,0 +1 @@
+../scripts/setup/manage_trigger.php
\ No newline at end of file
diff --git a/scripts/setup/manage_trigger.php b/scripts/setup/manage_trigger.php
new file mode 100755
--- /dev/null
+++ b/scripts/setup/manage_trigger.php
@@ -0,0 +1,21 @@
+#!/usr/bin/env php
+<?php
+
+$root = dirname(dirname(dirname(__FILE__)));
+require_once $root.'/scripts/__init_script__.php';
+
+$args = new PhutilArgumentParser($argv);
+$args->setTagline('manage triggers');
+$args->setSynopsis(<<<EOSYNOPSIS
+**trigger** __command__ [__options__]
+ Manage event triggers.
+
+EOSYNOPSIS
+ );
+$args->parseStandardArguments();
+
+$workflows = id(new PhutilSymbolLoader())
+ ->setAncestorClass('PhabricatorWorkerTriggerManagementWorkflow')
+ ->loadObjects();
+$workflows[] = new PhutilHelpArgumentWorkflow();
+$args->parseWorkflows($workflows);
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2603,6 +2603,8 @@
'PhabricatorWorkerTestCase' => 'infrastructure/daemon/workers/__tests__/PhabricatorWorkerTestCase.php',
'PhabricatorWorkerTrigger' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTrigger.php',
'PhabricatorWorkerTriggerEvent' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTriggerEvent.php',
+ 'PhabricatorWorkerTriggerManagementFireWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerTriggerManagementFireWorkflow.php',
+ 'PhabricatorWorkerTriggerManagementWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerTriggerManagementWorkflow.php',
'PhabricatorWorkerTriggerPHIDType' => 'infrastructure/daemon/workers/phid/PhabricatorWorkerTriggerPHIDType.php',
'PhabricatorWorkerTriggerQuery' => 'infrastructure/daemon/workers/query/PhabricatorWorkerTriggerQuery.php',
'PhabricatorWorkerYieldException' => 'infrastructure/daemon/workers/exception/PhabricatorWorkerYieldException.php',
@@ -5889,6 +5891,8 @@
'PhabricatorDestructibleInterface',
),
'PhabricatorWorkerTriggerEvent' => 'PhabricatorWorkerDAO',
+ 'PhabricatorWorkerTriggerManagementFireWorkflow' => 'PhabricatorWorkerTriggerManagementWorkflow',
+ 'PhabricatorWorkerTriggerManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorWorkerTriggerPHIDType' => 'PhabricatorPHIDType',
'PhabricatorWorkerTriggerQuery' => 'PhabricatorOffsetPagedQuery',
'PhabricatorWorkerYieldException' => 'Exception',
diff --git a/src/infrastructure/daemon/workers/management/PhabricatorWorkerTriggerManagementFireWorkflow.php b/src/infrastructure/daemon/workers/management/PhabricatorWorkerTriggerManagementFireWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/daemon/workers/management/PhabricatorWorkerTriggerManagementFireWorkflow.php
@@ -0,0 +1,136 @@
+<?php
+
+final class PhabricatorWorkerTriggerManagementFireWorkflow
+ extends PhabricatorWorkerTriggerManagementWorkflow {
+
+ protected function didConstruct() {
+ $this
+ ->setName('fire')
+ ->setExamples('**fire** --id __id__')
+ ->setSynopsis(
+ pht(
+ 'Activates selected triggers, firing them immediately.'))
+ ->setArguments(
+ array_merge(
+ array(
+ array(
+ 'name' => 'now',
+ 'param' => 'time',
+ 'help' => pht(
+ 'Fire the trigger as though the current time is a given '.
+ 'time. This allows you to test how a trigger would behave '.
+ 'if activated in the past or future. Defaults to the actual '.
+ 'current time.'),
+ ),
+ array(
+ 'name' => 'last',
+ 'param' => 'time',
+ 'help' => pht(
+ 'Fire the trigger as though the last event occurred at a '.
+ 'given time. Defaults to the actual last event time.'),
+ ),
+ array(
+ 'name' => 'next',
+ 'param' => 'time',
+ 'help' => pht(
+ 'Fire the trigger as though the next event was scheduled '.
+ 'at a given time. Defaults to the actual time when the '.
+ 'event is next scheduled to fire.'),
+ ),
+ ),
+ $this->getTriggerSelectionArguments()));
+ }
+
+ public function execute(PhutilArgumentParser $args) {
+ $console = PhutilConsole::getConsole();
+ $viewer = $this->getViewer();
+ $triggers = $this->loadTriggers($args);
+
+ $now = $args->getArg('now');
+ $now = $this->parseTime($now);
+ if (!$now) {
+ $now = PhabricatorTime::getNow();
+ }
+
+ PhabricatorTime::pushTime($now, date_default_timezone_get());
+
+ $console->writeOut(
+ "%s\n",
+ pht(
+ 'Set current time to %s.',
+ phabricator_datetime(PhabricatorTime::getNow(), $viewer)));
+
+ $last_time = $this->parseTime($args->getArg('last'));
+ $next_time = $this->parseTime($args->getArg('next'));
+
+ PhabricatorWorker::setRunAllTasksInProcess(true);
+
+ foreach ($triggers as $trigger) {
+ $console->writeOut(
+ "%s\n",
+ pht('Executing trigger %s.', $this->describeTrigger($trigger)));
+
+ $event = $trigger->getEvent();
+ if ($event) {
+ if (!$last_time) {
+ $last_time = $event->getLastEventEpoch();
+ }
+ if (!$next_time) {
+ $next_time = $event->getNextEventEpoch();
+ }
+ }
+
+ if (!$next_time) {
+ $console->writeOut(
+ "%s\n",
+ pht(
+ 'Trigger is not scheduled to execute. Use --at to simluate '.
+ 'a scheduled event.'));
+ continue;
+ } else {
+ $console->writeOut(
+ "%s\n",
+ pht(
+ 'Executing event as though it was scheduled to execute at %s.',
+ phabricator_datetime($next_time, $viewer)));
+ }
+
+ if (!$last_time) {
+ $console->writeOut(
+ "%s\n",
+ pht(
+ 'Executing event as though it never previously executed.'));
+ } else {
+ $console->writeOut(
+ "%s\n",
+ pht(
+ 'Executing event as though it previously executed at %s.',
+ phabricator_datetime($last_time, $viewer)));
+ }
+
+ $trigger->executeTrigger($last_time, $next_time);
+
+ $reschedule_time = $trigger->getNextEventEpoch(
+ $next_time,
+ $is_reschedule = true);
+
+ if (!$reschedule_time) {
+ $console->writeOut(
+ "%s\n",
+ pht(
+ 'After executing under these conditions, this event would never '.
+ 'execute again.'));
+ } else {
+ $console->writeOut(
+ "%s\n",
+ pht(
+ 'After executing under these conditions, this event would '.
+ 'next execute at %s.',
+ phabricator_datetime($reschedule_time, $viewer)));
+ }
+ }
+
+ return 0;
+ }
+
+}
diff --git a/src/infrastructure/daemon/workers/management/PhabricatorWorkerTriggerManagementWorkflow.php b/src/infrastructure/daemon/workers/management/PhabricatorWorkerTriggerManagementWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/daemon/workers/management/PhabricatorWorkerTriggerManagementWorkflow.php
@@ -0,0 +1,57 @@
+<?php
+
+abstract class PhabricatorWorkerTriggerManagementWorkflow
+ extends PhabricatorManagementWorkflow {
+
+ protected function getTriggerSelectionArguments() {
+ return array(
+ array(
+ 'name' => 'id',
+ 'param' => 'id',
+ 'repeat' => true,
+ 'help' => pht('Select one or more triggers by ID.'),
+ ),
+ );
+ }
+
+ protected function loadTriggers(PhutilArgumentParser $args) {
+ $ids = $args->getArg('id');
+ if (!$ids) {
+ throw new PhutilArgumentUsageException(
+ pht('Use --id to select triggers by ID.'));
+ }
+
+ $triggers = id(new PhabricatorWorkerTriggerQuery())
+ ->withIDs($ids)
+ ->needEvents(true)
+ ->execute();
+ $triggers = mpull($triggers, null, 'getID');
+
+ foreach ($ids as $id) {
+ if (empty($triggers[$id])) {
+ throw new PhutilArgumentUsageException(
+ pht('No trigger exists with id "%s"!', $id));
+ }
+ }
+
+ return $triggers;
+ }
+
+ protected function describeTrigger(PhabricatorWorkerTrigger $trigger) {
+ return pht('Trigger %d', $trigger->getID());
+ }
+
+ protected function parseTime($time) {
+ if (!strlen($time)) {
+ return null;
+ }
+
+ $epoch = strtotime($time);
+ if ($epoch <= 0) {
+ throw new PhutilArgumentUsageException(
+ pht('Unable to parse time "%s".', $time));
+ }
+ return $epoch;
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Mar 23 2025, 10:03 PM (4 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7713482
Default Alt Text
D11438.id27511.diff (8 KB)

Event Timeline