Skip to content

Media offload can enqueue duplicate optml_start_processing_images jobs #1074

@pirate-bot

Description

@pirate-bot

Summary

Optimole media offload/rollback background processing can appear to start multiple overlapping scheduled image-processing jobs when the start/sync path is hit more than once close together.

Expected behavior: a media offload or rollback transfer runs as a single coordinated background process for the active transfer.

Actual behavior: the inspected start path can enqueue additional processing jobs while the transfer status is still active, which may lead to duplicate work under concurrent cron or dashboard/API requests.

Impact: affected sites may see repeated background processing, elevated PHP usage, and increased Optimole-related API traffic while a transfer is active.

Customer context

  • Product / area: Optimole media offload / scheduled image processing
  • Version: Not provided
  • Environment: WordPress site using WP-Cron; Action Scheduler availability unknown from the thread
  • Integration / third party: WP-Cron / possible Action Scheduler path
  • Reported error / symptom: Repeated image optimization tasks, duplicate optimization jobs, continuous Optimole REST/API activity including /wp-json/optml/v1/optimizations
  • Impact: Increased PHP utilization on the reported site

Reproduction notes

Reported evidence only; no local runtime reproduction was performed.

Reported workflow:

  1. Optimole is active on a WordPress site.
  2. Scheduled image optimization/media processing appears to run via WP-Cron repeatedly.
  3. Multiple concurrent cron executions appear to create duplicate optimization jobs.
  4. The site observes continuous Optimole REST/API activity, including /wp-json/optml/v1/optimizations, and increased PHP utilization.

Repo-confirmed likely reproduction to verify:

  1. Start an Optimole media offload or rollback transfer from the dashboard or equivalent authenticated REST call.
  2. Trigger the non-refresh start path more than once close together while the transfer status remains active.
  3. Inspect whether more than one optml_start_processing_images action is pending/running for the same transfer.

Missing details: exact plugin version, cron runner setup, Action Scheduler presence, transfer type, and scheduled job records.

Diagnosis

Conclusion

The media offload/rollback background processor has a confirmed duplicate scheduling risk in the inspected code path. The dashboard REST start endpoint reaches Optml_Media_Offload::move_images(), which schedules optml_start_processing_images when a transfer is active. That start path does not check whether an equivalent pending/running action already exists, and the processor schedules its next batch after each run. This supports the reported duplicate scheduled image-processing jobs under concurrent or repeated execution.

The reported /wp-json/optml/v1/optimizations calls are part of the page profiling REST endpoint, not the offload cron scheduler in the inspected code. They may be an observed side effect or a separate symptom, but the stronger confirmed defect is in the offload/rollback scheduling path.

Where this likely occurs

  • User-visible surface: Optimole dashboard media offload/rollback flow and active transfer sync/polling.
  • inc/rest.phpOptml_Rest::$rest_routes lines 93–95 registers number_of_images_and_pages as a POST media cloud route.
  • inc/rest.phpOptml_Rest::register_media_offload_routes() lines 287–292 registers media offload routes with manage_options by default unless a route-specific callback is provided.
  • inc/rest.phpOptml_Rest::number_of_images_and_pages() lines 824–836 reads action/refresh and calls Optml_Media_Offload::move_images().
  • assets/src/dashboard/parts/connected/settings/OffloadMedia.jsOffloadMedia lines 100–113 calls sync with refresh: true when offload/rollback is already in progress; lines 117–135 and 138–157 start offload/rollback and call sync after saving settings.
  • inc/media_offload.phpOptml_Media_Offload::instance() lines 176–186 registers optml_start_processing_images and init -> maybe_reschedule.
  • inc/media_offload.phpOptml_Media_Offload::maybe_reschedule() lines 202–219 checks is_scheduled( 'optml_start_processing_images' ) before recovery rescheduling, showing a scheduled-action guard exists only for the missed-cron recovery path.
  • inc/media_offload.phpOptml_Media_Offload::move_images() lines 1854–1913 computes transfer state and schedules initial optml_start_processing_images when refresh is false, without an equivalent scheduled-action guard for the active transfer.
  • inc/media_offload.phpOptml_Media_Offload::schedule_action() lines 1946–1952 delegates to Action Scheduler when available, otherwise to WP-Cron.
  • inc/media_offload.phpOptml_Media_Offload::start_processing_images() lines 2035–2101 guards only on transfer status, processes a batch, and schedules the next optml_start_processing_images action after each successful batch or retryable exception.
  • Git history: git blame shows the current initial scheduling block around inc/media_offload.php lines 1902–1913 from commit 52ebcd907 dated 2025-04-03; recursive scheduling around lines 2074–2100 has existed since earlier commits including 28adecca6 and d9dcf38d. No clear version boundary was confirmed from tags during this inspection.

Engineering notes

The status options (offloading_status, rollback_status, and transfer_status) coordinate whether a transfer is active, and the opposite transfer type is disabled when starting a new mass action. Those flags do not act as a per-run lock because repeated start requests for the same active action still see the status as active.

The dashboard calls the sync endpoint both after starting a transfer and on load when a transfer is already in progress. The refresh: true path avoids initial scheduling, but the non-refresh start path schedules immediately. If the non-refresh start path is triggered more than once before the first scheduled job claims or clears state, duplicate scheduled actions for the same transfer appear possible from the inspected code.

The page profiling endpoint /optml/v1/optimizations is separate. assets/js/modules/main.js checks missing devices and sessionStorage before calling optmlApi.sendToRestApi(); assets/js/modules/api.js sends to /optimizations; inc/rest.php validates and stores profile data in Optml_Rest::optimizations(). This path did not show a WP-Cron scheduling connection during inspection.

Action Scheduler internals and WordPress core cron internals were not inspected in the workspace. The conclusion is based on Optimole’s scheduling calls and the absence of a product-level duplicate guard in the start/processor paths.

Test coverage status

No relevant PHP tests for Optml_Media_Offload::move_images(), Optml_Media_Offload::schedule_action(), Optml_Media_Offload::start_processing_images(), or optml_start_processing_images were found during inspection of tests/.

Relevant JavaScript tests exist for the separate /optimizations page profiling client path in assets/js/modules/__tests__/api.test.js, including sendBeacon/fetch behavior and processed marking. Those tests do not cover media offload scheduling or duplicate background jobs.

What to verify or explore next

  • Reproduce on a local WordPress site by starting media offload/rollback and triggering the start REST path twice in close succession, then inspect scheduled optml_start_processing_images entries.
  • Repeat the check with Action Scheduler available and with the WP-Cron fallback path.
  • Capture whether duplicate jobs process the same attachment batch or only create redundant pending actions.
  • Compare behavior when the dashboard reloads during an active transfer versus repeated explicit transfer starts.
  • Check whether the reported /wp-json/optml/v1/optimizations traffic correlates with active media offload, page profiling visits, or both.

Unknowns / follow-up

  • Customer’s Optimole version was not provided.
  • Action Scheduler availability and cron configuration on the reported site are unknown.
  • No customer logs or scheduled-action table rows were available in the transcript.
  • The exact relationship between repeated /optimizations calls and duplicate offload/rollback scheduled jobs remains unverified.

Confidence

Confidence: 82/100

Repository inspection found a reachable media offload scheduling path that can enqueue the same background processor without a hard pending/running-job guard; the reported concurrency/high-load symptom matches that risk.


Source: HelpScout #3344927857
Generated by bug-report-triage workflow (ID: bug-report-triage_6a21cb4c19b580.60000883)

Metadata

Metadata

Assignees

No one assigned

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions