Class: Solrengine::Sdp::TrackTransferJob
- Inherits:
-
ActiveJob::Base
- Object
- ActiveJob::Base
- Solrengine::Sdp::TrackTransferJob
- Defined in:
- app/jobs/solrengine/sdp/track_transfer_job.rb
Overview
Settles every Transfer row into a terminal state (R6). Two modes, keyed on the row’s status:
processing/confirmed → poll get_transfer, map per the status table,
re-enqueue until terminal. A row stuck in processing past
Configuration#expired_transfer_deadline settles as engine-local
"expired" (SDP has no such status). confirmed keeps tracking —
it is user-facing success, but finalized is the terminal verdict.
unknown (the create POST read-timed out, the row never got an SDP id,
or SDP 404ed the id we had) → reconcile: scan the source wallet's
transfers for the engine memo token. Found → adopt the SDP row and
keep tracking; not found → re-enqueue and scan again until the
deadline settles it as failed "unsent (reconcile exhausted)".
Deadline exhaustion is checked at the top of perform, BEFORE any SDP I/O, so an SDP outage can never keep a row unsettled past its deadline (an in-poll check would only fire after a successful GET).
API errors never orphan a row (mirrors ProvisionWalletJob’s posture): Unavailable/Timeout propagate to retry_on; NotFound flips the row to “unknown” so the memo token — not a 404 poll loop — decides; any other Sdp::Error re-enqueues within the deadline and settles the row failed (message renderable) past it.
Backoff: a simple fixed wait (Configuration#transfer_poll_interval, default 3s) rather than exponential — Solana confirmation latency is bounded at seconds, and expired_transfer_deadline caps total tracking, so growing waits would only delay the verdict.
Inherits ActiveJob::Base directly so the engine never depends on the host app’s ApplicationJob (same posture as ProvisionWalletJob).
Class Method Summary collapse
Instance Method Summary collapse
Class Method Details
.poll_interval ⇒ Object
54 55 56 |
# File 'app/jobs/solrengine/sdp/track_transfer_job.rb', line 54 def self.poll_interval Solrengine::Sdp.configuration.transfer_poll_interval.seconds end |
Instance Method Details
#perform(transfer) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'app/jobs/solrengine/sdp/track_transfer_job.rb', line 58 def perform(transfer) return if transfer.terminal? return if settle_past_deadline(transfer) if transfer.unknown? reconcile(transfer) else poll(transfer) end rescue ::Sdp::Unavailable, ::Sdp::Timeout raise # transport: retry_on owns backoff and the exhaustion handoff rescue ::Sdp::NotFound # The id provably doesn't exist at SDP — polling it would 404 # forever. Reconcile by memo token instead: it positively identifies # OUR attempt (found → adopt; never found → the deadline settles # the row as unsent). transfer.update!(status: "unknown") reenqueue(transfer) rescue ::Sdp::Error => e # Auth/rate-limit/validation errors must never strand the row in a # dead-letter: within the deadline they read as an API hiccup — # re-enqueue and try again; past it the row settles failed with the # renderable reason. if past_deadline?(transfer) transfer.settle!("failed", sdp_error: e.) else reenqueue(transfer) end end |