diff --git a/CHANGELOG.md b/CHANGELOG.md index 1616d8b5..b49e703a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The WpCli module no longer reaches for Laravel's application, the first step towards `pollora/wp-cli`: `WpCliDiscovery` builds commands through the discovery's instance pool instead of `resolve()`. Its service provider and `pollora:make:wp-cli` stay in the framework; an architecture test keeps the rest to the attributes, discovery, PSR logging and WP-CLI - `#[Schedule]`, which runs on WP-Cron alone, no longer reaches for Laravel, the first step towards `pollora/schedule`: `ScheduleDiscovery` derives default hook names itself, with the same results as `Str::snake()` (a parity test keeps them), so hooks already scheduled keep their name. The bridge to Laravel's scheduler (`use_laravel_scheduler`) stays in the framework +- Asynchronous actions queue through the WP-Cron and Action Scheduler drivers of `pollora/schedule`, with `pollora/hook` 2.0: `->async()`, `#[Async]`, `Async::fake()`, `via()` and their options do not change, and work already queued runs once the upgrade is in. `Async\Drivers\WpCronDriver` and `ActionSchedulerDriver` are gone with no alias; the framework never used them, and the `queue` driver is unchanged + ### Deprecated - `DiscoveryCacheInterface` and `LaravelDiscoveryCache`, removed in 15.0: nothing reads this cache, scans are cached by the Spatie driver given to `DiscoveryCacheManager` - `Pollora\Attributes\PostType\PostTypeAttribute` and `Pollora\Attributes\Taxonomy\TaxonomyAttribute`, removed in 15.0: no built-in attribute extends them any more; implement `ConfiguresArguments` @@ -36,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `handle()` on `#[Action]`, `#[Filter]`, `#[WpRestRoute]` and `#[WpRestRoute\Method]`, and `Hook` no longer implements `HandlesAttributes`: `HookDiscovery` and `WpRestDiscovery` register hooks and routes themselves. Only the bug below reached `Action::handle()`, and `WpRestRoute::handle()` wrote to a read-only wrapper ### Fixed +- `pollora:doctor` no longer counts as overdue WP-Cron events the ones Action Scheduler keeps: the `cron` option indexes them too, with a `driver` key - A public `#[Action]` or `#[Filter]` method in a `#[PostType]` or `#[Taxonomy]` class is registered once: the post type and taxonomy discoveries also handed it to `Action::handle()`, which registered it a second time on the discovery's configuration object, so the page firing that hook failed with `call_user_func(): Argument #1 ($callback) must be a valid callback, class Pollora\PostType\Infrastructure\Services\PostTypeConfiguration does not have a method …` - A REST controller declared with `#[WpRestRoute]` gets its constructor dependencies: it is resolved through the discovery's instance pool (Laravel's container in a Pollora application) instead of `new` with no argument, so a controller with a required dependency answered every request with `Trying to invoke non static method … without an object` diff --git a/composer.json b/composer.json index 7058d64c..a926bd66 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,7 @@ "pollora/attributes": "^0.1 || ^1.0", "pollora/discovery": "^0.1 || ^1.0", "pollora/entity": "^1.2", - "pollora/hook": "^1.5", + "pollora/hook": "^2.0", "pollora/option": "^1.1", "pollora/schedule": "^0.1.1 || ^1.0", "pollora/wp-cli": "^0.1 || ^1.0", diff --git a/src/Hook/Infrastructure/Services/AsyncInspector.php b/src/Hook/Infrastructure/Services/AsyncInspector.php index da55592e..d05ecf3b 100644 --- a/src/Hook/Infrastructure/Services/AsyncInspector.php +++ b/src/Hook/Infrastructure/Services/AsyncInspector.php @@ -81,8 +81,9 @@ public function overdueCronEvents(int $seconds): array continue; } + // The events another driver keeps (Action Scheduler) are in the index too: this counts what only WP-Cron runs foreach ((array) $hooks as $events) { - $count += count((array) $events); + $count += count(array_filter((array) $events, static fn (mixed $event): bool => ! is_array($event) || ($event['driver'] ?? 'wp-cron') === 'wp-cron')); } $oldest = $oldest === null ? $timestamp : min($oldest, $timestamp); diff --git a/tests/Feature/Hook/Async/AsyncInspectorTest.php b/tests/Feature/Hook/Async/AsyncInspectorTest.php index 1ed06cca..4195a02e 100644 --- a/tests/Feature/Hook/Async/AsyncInspectorTest.php +++ b/tests/Feature/Hook/Async/AsyncInspectorTest.php @@ -93,6 +93,15 @@ public function get_results(string $query, string $output): array ->and($queued)->toBeInstanceOf(QueuedHandler::class); }); +it("does not count as WP-Cron's the events another driver keeps, which the cron option indexes too", function (): void { + $now = time(); + Functions\when('_get_cron_array')->justReturn([ + $now - 7200 => ['wp_version_check' => ['k1' => ['schedule' => 'daily', 'args' => []]], 'reports' => ['k2' => ['schedule' => 'daily', 'args' => [], 'driver' => 'action-scheduler']]], + ]); + + expect($this->inspector->overdueCronEvents(3600))->toBe(['count' => 1, 'oldest' => $now - 7200]); +}); + it('counts the WP-Cron events overdue for longer than the grace period', function (): void { $now = time(); Functions\when('_get_cron_array')->justReturn([