action-scheduler icon indicating copy to clipboard operation
action-scheduler copied to clipboard

Make it easier to determine if we are 'inside' a queue processor

Open remcotolsma opened this issue 1 year ago • 5 comments

It could be useful to other developers if we make it easier to detect when code is executing in the context of the Action Scheduler queue. There are various patterns/strategies to determine this already, but it's not quite as straightforward as it might be. We should at least consider the proposal in this comment. Original description follows.


We know that WordPress sometimes increases the timeout of HTTP requests when initiated via the WordPress cron.

$options = array(
	'timeout' => wp_doing_cron() ? 30 : 3,
);

See for example:

  • https://github.com/WordPress/WordPress/blob/f4b5da285990e948e7b40ba53be5037aed2ae07b/wp-admin/includes/update.php#L141-L145
  • https://github.com/WordPress/WordPress/blob/f4b5da285990e948e7b40ba53be5037aed2ae07b/wp-includes/update.php#L190-L202
  • https://github.com/WordPress/WordPress/blob/f4b5da285990e948e7b40ba53be5037aed2ae07b/wp-includes/update.php#L410-L440

We'd like to do something similar for tasks initiated through this library. However, it seems that wp_doing_cron() does not always return true when running "Action Scheduler" tasks. In the codebase of this library there is also no define( 'DOING_CRON', true ); as in WordPress:

/**
 * Tell WordPress the cron task is running.
 *
 * @var bool
 */
define( 'DOING_CRON', true );

https://github.com/WordPress/WordPress/blob/f4b5da285990e948e7b40ba53be5037aed2ae07b/wp-cron.php#L37-L42

Now we might be able to catch this with a piece of code as follows:

\add_action( 'action_scheduler_run_queue', function () {
	if ( \defined( 'DOING_CRON' ) ) {
		return;
	}

	define( 'DOING_CRON', true );
} );

However, we wonder whether this is wise and/or correct, so we are curious about the opinion of the developers of this library. Should DOING_CRON be set to true when running "Action Scheduler" tasks? Or is it useful/better to introduce an as_doing_cron() function or something like that? Or are we looking at this completely wrong?

CC @rvdsteege

remcotolsma avatar Jan 18 '24 11:01 remcotolsma

Hi!

However, it seems that wp_doing_cron() does not always return true when running "Action Scheduler" tasks.

That's right. By default, there are up to three different contexts through which Action Scheduler may be triggered:

  • WP Cron
  • Async HTTP requests
  • WP CLI

In most cases, it's a mix of the first two: it doesn't always run via WP Cron (and so DOING_CRON will not always be set).

However, we wonder whether this is wise and/or correct, so we are curious about the opinion of the developers of this library.

If you are finding you need something like this, then possibly? Can I just highlight though that we already have some related functionality within the library:

https://github.com/woocommerce/action-scheduler/blob/3.7.1/classes/ActionScheduler_Compatibility.php#L87-L104

This is generally called immediately prior to processing waiting actions. However, there isn't really any way to ensure this takes effect: restrictions in a given hosting environment take precedence, in many cases.

barryhughes avatar Jan 19 '24 01:01 barryhughes

Thanks @barryhughes, good to know about these 3 contexts. I think the PHP timeouts you were referring to are different from the WordPress HTTP API timeouts. WordPress uses a standard timeout of 5 seconds for HTTP requests: https://developer.wordpress.org/reference/classes/wp_http/request/#parameters. For HTTP requests that are executed via background tasks, this may be slightly higher. However, there is currently no easy way to check whether a script is running in one of the 3 contexts mentioned? For the WordPress cron wp_doing_cron() for WP-CLI defined( 'WP_CLI' ) && WP_CLI and for the Action Scheduler "Async HTTP requests"?

remcotolsma avatar Jan 19 '24 08:01 remcotolsma

I'm sorry, I misunderstood.

However, there is currently no easy way to check whether a script is running in one of the 3 contexts mentioned?

I'm not sure how useful this would be in your case, but the action_scheduler_begin_execute hook is triggered immediately before each scheduled action is fetched and executed, and supplies two parameters to its callbacks:

  • $action_id
  • $context

The second of those provides the information you are looking for (and even without it, you could still use the action itself as a signal that you are 'inside' the scheduled action queue).

Might that work? If not, we could explore alternatives. For instance, it would seem reasonable to also share the context via the action_scheduler_before_process_queue action hook, and there are probably various other possibilities.

barryhughes avatar Jan 19 '24 20:01 barryhughes

Thanks, for now we handled it this way:

  • https://github.com/pronamic/wp-pay-core/blob/b1c28b0d2f7e4772ce4e600ff6215e613cc87996/src/ActionSchedulerController.php#L1-L41
  • https://github.com/pronamic/wp-mollie/blob/13bfb8f77bb4333c975e45093b19ffb2771d0c82/src/Client.php#L102-L147

It would be nice if this library introduced it's own DOING_ACTION_SCHEDULER or something similar.

remcotolsma avatar Jan 22 '24 14:01 remcotolsma

It would be nice if this library introduced it's own DOING_ACTION_SCHEDULER or something similar.

Re-opening so we don't lose sight of this idea (a little unsure if defining a constant is the best approach for us, but the general idea makes sense).

barryhughes avatar Jan 23 '24 23:01 barryhughes