Class: Order::AuthorizationTopupWorker

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

Overview

Deferred shared-PI authorization top-up for an order left short by a split.

The split's coupon reallocation and shipping re-quote can raise an order's
total above what was authorized at split time (the authorization is a
snapshot taken while the delivery is still quoting). This worker reconciles
the gap once the total is final — enqueued when a split-related delivery
leaves quoting (see the Delivery after_commit hook). Runs for the PARENT too,
which AuthorizationSplitWorker never re-funds.

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

Instance Method Summary collapse

Instance Method Details

#perform(order_id) ⇒ Object

Parameters:

  • order_id (Integer)

    the under-authorized order to top up



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
# File 'app/workers/order/authorization_topup_worker.rb', line 23

def perform(order_id)
  order = Order.find_by(id: order_id)
  return unless order&.needs_shared_pi_authorization_topup?

  # Serialize per order so two delivery commits can't both top up the auth.
  # Bang form raises on lock-acquisition timeout so Sidekiq retries rather
  # than the job exiting "successfully" without ever running the top-up.
  Order.with_advisory_lock!("order_auth_topup_#{order_id}", timeout_seconds: 10) do
    order.reload
    next unless order.needs_shared_pi_authorization_topup? # re-check under lock

    Rails.logger.info("[AuthorizationTopupWorker] Topping up shared-PI authorization for order #{order.id}")
    result = Order::AuthorizationSplitter.topup(order)

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