Skip to content

Commit

Permalink
Merge pull request #322 from Prospress/issue_319_async_action_apis
Browse files Browse the repository at this point in the history
Add as_enqueue_async_action() and async action APIs
  • Loading branch information
rrennick authored Jul 8, 2019
2 parents 1827888 + cacacea commit 5649d06
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 5 deletions.
22 changes: 22 additions & 0 deletions classes/ActionScheduler_ActionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,28 @@ public function get_stored_action( $status, $hook, array $args = array(), Action
return apply_filters( 'action_scheduler_stored_action_instance', $action, $hook, $args, $schedule, $group );
}

/**
* Enqueue an action to run one time, as soon as possible (rather a specific scheduled time).
*
* This method creates a new action with the NULLSchedule. This schedule maps to a MySQL datetime string of
* 0000-00-00 00:00:00. This is done to create a psuedo "async action" type that is fully backward compatible.
* Existing queries to claim actions claim by date, meaning actions scheduled for 0000-00-00 00:00:00 will
* always be claimed prior to actions scheduled for a specific date. This makes sure that any async action is
* given priority in queue processing. This has the added advantage of making sure async actions can be
* claimed by both the existing WP Cron and WP CLI runners, as well as a new async request runner.
*
* @param string $hook The hook to trigger when this action runs
* @param array $args Args to pass when the hook is triggered
* @param string $group A group to put the action in
*
* @return string The ID of the stored action
*/
public function async( $hook, $args = array(), $group = '' ) {
$schedule = new ActionScheduler_NullSchedule();
$action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
return $this->store( $action );
}

/**
* @param string $hook The hook to trigger when this action runs
* @param array $args Args to pass when the hook is triggered
Expand Down
2 changes: 1 addition & 1 deletion classes/ActionScheduler_ListTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ protected function get_schedule_display_string( ActionScheduler_Schedule $schedu
$schedule_display_string = '';

if ( ! $schedule->next() ) {
return $schedule_display_string;
return '0000-00-00 00:00:00';
}

$next_timestamp = $schedule->next()->getTimestamp();
Expand Down
4 changes: 2 additions & 2 deletions classes/abstracts/ActionScheduler_Store.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ protected function validate_sql_comparator( $comparison_operator ) {
protected function get_scheduled_date_string( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
$next = null === $scheduled_date ? $action->get_schedule()->next() : $scheduled_date;
if ( ! $next ) {
throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'action-scheduler' ) );
return '0000-00-00 00:00:00';
}
$next->setTimezone( new DateTimeZone( 'UTC' ) );

Expand All @@ -166,7 +166,7 @@ protected function get_scheduled_date_string( ActionScheduler_Action $action, Da
protected function get_scheduled_date_string_local( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
$next = null === $scheduled_date ? $action->get_schedule()->next() : $scheduled_date;
if ( ! $next ) {
throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'action-scheduler' ) );
return '0000-00-00 00:00:00';
}

ActionScheduler_TimezoneHelper::set_local_timezone( $next );
Expand Down
20 changes: 18 additions & 2 deletions functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
* General API functions for scheduling actions
*/

/**
* Enqueue an action to run one time, as soon as possible
*
* @param string $hook The hook to trigger.
* @param array $args Arguments to pass when the hook triggers.
* @param string $group The group to assign this job to.
* @return string The action ID.
*/
function as_enqueue_async_action( $hook, $args = array(), $group = '' ) {
return ActionScheduler::factory()->async( $hook, $args, $group );
}

/**
* Schedule an action to run one time
*
Expand Down Expand Up @@ -109,10 +121,12 @@ function as_unschedule_all_actions( $hook, $args = array(), $group = '' ) {
* @param array $args
* @param string $group
*
* @return int|bool The timestamp for the next occurrence, or false if nothing was found
* @return int|bool The timestamp for the next occurrence of a scheduled action, true for an async action or false if there is no matching, pending action.
*/
function as_next_scheduled_action( $hook, $args = NULL, $group = '' ) {
$params = array();
$params = array(
'status' => ActionScheduler_Store::STATUS_PENDING,
);
if ( is_array($args) ) {
$params['args'] = $args;
}
Expand All @@ -127,6 +141,8 @@ function as_next_scheduled_action( $hook, $args = NULL, $group = '' ) {
$next = $job->get_schedule()->next();
if ( $next ) {
return (int)($next->format('U'));
} elseif ( NULL === $next ) { // pending async action with NullSchedule
return true;
}
return false;
}
Expand Down
26 changes: 26 additions & 0 deletions tests/phpunit/procedural_api/procedural_api_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,32 @@ public function test_get_next() {
$this->assertEquals( $time->getTimestamp(), $next );
}

public function test_get_next_async() {
$hook = md5(rand());
$action_id = as_enqueue_async_action( $hook );

$next = as_next_scheduled_action( $hook );

$this->assertTrue( $next );

$store = ActionScheduler::store();

// Completed async actions should still return false
$store->mark_complete( $action_id );
$next = as_next_scheduled_action( $hook );
$this->assertFalse( $next );

// Failed async actions should still return false
$store->mark_failure( $action_id );
$next = as_next_scheduled_action( $hook );
$this->assertFalse( $next );

// Cancelled async actions should still return false
$store->cancel_action( $action_id );
$next = as_next_scheduled_action( $hook );
$this->assertFalse( $next );
}

public function provider_time_hook_args_group() {
$time = time() + 60 * 2;
$hook = md5( rand() );
Expand Down

0 comments on commit 5649d06

Please sign in to comment.