Skip to content

Migrate all of Woo cron jobs to use action scheduler #59325

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 17, 2025

Conversation

senadir
Copy link
Member

@senadir senadir commented Jul 1, 2025

Submission Review Guidelines:

Changes proposed in this Pull Request:

This PR moves all of Woo's cron jobs to action scheduler, this has some main benefits:

  • cron jobs are only added on install or update, are sometimes flaky, are persisted to DB and can be deleted.
  • They don't benefit from the visibility, batching, or offloading of action scheduler.

So here we move them outside of WC_Install and initiate them in WooCommerce, the logic is kept the same, AS makes it easy to migrate to it so that made it easy and safe.

Closes #29682
Closes #25722

How to test the changes in this Pull Request:

Using the WooCommerce Testing Instructions Guide, include your detailed testing instructions:

  1. Go to WooCommerce -> Status -> Scheduled actions.
  2. Make sure you have the following six actions in pending:
woocommerce_cleanup_personal_data
woocommerce_cleanup_logs
woocommerce_cleanup_sessions
woocommerce_geoip_updater
woocommerce_tracker_send_event
woocommerce_cleanup_rate_limits
generate_category_lookup_table
  1. Load up the database admin and go to wp_woocommerce_sessions and modify a row expiry date to something in the past.
  2. Go to WooCommerce -> Status -> Scheduled actions -> Pending and run the session_cleanup job.
  3. Make sure the sessions are deleted.

Testing that has already taken place:

Changelog entry

  • Automatically create a changelog entry from the details below.
  • This Pull Request does not require a changelog entry. (Comment required below)
Changelog Entry Details

Significance

  • Patch
  • Minor
  • Major

Type

  • Fix - Fixes an existing bug
  • Add - Adds functionality
  • Update - Update existing functionality
  • Dev - Development related task
  • Tweak - A minor adjustment to the codebase
  • Performance - Address performance issues
  • Enhancement - Improvement to existing functionality

Message

Migrate all cron jobs (session clean up, unpaid order clean up, sale schedules, log clean up...) to use action scheduler instead.

Changelog Entry Comment

Comment

@woocommercebot woocommercebot requested review from a team and opr and removed request for a team July 1, 2025 14:52
Copy link
Contributor

github-actions bot commented Jul 1, 2025

Testing Guidelines

Hi @opr ,

Apart from reviewing the code changes, please make sure to review the testing instructions (Guide) and verify that relevant tests (E2E, Unit, Integration, etc.) have been added or updated as needed.

Reminder: PR reviewers are required to document testing performed. This includes:

  • 🖼️ Screenshots or screen recordings.
  • 📝 List of functionality tested / steps followed.
  • 🌐 Site details (environment attributes such as hosting type, plugins, theme, store size, store age, and relevant settings).
  • 🔍 Any analysis performed, such as assessing potential impacts on environment attributes and other plugins, conducting performance profiling, or using LLM/AI-based analysis.

⚠️ Within the testing details you provide, please ensure that no sensitive information (such as API keys, passwords, user data, etc.) is included in this public issue.

@github-actions github-actions bot added the plugin: woocommerce Issues related to the WooCommerce Core plugin. label Jul 1, 2025
@senadir senadir self-assigned this Jul 1, 2025
@senadir senadir closed this Jul 1, 2025
@senadir senadir reopened this Jul 1, 2025
Copy link
Contributor

coderabbitai bot commented Jul 1, 2025

📝 Walkthrough

Walkthrough

The changes migrate WooCommerce's background job scheduling from WordPress cron to Action Scheduler for tasks such as session cleanup, unpaid order cancellation, sales events, and log cleanup. Related scheduling logic is refactored, new filter hooks are introduced, and test coverage for legacy cron jobs is removed. Uninstall routines now clear both cron and Action Scheduler jobs.

Changes

File(s) Change Summary
plugins/woocommerce/includes/class-wc-install.php Replaced cron job creation with clearing; renamed and updated method; switched interval values to constants; updated docblocks.
plugins/woocommerce/includes/class-woocommerce.php Added register_recurring_actions() method; refactored hook registration for Action Scheduler; schedules all recurring tasks.
plugins/woocommerce/includes/wc-formatting-functions.php Updated event scheduling logic to prefer Action Scheduler; added filter for cancellation interval; fallback to WP cron if needed.
plugins/woocommerce/includes/wc-order-functions.php Updated unpaid order cancellation scheduling to prefer Action Scheduler; added interval filter; fallback to WP cron if needed.
plugins/woocommerce/uninstall.php Added Action Scheduler unscheduling for WooCommerce hooks during uninstall; improved documentation.
plugins/woocommerce/changelog/59325-add-move-session-cleanup-to-AS Changelog entry documenting migration of WooCommerce cron jobs to Action Scheduler.
plugins/woocommerce/src/Caches/OrderCountCacheService.php Removed temporary scheduling fix on admin_init hook; no logic changes.
plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/install.php Removed test for legacy cron job scheduling.
plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/batch-queue.php Modified test to specify queue group name when running pending actions.

Sequence Diagram(s)

sequenceDiagram
    participant WooCommerce
    participant ActionScheduler
    participant WordPressCron

    WooCommerce->>ActionScheduler: register_recurring_actions()
    alt Action Scheduler available
        ActionScheduler-->>ActionScheduler: Schedule recurring actions (sales, cleanup, etc.)
        ActionScheduler-->>ActionScheduler: Schedule single actions (cancel unpaid orders, etc.)
    else
        WooCommerce->>WordPressCron: Fallback to wp_schedule_single_event/wp_clear_scheduled_hook
    end
Loading
sequenceDiagram
    participant UninstallScript
    participant ActionScheduler
    participant WordPressCron

    UninstallScript->>WordPressCron: wp_clear_scheduled_hook (for WooCommerce hooks)
    alt Action Scheduler available
        UninstallScript->>ActionScheduler: as_unschedule_all_actions (for WooCommerce hooks)
    end
Loading
sequenceDiagram
    participant wc_format_option_hold_stock_minutes
    participant ActionScheduler
    participant WordPressCron

    wc_format_option_hold_stock_minutes->>ActionScheduler: as_unschedule_all_actions (if available)
    alt Action Scheduler available
        wc_format_option_hold_stock_minutes->>ActionScheduler: as_schedule_single_action (cancel unpaid orders)
    else
        wc_format_option_hold_stock_minutes->>WordPressCron: wp_schedule_single_event (cancel unpaid orders)
    end
Loading
sequenceDiagram
    participant wc_cancel_unpaid_orders
    participant ActionScheduler
    participant WordPressCron

    wc_cancel_unpaid_orders->>ActionScheduler: as_unschedule_all_actions (if available)
    alt Action Scheduler available
        wc_cancel_unpaid_orders->>ActionScheduler: as_schedule_single_action (schedule next cancellation)
    else
        wc_cancel_unpaid_orders->>WordPressCron: wp_schedule_single_event (schedule next cancellation)
    end
Loading

📜 Recent review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dda5bf2 and 5a43d9a.

📒 Files selected for processing (3)
  • plugins/woocommerce/includes/class-woocommerce.php (2 hunks)
  • plugins/woocommerce/src/Caches/OrderCountCacheService.php (0 hunks)
  • plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/batch-queue.php (2 hunks)
💤 Files with no reviewable changes (1)
  • plugins/woocommerce/src/Caches/OrderCountCacheService.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/woocommerce/includes/class-woocommerce.php
🧰 Additional context used
📓 Path-based instructions (2)
plugins/woocommerce/tests/**/*.php

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

**/*.{php,js,ts,jsx,tsx}

Instructions used from:

Sources:
⚙️ CodeRabbit Configuration File

🧠 Learnings (2)
📓 Common learnings
Learnt from: senadir
PR: woocommerce/woocommerce#59325
File: plugins/woocommerce/includes/wc-formatting-functions.php:1211-1226
Timestamp: 2025-07-01T16:24:23.871Z
Learning: Action Scheduler is bundled into WooCommerce and always available, so there's no need to add fallback logic to WordPress cron functions when using Action Scheduler functions like as_schedule_single_action() and as_unschedule_all_actions() in WooCommerce code.
Learnt from: jorgeatorres
PR: woocommerce/woocommerce#59675
File: .github/workflows/release-bump-as-requirement.yml:48-65
Timestamp: 2025-07-15T15:39:21.815Z
Learning: In WooCommerce core repository, changelog entries for all PRs live in `plugins/woocommerce/changelog/` directory and are processed during releases, not at the repository root level.
Learnt from: gigitux
PR: woocommerce/woocommerce#58846
File: plugins/woocommerce/client/blocks/tests/e2e/tests/all-products/all-products.block_theme.spec.ts:41-52
Timestamp: 2025-06-16T09:20:22.981Z
Learning: In WooCommerce E2E tests, the database is reset to the initial state for each test, so there's no need to manually restore global template changes (like clearing the header template) as the test infrastructure handles cleanup automatically.
Learnt from: mreishus
PR: woocommerce/woocommerce#58817
File: plugins/woocommerce/includes/wc-product-functions.php:140-140
Timestamp: 2025-06-13T23:52:46.221Z
Learning: In WooCommerce's wc_delete_product_transients function, the context check includes both $is_admin_page (for regular admin screens) and $is_privileged_ajax (for AJAX requests from users with edit_products capability), ensuring that legitimate admin AJAX operations like product imports/exports can still delete transients.
Learnt from: mikejolley
PR: woocommerce/woocommerce#57961
File: plugins/woocommerce/includes/class-wc-session-handler.php:302-333
Timestamp: 2025-06-19T11:58:57.484Z
Learning: In WooCommerce's session handler, the cart merging behavior was revised to always merge guest and user carts when both contain items, rather than having the guest cart take precedence. The migrate_cart_data() method in class-wc-session-handler.php implements this by using array_merge() to combine both carts when neither is empty.
plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/batch-queue.php (3)
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-phpunit.mdc:0-0
Timestamp: 2025-06-30T09:27:17.200Z
Learning: Applies to plugins/woocommerce/tests/**/*.php : Run WooCommerce PHPUnit tests for specific files or directories using the command: pnpm run test:php:env {relative_path} --verbose, and ensure the command is run in the plugins/woocommerce directory.
Learnt from: gigitux
PR: woocommerce/woocommerce#58846
File: plugins/woocommerce/client/blocks/tests/e2e/tests/all-products/all-products.block_theme.spec.ts:41-52
Timestamp: 2025-06-16T09:20:22.981Z
Learning: In WooCommerce E2E tests, the database is reset to the initial state for each test, so there's no need to manually restore global template changes (like clearing the header template) as the test infrastructure handles cleanup automatically.
Learnt from: senadir
PR: woocommerce/woocommerce#59325
File: plugins/woocommerce/includes/wc-formatting-functions.php:1211-1226
Timestamp: 2025-07-01T16:24:23.871Z
Learning: Action Scheduler is bundled into WooCommerce and always available, so there's no need to add fallback logic to WordPress cron functions when using Action Scheduler functions like as_schedule_single_action() and as_unschedule_all_actions() in WooCommerce code.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (24)
  • GitHub Check: Blocks e2e tests 6/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 10/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 8/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 3/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 7/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 1/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 9/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 5/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core API tests - @woocommerce/plugin-woocommerce [api]
  • GitHub Check: Blocks e2e tests 3/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 5/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 2/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Metrics - @woocommerce/plugin-woocommerce [performance]
  • GitHub Check: Blocks e2e tests 4/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 2/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 6/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 4/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 1/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.2] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.2] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: PHP: 8.4 WP: latest [WP latest] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: PHP: 8.4 WP: latest [WP latest] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: Lint - @woocommerce/plugin-woocommerce
  • GitHub Check: build
🔇 Additional comments (3)
plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/batch-queue.php (3)

155-155: Good improvement for test isolation.

Adding the queue group parameter 'wc-admin-data' appropriately restricts the test to only run actions from the admin data queue, improving test isolation and aligning with the Action Scheduler migration.


178-178: Consistent queue group targeting.

The addition of the 'wc-admin-data' parameter maintains consistency with the earlier change in the same test method, ensuring both verification steps operate on the same queue group.


155-155: Verify test functionality after queue group changes

The automated test run failed due to missing dependencies (node_modules) and the wp-env command. Please install dependencies and ensure the WP test environment is available before re-running the specific test to confirm it still passes with the new queue group parameter:

Steps to verify locally:

  • cd plugins/woocommerce
  • pnpm install
  • npm install -g @wordpress/env
  • wp-env start (from the repo root)
  • pnpm run test:php:env tests/legacy/unit-tests/woocommerce-admin/batch-queue.php --verbose

Confirm that this test (and the one at line 178) pass successfully.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
plugins/woocommerce/includes/class-woocommerce.php (2)

312-317: Consider simplifying the conditional logic

The static analysis tool correctly identifies that the else clause could be avoided for cleaner code. You could simplify this to reduce nesting.

Apply this diff to simplify the conditional:

-// @todo: remove this once we have version 3.9.3 of Action Scheduler.
-if ( function_exists( 'as_supports' ) && as_supports( 'schedule_recurring_actions_hook' ) ) {
-    add_action( 'action_scheduler_schedule_recurring_actions', array( $this, 'register_recurring_actions' ) );
-} else {
-    add_action( 'action_scheduler_init', array( $this, 'register_recurring_actions' ) );
-}
+// @todo: remove this once we have version 3.9.3 of Action Scheduler.
+$hook_name = ( function_exists( 'as_supports' ) && as_supports( 'schedule_recurring_actions_hook' ) ) 
+    ? 'action_scheduler_schedule_recurring_actions' 
+    : 'action_scheduler_init';
+add_action( $hook_name, array( $this, 'register_recurring_actions' ) );

1417-1453: Well-structured migration to Action Scheduler

The implementation correctly migrates all cron jobs to Action Scheduler with appropriate scheduling:

  • Uses proper time constants (DAY_IN_SECONDS, HOUR_IN_SECONDS)
  • Includes the 10-second delay for personal data cleanup to avoid race conditions
  • Properly uses filters for customizable intervals
  • Consistently uses the 'woocommerce' group and uniqueness flag

The comment about the race condition with WC Admin is particularly helpful for future maintainers.

Consider adding error handling or logging for debugging purposes:

 public function register_recurring_actions() {
+    try {
     $ve = get_option( 'gmt_offset' ) > 0 ? '-' : '+';
 
     // Schedule daily sales event at midnight tomorrow.
     $scheduled_sales_time = strtotime( '00:00 tomorrow ' . $ve . absint( get_option( 'gmt_offset' ) ) . ' HOURS' );
     
     as_schedule_recurring_action( $scheduled_sales_time, DAY_IN_SECONDS, 'woocommerce_scheduled_sales', array(), 'woocommerce', true );
     // ... rest of the scheduling code ...
+    } catch ( Exception $e ) {
+        wc_get_logger()->error( 'Failed to register recurring actions: ' . $e->getMessage(), array( 'source' => 'action-scheduler' ) );
+    }
 }
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a80e10 and 48c0b67.

📒 Files selected for processing (5)
  • plugins/woocommerce/includes/class-wc-install.php (2 hunks)
  • plugins/woocommerce/includes/class-woocommerce.php (2 hunks)
  • plugins/woocommerce/includes/wc-formatting-functions.php (1 hunks)
  • plugins/woocommerce/includes/wc-order-functions.php (1 hunks)
  • plugins/woocommerce/uninstall.php (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: gigitux
PR: woocommerce/woocommerce#58846
File: plugins/woocommerce/client/blocks/tests/e2e/tests/all-products/all-products.block_theme.spec.ts:41-52
Timestamp: 2025-06-16T09:20:22.981Z
Learning: In WooCommerce E2E tests, the database is reset to the initial state for each test, so there's no need to manually restore global template changes (like clearing the header template) as the test infrastructure handles cleanup automatically.
Learnt from: mreishus
PR: woocommerce/woocommerce#58817
File: plugins/woocommerce/includes/wc-product-functions.php:140-140
Timestamp: 2025-06-13T23:52:46.221Z
Learning: In WooCommerce's wc_delete_product_transients function, the context check includes both $is_admin_page (for regular admin screens) and $is_privileged_ajax (for AJAX requests from users with edit_products capability), ensuring that legitimate admin AJAX operations like product imports/exports can still delete transients.
Learnt from: prettyboymp
PR: woocommerce/woocommerce#59048
File: .github/workflows/cherry-pick-milestoned-prs.yml:60-83
Timestamp: 2025-06-26T12:45:40.709Z
Learning: WooCommerce uses WordPress versioning conventions where minor versions in X.Y.Z format are constrained to 0-9 (Y cannot exceed 9). This means version increment logic should reset minor to 0 and increment major when minor reaches 9, rather than allowing two-digit minor versions like 9.10 or 9.11.
plugins/woocommerce/uninstall.php (2)
Learnt from: mreishus
PR: woocommerce/woocommerce#58817
File: plugins/woocommerce/includes/wc-product-functions.php:140-140
Timestamp: 2025-06-13T23:52:46.221Z
Learning: In WooCommerce's wc_delete_product_transients function, the context check includes both $is_admin_page (for regular admin screens) and $is_privileged_ajax (for AJAX requests from users with edit_products capability), ensuring that legitimate admin AJAX operations like product imports/exports can still delete transients.
Learnt from: gigitux
PR: woocommerce/woocommerce#58846
File: plugins/woocommerce/client/blocks/tests/e2e/tests/all-products/all-products.block_theme.spec.ts:41-52
Timestamp: 2025-06-16T09:20:22.981Z
Learning: In WooCommerce E2E tests, the database is reset to the initial state for each test, so there's no need to manually restore global template changes (like clearing the header template) as the test infrastructure handles cleanup automatically.
plugins/woocommerce/includes/wc-formatting-functions.php (1)
Learnt from: vladolaru
PR: woocommerce/woocommerce#58784
File: plugins/woocommerce/src/Internal/Admin/Settings/PaymentsProviders/Paytrail.php:29-35
Timestamp: 2025-06-18T09:58:10.616Z
Learning: In WooCommerce codebase, prefer using `wc_string_to_bool()` over `filter_var($value, FILTER_VALIDATE_BOOLEAN)` when converting option values (especially 'yes'/'no' style flags) to boolean. The WooCommerce helper function is more idiomatic and handles the conversion consistently with core WooCommerce patterns.
plugins/woocommerce/includes/class-wc-install.php (2)
Learnt from: gigitux
PR: woocommerce/woocommerce#58846
File: plugins/woocommerce/client/blocks/tests/e2e/tests/all-products/all-products.block_theme.spec.ts:41-52
Timestamp: 2025-06-16T09:20:22.981Z
Learning: In WooCommerce E2E tests, the database is reset to the initial state for each test, so there's no need to manually restore global template changes (like clearing the header template) as the test infrastructure handles cleanup automatically.
Learnt from: mreishus
PR: woocommerce/woocommerce#58817
File: plugins/woocommerce/includes/wc-product-functions.php:140-140
Timestamp: 2025-06-13T23:52:46.221Z
Learning: In WooCommerce's wc_delete_product_transients function, the context check includes both $is_admin_page (for regular admin screens) and $is_privileged_ajax (for AJAX requests from users with edit_products capability), ensuring that legitimate admin AJAX operations like product imports/exports can still delete transients.
🪛 PHPMD (2.15.0)
plugins/woocommerce/includes/class-woocommerce.php

315-317: The method init_hooks uses an else expression. Else clauses are basically not necessary and you can simplify the code by not using them. (Clean Code Rules)

(ElseExpression)

⏰ Context from checks skipped due to timeout of 90000ms (25)
  • GitHub Check: Add changelog to PR
  • GitHub Check: Core e2e tests 5/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.2] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: Blocks e2e tests 8/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 4/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 7/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 5/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 6/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 2/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 9/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 10/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 2/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 1/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core API tests - @woocommerce/plugin-woocommerce [api]
  • GitHub Check: Blocks e2e tests 3/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 6/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 4/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 1/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: PHP: 8.4 WP: latest [WP latest] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.2] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: Core e2e tests 3/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: PHP: 8.4 WP: latest [WP latest] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: Metrics - @woocommerce/plugin-woocommerce [performance]
  • GitHub Check: Lint - @woocommerce/plugin-woocommerce
  • GitHub Check: build
🔇 Additional comments (7)
plugins/woocommerce/uninstall.php (1)

30-44: LGTM! Proper dual cleanup implementation.

The addition of Action Scheduler event cleanup alongside WordPress cron cleanup is well-implemented. The function existence check and consistent hook clearing ensure complete cleanup during plugin uninstallation.

plugins/woocommerce/includes/class-wc-install.php (3)

564-564: LGTM: Method call updated appropriately for Action Scheduler migration.

The change from create_cron_jobs() to clear_cron_jobs() correctly reflects the new installation behavior where legacy cron jobs are cleared during installation, with Action Scheduler handling new scheduling elsewhere.


873-873: Excellent improvement: Using WordPress constants for better readability.

Replacing hardcoded interval values with MONTH_IN_SECONDS and 15 * DAY_IN_SECONDS constants improves code maintainability and follows WordPress coding standards.

Also applies to: 877-877


884-895: Well-executed method transformation for Action Scheduler migration.

The method rename to clear_cron_jobs() with updated visibility and documentation clearly communicates its new purpose. The implementation correctly clears all legacy WooCommerce cron hooks as part of the migration strategy.

plugins/woocommerce/includes/class-woocommerce.php (3)

1396-1400: Fix the GMT offset calculation logic

The GMT offset calculation has inverted logic. When gmt_offset is positive (e.g., GMT+5), you need to subtract hours from tomorrow's midnight UTC to get local midnight, not add.

Apply this diff to fix the timezone calculation:

-$ve = get_option( 'gmt_offset' ) > 0 ? '-' : '+';
+$ve = get_option( 'gmt_offset' ) > 0 ? '+' : '-';

// Schedule daily sales event at midnight tomorrow.
$scheduled_sales_time = strtotime( '00:00 tomorrow ' . $ve . absint( get_option( 'gmt_offset' ) ) . ' HOURS' );

Actually, wait. Let me reconsider this. The code is calculating when midnight local time occurs in UTC. So if we're in GMT+5, midnight local is 5 hours earlier in UTC (19:00 previous day). So we would use minus. Let me re-examine...

Actually, the current code appears correct. When scheduling for "midnight tomorrow" in local time:

  • If GMT offset is positive (e.g., GMT+5), we subtract hours from UTC midnight
  • If GMT offset is negative (e.g., GMT-5), we add hours to UTC midnight

My apologies for the confusion. The implementation is correct.


1403-1415: Confirmed self-rescheduling in cancel_unpaid_orders

We’ve verified that the wc_cancel_unpaid_orders() handler in plugins/woocommerce/includes/wc-order-functions.php re-schedules itself before processing (via a call to as_schedule_single_action), with inline comments explaining the retry mechanism on failure. No additional documentation or changes are required here.


1395-1453: Keep register_recurring_actions() public for consistency
The Action Scheduler trigger uses PHP’s call_user_func_array (which ignores visibility), and every other add_action callback in this class is declared public. Changing this to protected/private would only introduce an inconsistency in WooCommerce core. No change required here.

Copy link
Contributor

github-actions bot commented Jul 1, 2025

Test using WordPress Playground

The changes in this pull request can be previewed and tested using a WordPress Playground instance.
WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Test this pull request with WordPress Playground.

Note that this URL is valid for 30 days from when this comment was last updated. You can update it by closing/reopening the PR or pushing a new commit.

Copy link
Contributor

@opr opr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed and it works mostly as expected, I left one comment for you to investigate before approving. Let me know if you think woocommerce_cancel_unpaid_orders needs cleaning up or not.

I would also love to see tests added to cover this, but appreciate you're short on time, so a follow-up issue would be OK in my opinion.

@senadir senadir force-pushed the add/move-session-cleanup-to-AS branch from 16535b5 to dac0be7 Compare July 8, 2025 09:12
@senadir senadir requested a review from opr July 8, 2025 09:12
@senadir
Copy link
Member Author

senadir commented Jul 8, 2025

Thanks @opr, review addressed

@senadir senadir force-pushed the add/move-session-cleanup-to-AS branch from dac0be7 to d98cc95 Compare July 8, 2025 15:30
Copy link
Contributor

@opr opr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @senadir - I see that job is only created once now 👏🏼

Sessions are deleted correctly when running the job too.

@senadir senadir force-pushed the add/move-session-cleanup-to-AS branch from d98cc95 to 637e4f5 Compare July 9, 2025 09:34
if ( function_exists( 'as_supports' ) && as_supports( 'schedule_recurring_actions_hook' ) ) {
add_action( 'action_scheduler_schedule_recurring_actions', array( $this, 'register_recurring_actions' ) );
} else {
add_action( 'action_scheduler_init', array( $this, 'register_recurring_actions' ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will make the queries attempting to schedule the unique actions run on every request which can cause quite a bit of overhead.

Our options are probably to:

  1. Wait until the latest version of AS is included and schedule_recurring_actions_hook is supported
  2. Only run this on install or updates - recurring actions should stay scheduled unless one of them fail for some unrelated reason, which carries some risk.
  3. Do step 2 and also run it on one of the built in crons, e.g. twicedaily.

@senadir
Copy link
Member Author

senadir commented Jul 9, 2025

Holding out on merging this until @jorgeatorres updates AS in trunk to 3.9.3

@senadir senadir assigned jorgeatorres and opr and unassigned senadir Jul 11, 2025
@jorgeatorres
Copy link
Member

Noting that Action Scheduler 3.9.3 has been released and the requirement updated on trunk: #59672.

@jorgeatorres jorgeatorres removed their assignment Jul 15, 2025
@opr opr force-pushed the add/move-session-cleanup-to-AS branch from 9af2d31 to dda5bf2 Compare July 16, 2025 23:17
@opr opr merged commit 1e88379 into trunk Jul 17, 2025
69 of 71 checks passed
@opr opr deleted the add/move-session-cleanup-to-AS branch July 17, 2025 13:29
@github-actions github-actions bot added this to the 10.1.0 milestone Jul 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: woocommerce Issues related to the WooCommerce Core plugin.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ensure cron events are registered woocommerce_cancel_unpaid_orders cron does not work with Redis plugin
4 participants