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 @@ -2362,6 +2362,7 @@ 'PhabricatorSSHWorkflow' => 'infrastructure/ssh/PhabricatorSSHWorkflow.php', 'PhabricatorSavedQuery' => 'applications/search/storage/PhabricatorSavedQuery.php', 'PhabricatorSavedQueryQuery' => 'applications/search/query/PhabricatorSavedQueryQuery.php', + 'PhabricatorScheduleTaskTriggerAction' => 'infrastructure/daemon/workers/action/PhabricatorScheduleTaskTriggerAction.php', 'PhabricatorScopedEnv' => 'infrastructure/env/PhabricatorScopedEnv.php', 'PhabricatorSearchAbstractDocument' => 'applications/search/index/PhabricatorSearchAbstractDocument.php', 'PhabricatorSearchApplication' => 'applications/search/application/PhabricatorSearchApplication.php', @@ -5643,6 +5644,7 @@ 'PhabricatorPolicyInterface', ), 'PhabricatorSavedQueryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorScheduleTaskTriggerAction' => 'PhabricatorTriggerAction', 'PhabricatorSearchApplication' => 'PhabricatorApplication', 'PhabricatorSearchApplicationSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorSearchAttachController' => 'PhabricatorSearchBaseController', diff --git a/src/infrastructure/daemon/workers/action/PhabricatorScheduleTaskTriggerAction.php b/src/infrastructure/daemon/workers/action/PhabricatorScheduleTaskTriggerAction.php new file mode 100644 --- /dev/null +++ b/src/infrastructure/daemon/workers/action/PhabricatorScheduleTaskTriggerAction.php @@ -0,0 +1,45 @@ +<?php + +/** + * Trigger action which queues a task. + * + * Most triggers should take this action: triggers need to execute as quickly + * as possible, and should generally queue tasks instead of doing any real + * work. + * + * In some cases, triggers could execute more quickly by examining the + * scheduled action time and comparing it to the current time, then exiting + * early if the trigger is executing too far away from real time (for example, + * it might not make sense to send a meeting reminder after a meeting already + * happened). + * + * However, in most cases the task needs to have this logic anyway (because + * there may be another arbitrarily long delay between when this code executes + * and when the task executes), and the cost of queueing a task is very small, + * and situations where triggers are executing far away from real time should + * be rare (major downtime or serious problems with the pipeline). + * + * The properties of this action map to the parameters of + * @{method:PhabricatorWorker::scheduleTask}. + */ +final class PhabricatorScheduleTaskTriggerAction + extends PhabricatorTriggerAction { + + public function validateProperties(array $properties) { + PhutilTypeSpec::checkMap( + $properties, + array( + 'class' => 'string', + 'data' => 'map<string, wild>', + 'options' => 'map<string, wild>', + )); + } + + public function execute($last_epoch, $this_epoch) { + PhabricatorWorker::scheduleTask( + $this->getProperty('class'), + $this->getProperty('data'), + $this->getProperty('options')); + } + +} diff --git a/src/infrastructure/daemon/workers/action/PhabricatorTriggerAction.php b/src/infrastructure/daemon/workers/action/PhabricatorTriggerAction.php --- a/src/infrastructure/daemon/workers/action/PhabricatorTriggerAction.php +++ b/src/infrastructure/daemon/workers/action/PhabricatorTriggerAction.php @@ -2,6 +2,10 @@ /** * A trigger action reacts to a scheduled event. + * + * Almost all events should use a @{class:PhabricatorScheduleTaskTriggerAction}. + * Avoid introducing new actions without strong justification. See that class + * for discussion of concerns. */ abstract class PhabricatorTriggerAction extends Phobject { @@ -41,6 +45,9 @@ * performing processing directly, triggers can execute more involved actions * without blocking other triggers. * + * Almost all events should use @{class:PhabricatorScheduleTaskTriggerAction} + * to do this, ensuring that they execute quickly. + * * An action may trigger a long time after it is scheduled. For example, * a meeting reminder may be scheduled at 9:45 AM, but the action may not * execute until later (for example, because the server was down for