Skip to content

Commit 969c27c

Browse files
Copilotswissspidy
andauthored
Respect doing_cron transient in wp cron event run --due-now (#130)
* Initial plan * Respect doing_cron transient in wp cron event run --due-now Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Pascal Birchler <pascal.birchler@gmail.com> * Fix test * Use wpcli_ prefix to distinguish WP-CLI cron lock from spawn_cron transient Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> * Use wp_cli_doing_cron transient instead of value prefix trick Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> * Use standard doing_cron transient with plain numeric microtime value Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> * Fix cron.feature:309 test by disabling spawn_cron() interference Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> * Set TTL on doing_cron transient; only delete if lock value still matches Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> Co-authored-by: Pascal Birchler <pascalb@google.com> Co-authored-by: Pascal Birchler <pascal.birchler@gmail.com>
1 parent 5bd4379 commit 969c27c

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

features/cron-event.feature

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,31 @@ Feature: Manage WP Cron events
244244
"""
245245
Debug: Beginning execution of cron event 'wp_version_check'
246246
"""
247+
248+
Scenario: --due-now respects the doing_cron transient and skips when another run is in progress
249+
When I run `wp cron event schedule wp_cli_test_event_lock now hourly`
250+
Then STDOUT should contain:
251+
"""
252+
Success: Scheduled event with hook 'wp_cli_test_event_lock'
253+
"""
254+
255+
# Simulate an in-progress cron run by setting the doing_cron transient.
256+
When I run `wp eval 'set_transient( "doing_cron", sprintf( "%.22F", microtime( true ) ) );'`
257+
258+
And I try `wp cron event run --due-now`
259+
Then STDERR should contain:
260+
"""
261+
Warning: A cron event run is already in progress; skipping.
262+
"""
263+
And STDOUT should not contain:
264+
"""
265+
wp_cli_test_event_lock
266+
"""
267+
268+
# After the transient is cleared, the run should proceed normally.
269+
When I run `wp eval 'delete_transient( "doing_cron" );'`
270+
And I try `wp cron event run --due-now`
271+
Then STDOUT should contain:
272+
"""
273+
Executed the cron event 'wp_cli_test_event_lock'
274+
"""

features/cron.feature

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,13 @@ Feature: Manage WP-Cron events and schedules
307307
# executes the "wp_privacy_delete_old_export_files" event there.
308308
@require-wp-5.0
309309
Scenario: Run currently scheduled events
310+
# Disable web-triggered cron so spawn_cron() cannot set doing_cron between
311+
# steps - wp cron event run always defines DOING_CRON so this has no effect
312+
# on the commands being tested.
313+
When I run `wp config set DISABLE_WP_CRON true --raw`
314+
310315
# WP throws a notice here for older versions of core.
311-
When I try `wp cron event run --all`
316+
And I try `wp cron event run --all`
312317
Then STDOUT should contain:
313318
"""
314319
Executed the cron event 'wp_version_check'

src/Cron_Event_Command.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ public function schedule( $args, $assoc_args ) {
226226
* : One or more hooks to run.
227227
*
228228
* [--due-now]
229-
* : Run all hooks due right now.
229+
* : Run all hooks due right now. Respects the doing_cron transient to
230+
* prevent overlapping runs.
230231
*
231232
* [--exclude=<hooks>]
232233
* : Comma-separated list of hooks to exclude.
@@ -243,10 +244,27 @@ public function schedule( $args, $assoc_args ) {
243244
* Success: Executed a total of 2 cron events.
244245
*/
245246
public function run( $args, $assoc_args ) {
247+
$due_now = Utils\get_flag_value( $assoc_args, 'due-now' );
248+
249+
$doing_cron_value = null;
250+
251+
if ( $due_now ) {
252+
$lock_timeout = defined( 'WP_CRON_LOCK_TIMEOUT' ) ? WP_CRON_LOCK_TIMEOUT : 60;
253+
$doing_cron_transient = get_transient( 'doing_cron' );
254+
if ( is_numeric( $doing_cron_transient ) && (float) $doing_cron_transient > microtime( true ) - $lock_timeout ) {
255+
WP_CLI::warning( 'A cron event run is already in progress; skipping.' );
256+
return;
257+
}
258+
$doing_cron_value = sprintf( '%.22F', microtime( true ) );
259+
set_transient( 'doing_cron', $doing_cron_value, $lock_timeout );
260+
}
246261

247262
$events = self::get_selected_cron_events( $args, $assoc_args );
248263

249264
if ( is_wp_error( $events ) ) {
265+
if ( $due_now && get_transient( 'doing_cron' ) === $doing_cron_value ) {
266+
delete_transient( 'doing_cron' );
267+
}
250268
WP_CLI::error( $events );
251269
}
252270

@@ -263,6 +281,10 @@ public function run( $args, $assoc_args ) {
263281
}
264282
}
265283

284+
if ( $due_now && get_transient( 'doing_cron' ) === $doing_cron_value ) {
285+
delete_transient( 'doing_cron' );
286+
}
287+
266288
$message = ( 1 === $executed ) ? 'Executed a total of %d cron event.' : 'Executed a total of %d cron events.';
267289
WP_CLI::success( sprintf( $message, $executed ) );
268290
}

0 commit comments

Comments
 (0)