Module: Workers::EdiFlowDispatch
- Extended by:
- ActiveSupport::Concern
- Included in:
- EdiInventoryFlowWorker, EdiPriceFlowWorker
- Defined in:
- app/concerns/workers/edi_flow_dispatch.rb
Overview
Turns a monolithic EDI flow worker into a Sidekiq Pro batch of one job per
ORCHESTRATOR CLASS, and gives the batch a completion callback.
The wiki's serial → parallel → back-to-serial shape
(https://github.com/sidekiq/sidekiq/wiki/Complex-Job-Workflows-with-Batches),
already used by EdiProductDataFlowWorker. Two things it buys that the
single job could not:
- Isolation. Edi::BaseOrchestrator.execute_flow walks every partner of
every orchestrator in ONE job, so a partner that HANGS holds the worker's
unique lock and silently coalesces every later scheduled run — a hung
Menard upload stopped Wayfair, Walmart, CommerceHub, Amazon and 31
reseller feeds for 8.5 hours on 2026-08-02. Fanned out, the lock is
per-orchestrator and Menard can only ever stop Menard. - A consumer for the results.
execute_flowbuilds a per-partner result
array with:errorentries and returns it to a Sidekiq worker, which
discards it. EdiFlowFinalizer reports it.
PER CLASS, NOT PER PARTNER — deliberately. Each vendor's flow paces itself
internally (Amazon sleeps between marketplaces; its twelve share two SP-API
accounts whose feed quota is metered per ACCOUNT — see
Edi::Amazon::FeedSubmissionBudget). Splitting partners into parallel jobs
discards that pacing. One job per class keeps every vendor's sequencing
exactly as it is today and still isolates vendors from each other.
ponytail: the fanned-out jobs run on the caller's queue (default), so peak
memory is now N orchestrators in flight rather than one. Realistically 3-4 do
real work per hour and each holds what the single job already held
sequentially. If peak RSS becomes the constraint, the upgrade is a dedicated
queue on the sidekiq_edi role (concurrency 4) — a capacity change with its
own DB_POOL/PgBouncer budget review, not a code change here.
Instance Method Summary collapse
-
#dispatch_flow(flow, options) ⇒ String, Array<Hash>
Runs +flow+ across every orchestrator class that has work for it.
Instance Method Details
#dispatch_flow(flow, options) ⇒ String, Array<Hash>
Runs +flow+ across every orchestrator class that has work for it.
A targeted request (CRM's per-partner buttons pass partner) runs inline:
fanning out a single target buys nothing and would drop the partner filter.
It still promotes partner failures to an exception, so a targeted run and a
fanned-out one fail the same way — otherwise execute_flow's :error
entries would be swallowed on exactly the path a human is watching.
54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/concerns/workers/edi_flow_dispatch.rb', line 54 def dispatch_flow(flow, ) orchestrator_name = ['orchestrator_name'].presence partner = ['partner'].presence if partner results = Edi::BaseOrchestrator.execute_flow(flow, orchestrator_name:, partner:) return EdiOrchestratorFlowWorker.promote_failures!(results, "#{flow} #{partner}") end targets = orchestrator_classes_with_work(flow, orchestrator_name) return [] if targets.empty? enqueue_batch(flow, targets) end |