Skip to content

Async actions: Action Scheduler driver and auto resolution - #12

Merged
ogorzalka merged 1 commit into
mainfrom
feat/async-action-scheduler
Oct 7, 2026
Merged

ogorzalka merged 1 commit into
mainfrom
feat/async-action-scheduler

Conversation

@ogorzalka

Copy link
Copy Markdown
Member

Phase 2, step D: Action Scheduler driver and auto resolution.

action-scheduler driver

  • Available when as_enqueue_async_action() exists and Action Scheduler is initialised (ActionScheduler::is_initialized()). Before action_scheduler_init its functions exist but cannot store anything. Never a Composer dependency.
  • The payload travels whole as the action argument (decision of 7 October). onQueue() becomes the group, pollora by default. A delay uses as_schedule_single_action(), otherwise as_enqueue_async_action(). History is visible in Tools › Scheduled Actions.
  • Long payloads: Action Scheduler refuses arguments over 8,000 characters as JSON, which a large capture() or, soon, a serialized closure can reach. Above 7,900, the payload is kept by PayloadStore (non-autoloaded option, claim on execution) and the action carries only its identifier. Rather than falling back to in-place execution, the work still goes through the queue.
  • Retries go through Action Scheduler (driver recorded in the payload). A refused action throws AsyncException, and a payload kept apart is forgotten.

auto, now the default

  • Resolves to the first available of Async::setAutoDrivers() (['action-scheduler', 'wp-cron']). Phase 3 will put the framework's queue first.
  • Resolved on each dispatch, so a hook fired before Action Scheduler is initialised still queues, through WP-Cron.
  • Behaviour change: a site with WooCommerce switches from WP-Cron to Action Scheduler on upgrade. Payloads already in WP-Cron still run, since the listener does not depend on the driver. POLLORA_ASYNC_DRIVER=wp-cron keeps the old behaviour. This is in the CHANGELOG.

Refactor

  • PayloadStore takes the non-autoloaded storage and the claim out of WpCronDriver. WpCronDriver::OPTION_PREFIX, handles() and claim(), public since 1.2.0, are kept and delegate to it.
  • The recovery task also leaves alone a payload whose Action Scheduler action is pending (as_has_scheduled_action()), so it never runs a delayed action early.

API fix

The PHPDoc of capture() and when() was callable(mixed...), which static analysis rejects for a closure with typed parameters such as fn (int $id) => …. It is now callable.

Tests

  • Unit: 208 passed, 11 new for the driver (stubbed Action Scheduler, only available when a test asks).

  • Real WordPress, now with the Action Scheduler plugin active, locally and in CI (wp plugin install action-scheduler --activate): 4 new tests, 10 in total.

    1. auto chooses Action Scheduler; the payload is whole in the pollora group; no WP-Cron event; the queue runs in a separate process and the handler runs.
    2. onQueue sets the group.
    3. A 9,000-character capture is kept apart and runs once.
    4. A retry goes through Action Scheduler.

    The suite's default driver stays wp-cron (fixture filter), so the earlier tests are unchanged.

  • PHPStan level 5 and Pint pass.

@ogorzalka
ogorzalka merged commit 31a6369 into main Oct 7, 2026
5 checks passed
@ogorzalka
ogorzalka deleted the feat/async-action-scheduler branch October 7, 2026 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant