Module: Solrengine::Sdp::WalletOwner
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/solrengine/sdp/wallet_owner.rb
Overview
Mixin for the host app’s user (wallet-owner) model. Expects four columns (the install generator adds them):
sdp_wallet_id :string — SDP's walletId once provisioned
wallet_address :string — the wallet's Solana public key
sdp_provisioning_state :string, default: "pending", null: false
sdp_provisioning_error :string — renderable failure reason
Provisioning is a state machine, not a fire-and-forget job:
pending → provisioning → ready | failed
failed → pending (retry_provisioning!)
provisioning (stale) → pending (retry_provisioning! — a
row whose updated_at is past Configuration#provisioning_lease was
abandoned by a dead worker, never settled by a live one)
ProvisionWalletJob drives every transition; “still provisioning” and “permanently wallet-less” are always distinguishable, and a failure carries a reason the app can render and re-trigger.
Provisioning timing is the app’s call — the concern deliberately wires NO callback. To provision on signup, add one line to the host model:
after_create_commit :provision_wallet!
States are plain strings rather than a Rails enum so the mixin cannot collide with the host model’s own enums or generated methods.
Constant Summary collapse
- PROVISIONING_STATES =
%w[pending provisioning ready failed].freeze
Instance Method Summary collapse
-
#provision_wallet! ⇒ Object
Enqueues provisioning.
-
#retry_provisioning! ⇒ Object
Re-arms a failed row — or a STALE provisioning row abandoned by a dead worker: clears the stored reason, resets to pending, and enqueues a fresh job.
-
#sdp_wallet_label ⇒ Object
SDP wallet label this user provisions under.
- #wallet_failed? ⇒ Boolean
- #wallet_pending? ⇒ Boolean
- #wallet_provisioning? ⇒ Boolean
-
#wallet_provisioning_stale? ⇒ Boolean
A provisioning row whose lease has lapsed: no live job has touched it within Configuration#provisioning_lease (every claim/retry/settle renews updated_at), so the worker that claimed it died before settling.
-
#wallet_provisioning_state ⇒ Object
Tolerates NULL (rows predating the column default): no state is pending.
- #wallet_ready? ⇒ Boolean
Instance Method Details
#provision_wallet! ⇒ Object
Enqueues provisioning. No-op (with a log line) when the wallet is already ready or a live job currently owns the row; from failed it re-enqueues — the job’s claim accepts failed rows, so an explicit reset via retry_provisioning! is equivalent but also clears the error. A STALE provisioning row (lease lapsed — the claiming worker died before settling) also re-enqueues: the job’s claim takes over expired leases, and label adoption makes the re-run double-provision-safe.
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/solrengine/sdp/wallet_owner.rb', line 90 def provision_wallet! if wallet_ready? || (wallet_provisioning? && !wallet_provisioning_stale?) Solrengine::Sdp.configuration.logger&.info( "[Solrengine::Sdp] provision_wallet! no-op for #{self.class.name}##{id}: " \ "state is #{wallet_provisioning_state}" ) return false end ProvisionWalletJob.perform_later(self) end |
#retry_provisioning! ⇒ Object
Re-arms a failed row — or a STALE provisioning row abandoned by a dead worker: clears the stored reason, resets to pending, and enqueues a fresh job. Anything else (including provisioning rows a live job still owns) is a no-op returning false.
106 107 108 109 110 111 |
# File 'lib/solrengine/sdp/wallet_owner.rb', line 106 def retry_provisioning! return false unless wallet_failed? || wallet_provisioning_stale? update!(sdp_provisioning_state: "pending", sdp_provisioning_error: nil) ProvisionWalletJob.perform_later(self) end |
#sdp_wallet_label ⇒ Object
SDP wallet label this user provisions under. The namespace prefix guards against cross-app collisions when several apps share one SDP project (see Configuration#label_namespace).
69 70 71 |
# File 'lib/solrengine/sdp/wallet_owner.rb', line 69 def sdp_wallet_label "#{Solrengine::Sdp.configuration.label_namespace}-user-#{id}" end |
#wallet_failed? ⇒ Boolean
62 63 64 |
# File 'lib/solrengine/sdp/wallet_owner.rb', line 62 def wallet_failed? wallet_provisioning_state == "failed" end |
#wallet_pending? ⇒ Boolean
50 51 52 |
# File 'lib/solrengine/sdp/wallet_owner.rb', line 50 def wallet_pending? wallet_provisioning_state == "pending" end |
#wallet_provisioning? ⇒ Boolean
54 55 56 |
# File 'lib/solrengine/sdp/wallet_owner.rb', line 54 def wallet_provisioning? wallet_provisioning_state == "provisioning" end |
#wallet_provisioning_stale? ⇒ Boolean
A provisioning row whose lease has lapsed: no live job has touched it within Configuration#provisioning_lease (every claim/retry/settle renews updated_at), so the worker that claimed it died before settling. Stale rows are re-enqueueable; fresh ones belong to a live job and must be left alone.
78 79 80 81 |
# File 'lib/solrengine/sdp/wallet_owner.rb', line 78 def wallet_provisioning_stale? wallet_provisioning? && updated_at <= Time.current - Solrengine::Sdp.configuration.provisioning_lease end |
#wallet_provisioning_state ⇒ Object
Tolerates NULL (rows predating the column default): no state is pending.
46 47 48 |
# File 'lib/solrengine/sdp/wallet_owner.rb', line 46 def wallet_provisioning_state self[:sdp_provisioning_state].presence || "pending" end |
#wallet_ready? ⇒ Boolean
58 59 60 |
# File 'lib/solrengine/sdp/wallet_owner.rb', line 58 def wallet_ready? wallet_provisioning_state == "ready" end |