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:
- Optimole is active on a WordPress site.
- Scheduled image optimization/media processing appears to run via WP-Cron repeatedly.
- Multiple concurrent cron executions appear to create duplicate optimization jobs.
- The site observes continuous Optimole REST/API activity, including
/wp-json/optml/v1/optimizations, and increased PHP utilization.
Repo-confirmed likely reproduction to verify:
- Start an Optimole media offload or rollback transfer from the dashboard or equivalent authenticated REST call.
- Trigger the non-refresh start path more than once close together while the transfer status remains active.
- 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.php — Optml_Rest::$rest_routes lines 93–95 registers number_of_images_and_pages as a POST media cloud route.
inc/rest.php — Optml_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.php — Optml_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.js — OffloadMedia 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.php — Optml_Media_Offload::instance() lines 176–186 registers optml_start_processing_images and init -> maybe_reschedule.
inc/media_offload.php — Optml_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.php — Optml_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.php — Optml_Media_Offload::schedule_action() lines 1946–1952 delegates to Action Scheduler when available, otherwise to WP-Cron.
inc/media_offload.php — Optml_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)
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
/wp-json/optml/v1/optimizationsReproduction notes
Reported evidence only; no local runtime reproduction was performed.
Reported workflow:
/wp-json/optml/v1/optimizations, and increased PHP utilization.Repo-confirmed likely reproduction to verify:
optml_start_processing_imagesaction 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 schedulesoptml_start_processing_imageswhen 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/optimizationscalls 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
inc/rest.php—Optml_Rest::$rest_routeslines 93–95 registersnumber_of_images_and_pagesas a POST media cloud route.inc/rest.php—Optml_Rest::register_media_offload_routes()lines 287–292 registers media offload routes withmanage_optionsby default unless a route-specific callback is provided.inc/rest.php—Optml_Rest::number_of_images_and_pages()lines 824–836 readsaction/refreshand callsOptml_Media_Offload::move_images().assets/src/dashboard/parts/connected/settings/OffloadMedia.js—OffloadMedialines 100–113 calls sync withrefresh: truewhen offload/rollback is already in progress; lines 117–135 and 138–157 start offload/rollback and call sync after saving settings.inc/media_offload.php—Optml_Media_Offload::instance()lines 176–186 registersoptml_start_processing_imagesandinit -> maybe_reschedule.inc/media_offload.php—Optml_Media_Offload::maybe_reschedule()lines 202–219 checksis_scheduled( 'optml_start_processing_images' )before recovery rescheduling, showing a scheduled-action guard exists only for the missed-cron recovery path.inc/media_offload.php—Optml_Media_Offload::move_images()lines 1854–1913 computes transfer state and schedules initialoptml_start_processing_imageswhenrefreshis false, without an equivalent scheduled-action guard for the active transfer.inc/media_offload.php—Optml_Media_Offload::schedule_action()lines 1946–1952 delegates to Action Scheduler when available, otherwise to WP-Cron.inc/media_offload.php—Optml_Media_Offload::start_processing_images()lines 2035–2101 guards only on transfer status, processes a batch, and schedules the nextoptml_start_processing_imagesaction after each successful batch or retryable exception.git blameshows the current initial scheduling block aroundinc/media_offload.phplines 1902–1913 from commit52ebcd907dated 2025-04-03; recursive scheduling around lines 2074–2100 has existed since earlier commits including28adecca6andd9dcf38d. No clear version boundary was confirmed from tags during this inspection.Engineering notes
The status options (
offloading_status,rollback_status, andtransfer_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: truepath 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/optimizationsis separate.assets/js/modules/main.jschecks missing devices andsessionStoragebefore callingoptmlApi.sendToRestApi();assets/js/modules/api.jssends to/optimizations;inc/rest.phpvalidates and stores profile data inOptml_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(), oroptml_start_processing_imageswere found during inspection oftests/.Relevant JavaScript tests exist for the separate
/optimizationspage profiling client path inassets/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
optml_start_processing_imagesentries./wp-json/optml/v1/optimizationstraffic correlates with active media offload, page profiling visits, or both.Unknowns / follow-up
/optimizationscalls 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)