Skip to content

Release 4.3.0#1930

Open
PatelUtkarsh wants to merge 19 commits into
masterfrom
release/v4.3.0
Open

Release 4.3.0#1930
PatelUtkarsh wants to merge 19 commits into
masterfrom
release/v4.3.0

Conversation

@PatelUtkarsh

Copy link
Copy Markdown
Member

Merges the 4.3.0 release branch into master.

Changes since 4.2.2

Enhancements

Bug Fixes

Development

Release checklist

  • Release branch created off develop
  • Version bumped to 4.3.0 (stream.php, classes/class-plugin.php, readme.txt)
  • changelog.md and readme.txt changelog finalized
  • v4.3.0-rc.1 pre-release published (WP.org dry-run + test ZIP)
  • RC tested
  • v4.3.0 stable release published (deploys to WP.org)
  • Merge this PR into master, then master into develop

PatelUtkarsh and others added 19 commits June 30, 2026 21:05
Stream hard-required Action Scheduler (AS) for all deferred work — the
recurring TTL auto-purge, the batched purge chain, the orphan reaper, and
the large-table reset. Hosts that bundle Stream and run reliable cron
(e.g. Cavalcade on Altis) had no way to opt out, even though AS is less
efficient for that workload and bypasses custom DB drivers.

Introduce a Scheduler abstraction with two implementations:
  - AS_Scheduler (default): thin wrappers over the existing as_*() calls;
    behavior is unchanged on the default path.
  - Cron_Scheduler: WP-Cron fallback implementing the same contract —
    self-chaining batches via one-off events, a custom 12h recurrence, a
    cron-array scan for the overlap guard, and a short-lived transient
    "running" marker to bridge mid-chain gaps that AS tracks natively.

Selection happens once in Plugin::create_scheduler() via the new
`wp_stream_use_action_scheduler` filter. The default is based on whether
the bundled AS file loaded — not function_exists() — because AS only
declares its as_*() API on `init`, while the plugin is constructed on
`plugins_loaded`; scheduler methods are only ever called on/after `init`.
All as_*() / ActionScheduler_Store references now live solely in
AS_Scheduler; Admin and Settings talk only to the interface.

No migration is needed when switching backends. purge_schedule_setup()
detects a switch via the autoloaded wp_stream_scheduler_backend marker and
clears the inactive backend's recurring action exactly once (so the purge
never fires from both AS and WP-Cron). Steady-state cost is a single
in-memory option compare; the cleanup query runs only on the first load
after a switch. Self-healing in both directions.

AS stays a hard, bundled dependency in composer.json — the WordPress.org
build ships it via `composer install --no-dev`, so it is NOT moved to
`suggest` (that would break the common shared-hosting case). The AS
require_once is now file_exists-guarded so an environment that omits or
already provides AS does not fatal.

Tests: Cron_Scheduler unit tests, scheduler-selection tests, a cron-mode
auto-purge workflow suite (batch chaining, terminal reaper, recurring
registration, overlap guard) mirroring the AS suite, and a backend-handoff
suite covering both switch directions. The per-site-scoping Admin test
stub gains the new scheduler property. Single-site and multisite PHPUnit
lanes pass. The DB_Driver purge_storage() rework is tracked separately.
…otice (#1907)

Three refinements to the optional-Action-Scheduler work:

1. Don't load Action Scheduler when the WP-Cron fallback is chosen. The
   `wp_stream_use_action_scheduler` filter is now evaluated before the bundled
   require_once; Plugin::create_scheduler() loads action-scheduler.php only on
   the AS branch. Opting into cron pays neither the require nor AS's own `init`
   bootstrap — only the unused file on disk. AS stays a hard bundled dependency.

2. Add the `wp_stream_enable_auto_purge` filter (default true). Returning false
   from purge_schedule_setup() unschedules any recurring purge from both backends
   and skips re-registration, for storage drivers that manage retention
   externally. The backend marker option is cleared so re-enabling heals cleanly.

3. Add a large-table notice on the cron backend. When a large-table batch
   operation (manual reset or auto-purge) is queued while the cron fallback is
   active, maybe_warn_large_table_without_action_scheduler() surfaces guidance to
   drain it deterministically via WP-CLI. No-op under AS and when auto-purge is
   disabled. Routed through Admin::notice(), so it renders as an admin notice in
   the dashboard and a WP_CLI::warning under WP-CLI — the WP-CLI surface is kept
   (scheduling the chain onto cron does not drain it, so headless/low-traffic
   sites are exactly where it can stall).

Tests: cron-purge suite gains coverage for the disable switch and the notice
firing/suppression across backends.
… notice (#1907)

purge_schedule_setup() already skips registering the recurring purge when
wp_stream_enable_auto_purge returns false, but the callback itself did not
re-check the filter. A recurring action already in flight when the filter
flips to false (or an args-specific entry the unschedule missed) would still
run a purge cycle the operator opted out of. Re-check the filter at the top
of purge_scheduled_action() so the off switch is honored on both the
scheduling and executing paths.

Clarify the large-table WP-Cron notice:
- State what the batched work does — either "delete records older than the
  retention period" (auto-purge) or "reset the Stream database" (manual
  reset) — via a new $operation argument, instead of a generic "large batch
  operation".
- Explain the cleanup mechanics (records removed in chained batches as
  WP-Cron runs) and the partial-completion risk (chain may stall, leaving
  records only partly removed) on default traffic-triggered WP-Cron.
- Describe "reliable cron" accurately as a Linux crontab or third-party cron
  service hitting wp-cron.php on a fixed interval without an execution
  timeout (not Cavalcade).

Document the wp_stream_enable_auto_purge filter, the large-table WP-Cron /
WP-CLI notice, and the cron-fallback "AS not loaded" behavior in the
changelog.

Test: a purge callback firing while the filter is false deletes nothing.
…ble (#1907)

Address PR review feedback:
- Move the cron running-marker lifecycle into auto_purge_reaper() so the
  overlap guard stays busy while the orphan-meta DELETE executes (WP-Cron
  removes the event before the callback runs).
- Disabled teardown now also clears the Action Scheduler store when cron
  is the active backend but the AS API is loaded (e.g. via WooCommerce),
  honoring the wp_stream_enable_auto_purge 'both backends' promise.
- Document intentional AS backend behaviors: keyed args preserved on
  enqueue, hook-scoped recurring probe.
Bring the 4.2.2 version bump and changelog entry back into develop to
keep the branches in sync following the release.

Co-authored-by: Cursor <cursoragent@cursor.com>
…reset chain, AS-absent fallback (#1907)

Addresses bartoszgadomski's review on PR #1917:

- Persist the large-table WP-Cron warning to an option and render it on
  the next admin page load. Neither queueing context could display it:
  the recurring purge runs under DOING_CRON (response discarded) and the
  manual reset redirects + exits before shutdown output reaches the
  browser. WP-CLI keeps the immediate WP_CLI::warning.
- Apply the running-marker treatment to the manual reset chain
  (erase_large_records), mirroring auto_purge_batch, and route
  is_running_async_deletion() through any_pending_or_running() so the
  reset link is not briefly re-exposed mid-callback on the cron backend.
  The Cron_Scheduler marker is now claimed per context so one chain
  finishing cannot un-mark a sibling chain.
- Fall back to Cron_Scheduler when wp_stream_use_action_scheduler is
  forced true but the bundled AS library is absent, instead of returning
  an AS_Scheduler whose unguarded as_*() calls would fatal.
…nal-action-scheduler

# Conflicts:
#	changelog.md
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…bool (#1907)

A filter callback returning a truthy string (e.g. 'false') would
otherwise select the Action Scheduler backend. The documented
__return_false / __return_true usage returns real booleans, so this is
robustness rather than a live bug — the explicit (bool) cast makes
backend selection deterministic. Raised by Copilot and seconded in
review.
Make Action Scheduler usage optional at runtime (WP-Cron fallback)
Fix phpcs warnings in BuddyPress connector
* Fix PHP 8.4 Deprecations

* Fix phpcs issues
* docs(readme): refresh plugin name line, tagline, and tags for activity log SEO

* docs(readme): rewrite Description intro around activity/audit log terminology, mention retention and AI abilities

* docs(readme): add Two Factor to built-in integrations list

* docs(readme): mention Stream is free and open source in Description

* docs(plugin-header): use activity log / audit trail terminology in plugin Description

* docs(readme.md): align GitHub tagline with activity log / audit trail terminology

* docs(readme): trim changelog to last five releases with links to full changelog

* docs(readme): inline latest release notes in changelog with link to GitHub

* docs(readme): inline user-facing release notes for 4.2.1 and 4.2.0

* docs(readme): remove 'Free' from short description

* docs(readme.md): align tagline with WordPress.org short description

* docs: drop 'for WordPress' from display name and update Plugin Name header
get_order() returns a WC_Order object where an int ID was
expected, triggering a PHP warning on every WooCommerce order
status change. Use get_order_id() instead, as the other callbacks
in this file already do.

Fixes #1928.
@PatelUtkarsh
PatelUtkarsh marked this pull request as ready for review July 20, 2026 06:55
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.

4 participants