Class: Order::AuthorizationSplitWorker

Inherits:
Object
  • Object
show all
Includes:
Sidekiq::Job
Defined in:
app/workers/order/authorization_split_worker.rb

Overview

Deferred authorization split for a split-off child order.

Enqueued when a child order's delivery is committed (see the Delivery
after_commit hook). By then the order has the delivery the auth-split needs,
so we allocate the parent's authorization onto it — the step that previously
only happened if the delivery existed at split time.

Idempotent: the work is guarded by #needs_authorization_split_from_parent?
(re-checked under an advisory lock), so duplicate enqueues are no-ops.

Instance Method Summary collapse

Instance Method Details

#perform(new_order_id) ⇒ Object

Parameters:

  • new_order_id (Integer)

    the split-off child order id



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'app/workers/order/authorization_split_worker.rb', line 21

def perform(new_order_id)
  new_order = Order.find_by(id: new_order_id)
  return unless new_order&.needs_authorization_split_from_parent?

  parent = new_order.parent
  return unless parent

  # Serialize per parent so two delivery commits can't both split the auth.
  Order.with_advisory_lock("order_auth_split_#{parent.id}", timeout_seconds: 10) do
    new_order.reload
    next unless new_order.needs_authorization_split_from_parent? # re-check under lock

    Rails.logger.info("[AuthorizationSplitWorker] Splitting auth from parent #{parent.id} onto child #{new_order.id}")
    result = Order::AuthorizationSplitter.new(parent, new_order).call

    # Only advance out of pending_payment when the split actually funded the
    # child — never on a no-op or a failed allocation. (The event itself is
    # still a no-op if the transition isn't currently valid.)
    if result.split?
      new_order.reload
      new_order.payment_complete if new_order.balance <= 0
    elsif result.failed?
      Rails.logger.warn("[AuthorizationSplitWorker] Split ran but child #{new_order.id} is still underfunded — leaving in pending_payment")
    end
  end
end