Class: EdiInventoryFlowWorker

Inherits:
Object
  • Object
show all
Includes:
Sidekiq::Job, Workers::EdiFlowDispatch
Defined in:
app/workers/edi_inventory_flow_worker.rb

Overview

Sidekiq worker: edi inventory flow.

+lock_ttl+ is the ceiling on how long ONE wedged partner can suppress the feed
for EVERY partner. This worker walks all orchestrators sequentially, and the
global +lock: :until_and_while_executing+ with +on_conflict: :log+ (see
config/initializers/sidekiq.rb) means a run that HANGS holds the RUN lock and
every later scheduled enqueue is coalesced away with a log line — no dead job,
no retry, no AppSignal incident. That is how a hung Menard portal upload
stopped Wayfair/Walmart/CommerceHub/Amazon/reseller inventory for 8.5 hours on
2026-08-02 (doc/troubleshooting/MENARD_PLAYWRIGHT_OUTAGE_2026_07.md).

2h is a ceiling, not an SLA: a real run of every partner finishes in seconds,
so the TTL can only expire on a wedge and never lets two healthy runs overlap.
Applied to every EDI +execute_flow+ worker for the same reason.

It DOES admit one overlap — a TTL that expires while the wedged run is still
alive lets the next scheduled run start alongside it. That is the trade: one
overlapping run beats no runs until someone notices, and every message this
flow sends is a full snapshot, so a duplicate is wasteful rather than wrong.
An advisory lock spanning the flow was rejected because a hung job holds its
DB session, so the lock would never release and we would be back to the
original bug. Per-flow analysis:
doc/troubleshooting/MENARD_PLAYWRIGHT_OUTAGE_2026_07.md § "The overlap
lock_ttl buys".

Instance Method Summary collapse

Methods included from Workers::EdiFlowDispatch

#dispatch_flow

Instance Method Details

#perform(options = {}) ⇒ String, Array

Returns batch id when fanned out, results when targeted.

Parameters:

  • options (Hash) (defaults to: {})

    optional orchestrator_name / partner filters

Options Hash (options):

  • orchestrator_name (String)

    restrict the flow to one orchestrator class

  • partner (String)

    restrict the flow to one partner

Returns:

  • (String, Array)

    batch id when fanned out, results when targeted



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'app/workers/edi_inventory_flow_worker.rb', line 37

def perform(options = {})
  ErrorReporting.scoped({
    job: self.class.name,
    jid: jid,
    orchestrator_name: options['orchestrator_name'],
    partner: options['partner'],
    options: options,
    worker_start_time: Time.current.iso8601,
    worker_host: Socket.gethostname
  }) do
    dispatch_flow(:execute_inventory_flow, options)
  rescue StandardError => e
    ErrorReporting.error(e, {
      job: self.class.name,
      jid: jid,
      options: options,
      error_type: 'inventory_flow_dispatch_error',
      worker_host: Socket.gethostname,
      message: "Error dispatching inventory flow: #{options.inspect}"
    })
    raise
  end
end