Documentation · System Requirements
Cron and Background Processing
Purpose
ADP Car Market Hub depends on scheduled background tasks for almost everything that is not a direct user action: it imports vehicles from AutoScout24, processes images asynchronously, cleans up analytics data, refreshes pricing analysis and runs daily data-quality scans. This document explains the cron mechanisms the plugin uses, the differences between WordPress's built-in scheduler and a real server cron, the recurring jobs the plugin schedules, and the operational signals to monitor.
When to use this document
Use this document when you:
- Decide between WP-Cron and an external server cron for a new dealership site.
- Configure the cron mode, frequency and secret token in the Import & Limits tab.
- Wire an external scheduler (Linux cron, hosting cron UI, or a remote pinger) to the plugin's REST cron endpoint.
- Investigate why imports are not running on schedule, or why image processing is delayed.
- Audit which recurring jobs the plugin registers and how long their data is retained.
Overview
The plugin's background-processing model has three layers:
- A trigger layer that decides when work should start. This can be WordPress's pseudo-cron (driven by site visits to
wp-cron.php) or an external server cron that calls eitherwp-cron.phpdirectly or the plugin's token-secured REST endpoint at/wp-json/as24ci/v1/cron-import. - A scheduler layer that owns the recurring jobs. The plugin registers custom intervals (every 5 minutes, every 6 hours, plus a configurable "every N minutes" interval with a 15-minute floor) and a small set of WP-Cron hooks for imports, the image queue, the AI generation queue, analytics cleanup, pricing analysis and the daily taxonomy scan.
- A worker layer that does the actual work. Each WP-Cron hook is bound to a class method (importer, image queue, analytics cleanup, etc.) that uses transient-based locks to prevent overlapping runs and writes status/heartbeat options that the System & Help / Health tab and the dashboard widget read back.
All three import paths — the scheduled WP-Cron hook, the REST cron endpoint and the "Trigger now" admin button — call the same shared runner, so behaviour and locking are identical regardless of trigger.
WordPress cron vs. server cron
The Import & Limits tab exposes two trigger modes; both are supported, but they have very different reliability profiles.
WordPress Cron (default)
- Driven by visitor traffic. Each request to a WordPress page may spawn
wp-cron.phpin the background. - Works on any host without server access.
- Becomes unreliable on low-traffic sites: with no visitors there are no cron runs.
- The plugin still installs all of its hooks; missing runs simply accumulate until the next visit.
Server cron (recommended for production)
- Driven by the operating system or hosting control-panel scheduler.
- Independent of website traffic, predictable, and required by the plugin's Health checks for a "fully ready" production status.
- Recommended setup:
1. Set
define( 'DISABLE_WP_CRON', true );inwp-config.phpso visit-driven cron is disabled. 2. Add a server cron entry that calls the plugin's REST endpoint with the secret token. 3. Add a second entry that runswp-cron.phpitself, so non-import recurring jobs (image queue, analytics cleanup, pricing, etc.) still fire.
Switching to Server Cron in the Import & Limits tab hides the WP-Cron schedule fields and reveals the REST trigger URL, the secret token, and copy-ready example commands.
Recurring jobs registered by the plugin
The following WP-Cron hooks are scheduled by the plugin (some only when the related feature is configured). The System & Help tab lists their next scheduled run time so they can be inspected at any moment.
| Hook | Purpose | Frequency |
|---|---|---|
as24ci_scheduled_import | Main vehicle import runner; calls the AutoScout24 API for each configured seller. | Configurable in the Import & Limits tab (hourly, twice daily, daily, every 6 hours, every 5 minutes, or a custom "every N minutes" interval with a minimum of 15 minutes). |
as24ci_image_queue_process | Asynchronous image worker; downloads remaining vehicle images after the first one is loaded inline during import. | Every 5 minutes when the image queue is enabled. |
as24ci_daily_cleanup | Deletes analytics events older than the configured retention window (default 180 days, minimum 7 days). | Daily. |
as24ci_pricing_analysis_cron | Recomputes the pricing-engine analysis for the inventory. | Daily. |
as24ci_automated_taxonomy_scan | Background data-quality / taxonomy scan. | Frequency configured by the Data Quality module. |
as24ci_competitor_watcher_cron | Legacy cleanup only; the Competitor Watcher feature has been removed and is not active. The hook name is retained so that any leftover scheduled event from older installations is cleared on plugin deactivation. | Not scheduled. |
| AI generation queue hook | Asynchronous AI Assistant generation worker; only scheduled when the AI Assistant is enabled and configured. | Driven by the AI Assistant settings. |
Activation registers the recurring jobs that should always exist (imports, analytics cleanup, pricing, image queue, AI queue when applicable). Deactivation removes the plugin's WP-Cron entries via wp_clear_scheduled_hook() for each hook above.
Recurring imports
The import runner is shared by all three trigger paths and behaves as follows:
- Locking. Before doing any work the runner sets a transient (
as24ci_cron_import_running) with a TTL of roughly 40 minutes. Subsequent runs that arrive while the lock is held exit cleanly and report that an import is already running. This prevents WP-Cron and a server cron from racing against each other. - Per-seller processing. The runner iterates over every configured Seller ID and calls the importer for each one in turn.
- Vehicles per run. The Import & Limits tab exposes a "Vehicles per Run" cap (0 = no limit). Lowering this value is the primary lever for stability on shared hosting and very large inventories; recommended values are 50–80 for large catalogues.
- Status persistence. After each run, options are updated with the last run timestamp, the trigger source (
wp-cron,rest, manual) and per-seller counts. The dashboard widget and System & Help tab read these options to render last-run information. - Optional full sync. When the Full Sync option is enabled, the runner can mark vehicles missing from the latest API response as deleted; this is permanent, so a tested backup strategy is required (see Hosting Requirements).
The Batch-Wizard in the admin UI uses the same importer but processes one vehicle per step from a queued list (transient as24ci_batch_queue), which is useful for very large initial imports on constrained hosts.
Image queue and asynchronous workers
When Enable Image Queue is on (recommended for image-heavy imports):
- During import only the first image of each vehicle is downloaded synchronously, so the page returns quickly and the cron run completes well within PHP execution-time limits.
- Remaining image URLs are appended to the image queue (a WordPress option) and processed in batches by the
as24ci_image_queue_processhook every 5 minutes. - The worker uses its own transient lock (
as24ci_image_queue_running, 10-minute TTL) and processes a fixed number of images per batch. - A safety limit (the queue size limit constant in
Scheduler) caps how large the queue may grow before the plugin logs a warning and forcibly de-duplicates entries.
The AI generation queue follows a similar pattern: AI calls during import are deferred to a queue and processed by an async worker so that import runs are not blocked by the managed Gemini endpoint.
Cleanup and retention routines
- Analytics retention.
Analytics::cleanup_old_data()(hookas24ci_daily_cleanup) deletes analytics rows older than the value in the Analytics retention days setting. The default is 180 days; the minimum enforced in code is 7 days. - Log rotation. Plugin logs in
wp-content/uploads/as24ci-logs/are rotated when a single file reaches 10 MB, and rotated files are deleted after 7 days. This is independent of WP-Cron and runs on each log write. - Token cache. OAuth access tokens are cached in a transient until shortly before their advertised
expires_in. A "Clear Token Cache" tool exists for diagnostics. - Vehicle deletions. When the plugin removes a vehicle (Full Sync or manual deletion) it cleans up the related media attachments and meta through a central deletion path.
REST cron endpoint
The token-secured trigger endpoint is registered by Cron_Endpoint:
- Route:
GET /wp-json/as24ci/v1/cron-import - Authentication: a 32-character random secret stored in the
as24ci_cron_tokenoption. The endpoint accepts the token in two ways: - Preferred:
Authorization: Bearer <token>HTTP header (keeps the token out of access logs). - Fallback:
?token=<token>query parameter. - Response codes:
200on success,429when the lock is already held (an import is already running),403for missing/invalid tokens,500for uncaught exceptions. - Side effect: every successful call updates the
as24ci_last_external_cron_runoption, which the System & Help tab uses to confirm the external cron is alive. - A separate, unauthenticated heartbeat is recorded whenever any WordPress URL is hit with
?as24ci_cron=1, which is useful for cheap external pingers that only need to confirm reachability.
The Import & Limits tab generates copy-ready example commands such as:
*/15 * * * * curl -s "https://example.com/wp-json/as24ci/v1/cron-import?token=YOUR_TOKEN" > /dev/null
*/5 * * * * php /var/www/html/wp-cron.php > /dev/null 2>&1
The first entry triggers imports; the second keeps non-import WP-Cron hooks (image queue, analytics cleanup, pricing, etc.) running when DISABLE_WP_CRON is true.
Operational monitoring
The plugin exposes the signals operators need to monitor without any extra tooling:
- System & Help / Health tab. Lists every plugin cron hook, its next scheduled run, and whether scheduling is currently handled by WP-Cron or by an external server cron. Includes a card that flags
DISABLE_WP_CRONas recommended in server-cron mode. - Dashboard widget. Shows the most recent import run, the next scheduled import (when WP-Cron is in use), the image-queue depth and the next queue run.
- Plugin logs.
wp-content/uploads/as24ci-logs/records each cron run, lock acquisition/release, image-queue activity and any HTTP errors. Logs rotate at 10 MB with 7-day retention. - Last-run options.
as24ci_last_external_cron_runand the corresponding internal options can be checked directly via WP-CLI for scripted alerting.
A simple production setup is:
- Uptime check on the public archive URL (front-end availability).
- Uptime check on
/wp-json/as24ci/v1/cron-import?token=…returning a2xx/429status (cron path reachable and authenticating). - Disk-space alert on the
wp-content/uploads/volume (image growth and logs). - Optional log-shipping or periodic review of the plugin log directory.
Troubleshooting
- Imports never run automatically. Confirm the cron mode in the Import & Limits tab. If WP-Cron is selected, low-traffic sites may not fire cron at all — switch to server cron. If server cron is selected, verify that the curl/wget command actually reaches the REST endpoint (HTTP 200 or 429 expected).
- "An import is already running" responses (HTTP 429). The lock transient is still held from a previous run. Wait for the run to finish, or clear the
as24ci_cron_import_runningtransient if a previous PHP process crashed without releasing the lock. Lower Vehicles per Run to keep individual runs comfortably below the lock TTL. - Image queue grows without shrinking. Confirm that
wp-cron.phpis being executed (in server-cron mode this requires the second cron entry shown above), check the log directory for queue-worker errors, and verify outbound HTTPS to the image hosts (see API, Network and SSL Requirements). - Analytics or pricing data not refreshed. These run via WP-Cron daily; if
DISABLE_WP_CRONis true and there is no second cron entry callingwp-cron.php, daily jobs will never fire. - System & Help tab shows the cron token is not configured. Open the Import & Limits tab, switch to server-cron mode and either let the plugin auto-generate a token or paste your own and save.
- Token leaked or rotated. Click Regenerate Token in the Import & Limits tab. Update every external scheduler immediately, since the previous token stops working as soon as the new one is saved.
- Cron runs on staging affect production data. Use a different cron token per environment and consider a different AutoScout24 client when possible (see Hosting Requirements).