Action Scheduler’s tables have quietly become some of the busiest in many WooCommerce databases, and on high-volume stores they could grow faster than the cleanup could keep up, with failed actions never cleared at all. 4.0.0 is largely about fixing that: tighter retention of failed actions, and cleanup that scales better.
4.0.0 is now available on WordPress.org, and will be bundled with WooCommerce 11.0 (currently scheduled for July 28th). Whether you bundle Action Scheduler in your own extension or run a site that relies on it, now is a good time to test against this version and report anything unexpected on GitHub.
Because some of the changes in this version are backwards incompatible, it’s worth taking a look at what’s shipping in 4.0.0.
Why 4.0.0 and not 3.9.4? WordPress-style versioning (which Action Scheduler follows) means there is no 3.10 after 3.9.3. Rather than ship these breaking changes under a routine-looking 3.9.4, we bumped to 4.0.0 to flag them clearly.
Failed actions are now purged by default
Action Scheduler has always purged complete and canceled actions. Failed actions could be too by adding this status via the action_scheduler_default_cleaner_statuses filter, but out of the box they were kept indefinitely, and on busy stores that meant the actions and logs tables could grow without bound and never recover on their own.
4.0.0 introduces a dedicated cleanup path for failed actions that runs by default: failed actions are now removed once they are older than 3 months.
We picked 3 months deliberately because it lines up with a typical quarterly accounting cycle and gives you a reasonable window to investigate failures, while still bounding table growth. Stores with stricter data-retention requirements can change the window, or turn the new behavior off entirely:
// Adjust the retention window for failed actions (in seconds).
add_filter(
'action_scheduler_retention_period_for_failed',
function () {
return 6 * MONTH_IN_SECONDS;
}
);
// Or restore the pre-4.0.0 behavior and never purge failed actions.
add_filter( 'action_scheduler_enable_failed_action_cleanup', '__return_false' );Note that if you were already using action_scheduler_default_cleaner_statuses to include failed actions, that takes precedence over the new behavior and failed actions will be cleaned on the same schedule and retention window as your other statuses.
Unique actions now consider their arguments
The as_enqueue_async_action() and as_schedule_*_action() family of functions all accept a $unique argument. When set to true, Action Scheduler won’t create a new action if a matching pending or running one already exists. Before 4.0.0, “matching” meant the same hook and group, ignoring the arguments, so two actions with the same hook and group but with different args would block each other, the second being silently dropped even though it related to possibly different work.
In 4.0.0 the uniqueness check includes the arguments, so only a genuinely identical action (same hook, group, and args) counts as a duplicate.
If you relied on the old hook-and-group-only deduplication, expect more actions to be created than before, so please carefully review your code. Refer to the function reference for details.
Cleanup as a dedicated daily job
This one is not strictly breaking, but it changes when cleanup happens. Previously, deletion of old actions ran inline on every queue batch, processing only a small slice each time. It wasn’t uncommon for the cleanup to fall behind on high-volume stores.
In 4.0.0 it runs as its own task once a day at 3 am site time, deleting in larger batches (at least 250 per run) and continuing itself until the backlog is clear. That keeps deletion off the processing path and naturally allows the cleanup to catch up on large tables.
The batch size for the daily run can still be customized:
add_filter(
'action_scheduler_cleanup_batch_size',
function ( $size ) {
return 500;
}
);If you need cleanup to run inline on every batch as before, supply a custom queue cleaner: when Action Scheduler detects a cleaner other than its built-in ActionScheduler_QueueCleaner, it reverts to the inline cycle. We expect most sites won’t need this.
Other changes
4.0.0 now requires WordPress 6.8 or newer and is marked compatible with WordPress 7.0.
For the full set of changes, see the 4.0.0 changelog.
Leave a Reply