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
47
48
49
50
51
52
# 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

  # Redistributing the parent's auth onto the child can leave the PARENT
  # short if its own total settled above the authorized amount. It has no
  # other trigger, so reconcile it too (no-op unless its deliveries are
  # settled and it's actually under-authorized).
  Order::AuthorizationTopupWorker.perform_async(parent.id) if parent.needs_shared_pi_authorization_topup?
end