=== SwiftQueue ===
Contributors: utahcreates
Tags: cron, wp-cron, performance, background, scheduled tasks
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 8.0
Stable tag: 3.2.2
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html

Runs WP-Cron in a separate background request instead of inside your visitors' page loads.

== Description ==

By default, WordPress runs scheduled tasks *inside a visitor's page request*. If
your site has a backup, a batch of emails, or a plugin's cleanup routine due, one
unlucky visitor waits while it finishes. On a store, that visitor is sometimes the
person checking out.

SwiftQueue changes when and where that work happens. When tasks are due, it fires
a separate non-blocking background request to handle them, and the visitor's page
is returned immediately.

= What it actually does =

* Prevents WordPress from running cron inline during page loads
* Dispatches a separate background request to process due tasks
* Uses a concurrency lock so two workers never run the same queue at once
* Rate-limits spawns so a traffic spike can't trigger a stampede
* Reports what happened — every spawn, its duration, and its outcome

= Monitoring, included free =

* WordPress Site Health tests, including detection of the silent
  DISABLE_WP_CRON-without-a-crontab misconfiguration
* Overview dashboard: queue status, spawn history, health at a glance
* Task Inspector: every scheduled task by name, with run / defer / cancel
  controls, dead-letter recovery for failed Action Scheduler jobs, and an
  Action Scheduler queue runner
* Optional structured JSON logging of every spawn and outcome
* Dashboard widget and admin bar status
* WP-CLI: `wp swiftqueue status|doctor|export`
* Production Setup tab that generates the exact crontab command for your site
  and turns green only when it has observed your server cron actually working

Everything in this plugin is fully functional — nothing is locked, limited or
licence-gated.

= SwiftQueue Pro =

The free version is the complete background engine — it is not a trial. A
separate Pro plugin, sold at [getswiftqueue.com](https://getswiftqueue.com/pricing),
adds what stores, agencies and networks need:

* Priority lanes (Express / Standard / Housekeeping) with a database-contention
  shield that holds housekeeping back under load, and adaptive spawn throttling
* Checkout Priority Mode for WooCommerce — no background work while a customer
  is paying
* Alerts by email, Slack, Discord, Microsoft Teams, PagerDuty and webhooks,
  plus a weekly digest email
* Token-protected REST endpoints
* A network-wide queue dashboard for multisite

Every published performance number for this plugin is measured and reproducible;
the harness and raw data are at [getswiftqueue.com/benchmarks](https://getswiftqueue.com/benchmarks).

== Installation ==

1. Install and activate the plugin.
2. Open **Settings → SwiftQueue**.
3. Complete the setup wizard and apply the scale profile matching your site.
4. Recommended for production: set `DISABLE_WP_CRON` in `wp-config.php` and add a
   real system cron entry. The Production Setup tab generates the exact command
   for your server.

== Frequently Asked Questions ==

= Do I need WooCommerce? =

No. Every WordPress site runs cron, so every site benefits. The WooCommerce
features activate automatically when WooCommerce is detected.

= Does this work on shared hosting? =

Yes, provided your host allows loopback HTTP requests to your own site — most do.
The Production Setup tab runs a live loopback test and tells you plainly whether
yours works. If it doesn't, the plugin will tell you rather than failing quietly.

= Will this make my site faster? =

It removes cron work from the page loads it currently lands on. If your site has
few scheduled tasks, you may not notice a difference. If you run WooCommerce, a
backup plugin, or anything that sends batches of email, the affected requests get
noticeably quicker. It is not a caching plugin and won't change your Core Web
Vitals on its own.

= Is it safe to run alongside a caching plugin? =

Yes. SwiftQueue doesn't modify page output. It's been checked against WP Rocket,
LiteSpeed Cache, and Redis Object Cache.

= What happens to my scheduled tasks if I deactivate it? =

Nothing. WordPress resumes running them the default way. SwiftQueue never removes
or rewrites your scheduled events on deactivation.

= Can scheduled events still be lost? =

Yes, and this is worth understanding because it is a WordPress limitation rather
than something any plugin can fully fix.

WordPress keeps every scheduled event in a single option with no locking. A cron
run that takes a while — Action Scheduler on a busy store, for example — holds
its own copy of that list. If another request schedules something while that run
is in progress, the long-running process can write its older copy back and the
newly scheduled event disappears. No error is raised.

Running cron more often makes this more likely, so a plugin that spawns workers
has to be careful not to make it worse. SwiftQueue takes a concurrency lock
before spawning, avoids writing to the cron list on ordinary page requests, and
never rewrites that list behind WordPress's back.

The most effective fix available to you is the one on the Production Setup tab:
set `DISABLE_WP_CRON` and run cron from a real system crontab on a fixed
schedule. That gives you predictable, non-overlapping runs.

= Does "defer housekeeping" delete anything? =

No. It reschedules tasks later using WordPress's own scheduling functions, and
caps how many times any single task can be pushed back so nothing is starved.
It's off by default.

== External services ==

This plugin connects to Freemius, the service that handles licensing, payments
and plugin updates for SwiftQueue.

What is sent, and when:

* **On activation, only if you agree.** The first screen asks whether to share
  your site URL, your admin email address, and basic environment details (PHP
  and WordPress versions, active theme and plugins). Choosing "Skip" sends none
  of it, and the plugin works exactly the same either way.
* **When you activate a paid licence.** Your licence key and site URL are sent
  so the licence can be validated and counted against your allowance.
* **When checking for updates.** The site URL and the installed version are sent
  so the correct update can be offered.

Nothing is sent for visitors to your site, and no page content, post content or
customer data is ever transmitted.

Service: Freemius, Inc. — https://freemius.com
Terms: https://freemius.com/terms/
Privacy policy: https://freemius.com/privacy/

The background task engine itself makes no external requests. It only calls your
own site's wp-cron.php, on your own server.

== Screenshots ==

1. Overview — queue status, recent spawns, and health at a glance
2. Tasks — every scheduled task, by name, with when it runs
3. Production Setup — readiness check and copy-paste cron command
4. Site Health integration — cron problems reported where WordPress reports everything else

== Changelog ==

= 3.2.2 =
* Changed: Task Inspector controls (run / defer / cancel, dead-letter recovery,
  Action Scheduler queue runner) and structured JSON logging are now free for
  everyone — no licence checks anywhere in this plugin.
* Changed: premium features (priority lanes, contention shield, adaptive
  throttling, alerts, weekly digest, REST endpoints, multisite dashboard,
  WooCommerce Checkout Priority Mode) now live entirely in the separate Pro
  plugin rather than shipping here in a gated state.
* Removed: load_plugin_textdomain() call — WordPress loads translations for
  directory-hosted plugins automatically.

= 3.2.1 =
* New: background workers now release the visitor's connection before running
  the queue. Previously the request that triggered a background run could wait
  up to a second for the server to answer — measured at a median of 820ms on
  stock WordPress and 8ms after this change. This was the plugin's core promise,
  so this release is the first one where the benchmarks show it clearly beating
  a stock install where it counts.
* New: licensing and updates via Freemius, with a customer portal for licence
  keys, receipts and VAT invoices. The free version remains fully functional
  and free forever; see the External services section for exactly what is sent
  and when.
* Fixed: uninstall cleanup moved from uninstall.php to the uninstall hook so it
  cooperates with the licensing SDK's own cleanup. Deleting the plugin still
  removes every option, transient, log file and scheduled event it created.
* Changed: premium features now ship separately from the free plugin instead of
  being locked in place inside it.

= 3.2.0 =
* Fixed: the plugin added roughly seven uncached database queries to every
  front-end request -- two `SHOW FULL PROCESSLIST` calls and five queries
  against the Action Scheduler table, three of them `COUNT(*)`. All of it ran
  before the plugin had even checked whether anything was due. Measured on a
  stock install: 62 queries per request before, 55 after. The saving is far
  larger on busy stores, where the Action Scheduler table is big enough for
  those counts to be genuinely slow.
* Fixed: a stalled queue could email you every five minutes indefinitely. The
  alert cooldown keyed on the rendered message text, which embeds a live
  counter, so the cooldown never matched itself. It now keys on the kind of
  problem.
* Fixed: PagerDuty alerts opened a new incident every time instead of updating
  the one already open.
* Fixed: Slack alerts showed a literal "\n" instead of a line break.
* Fixed: two simultaneous requests could both believe they held the processing
  lock on sites without a persistent object cache.
* Fixed: turning off the weekly digest left its scheduled event in place
  forever.
* Added: alert webhooks are refused for loopback, private-network and cloud
  metadata addresses. Use the `swiftqueue_allow_private_webhooks` filter if you
  genuinely need an internal endpoint.
* Fixed: background cron never actually ran. The loopback request sent a
  `doing_wp_cron` parameter, which wp-cron.php treats as a lock key and compares
  strictly against a transient the plugin never set. wp-cron.php therefore
  returned without processing a single event, while the plugin reported the
  spawn as successful. Verified against WordPress 7.0.3.
* Fixed: WordPress cron was never actually taken off page loads. The plugin
  removed `_wp_cron` from `wp_loaded` and `spawn_cron` from `shutdown`; current
  WordPress registers neither. It now removes `wp_cron` from `init`, which stops
  the whole chain.
* Added: if a background dispatch fails, cron is handed back to WordPress for
  that request. Previously a host that blocks loopback requests could have ended
  up running no scheduled tasks at all.
* Fixed: the loopback diagnostic reported failure on healthy sites. It waited
  for wp-cron.php to process the entire queue within 2 seconds, so any site with
  real work queued was told loopback was broken. It now probes connectivity
  without running the queue, and distinguishes "reachable but slow" from
  "loopback is blocked" -- which need completely different fixes.
* Removed: the cron secret is no longer placed in the loopback URL or in the
  generated crontab commands. Nothing ever verified it, and it was being written
  into web server access logs.
* Fixed: WooCommerce integration never loaded. The plugin bootstrapped at file
  include time, before WooCommerce was loaded, so the checkout protection
  features silently never activated on any site.
* Fixed: possible loss of scheduled events. The priority engine filtered
  `pre_option_cron`, and because WordPress reads through that filter and writes
  the result back when scheduling, low-priority events could be permanently
  deleted. Priority handling now works through spawn gating and WordPress's own
  scheduling API, and never rewrites the cron option behind your back.
* Fixed: spawn telemetry could report successes that had not occurred.
* Removed: shell-based worker dispatch (`exec`/`shell_exec`). It was unavailable
  on most managed hosts and blocked WordPress.org distribution. Loopback dispatch
  now retries as a blocking request if the fire-and-forget attempt fails.
* Added: optional housekeeping deferral under database contention, with a
  starvation cap. Off by default.
* Changed: translations now load on `init` (fixes a WordPress 6.7+ notice).
* Changed: telemetry exports redact tokens, secrets, and webhook URLs.
* Changed: uninstall now removes spawn-rate transients and all scheduled hooks.

= 3.1.0 =
* Multi-track priority engine (Express / Standard / Housekeeping)
* Database contention detection
* Priority Tracks telemetry dashboard
* Developer filters: swiftqueue_hook_priority_map, swiftqueue_db_contention_detected

= 3.0.0 =
* WooCommerce checkout protection
* Multisite network dashboard
* Slack, Discord, Teams, PagerDuty webhook formats
* Hosting detection, cache plugin compatibility panel
* Weekly digest email, REST ping endpoint

= 2.0.0 =
* Scale profiles, watchdog, REST API, WP-CLI, Site Health

= 1.0.0 =
* Initial release

== Upgrade Notice ==

= 3.2.1 =
Background workers now answer the triggering request in milliseconds instead of
up to a second — the core fix this plugin exists for. Recommended for everyone.

= 3.2.0 =
Fixes four significant bugs, including two that meant background cron never
actually ran and the WooCommerce integration never activated. The priority engine
could also delete scheduled events. Upgrading is strongly recommended.
