Class: SpreeCmCommissioner::AsyncOperation
- Includes:
- StoreMetadata
- Defined in:
- app/models/spree_cm_commissioner/async_operation.rb
Overview
A long-running operation a human started and is waiting on the result of, with a status an admin screen can poll: queue -> progress -> done | failed.
SCOPE RULE: operations a person initiated and is watching. Not webhook deliveries, not per-order background work, not general job logging.
That rule is what keeps this table small enough to need no retention policy -- admin actions are rare, and the rows are a few hundred bytes of jsonb. cm_exports, the table this is modelled on, has grown unpruned while storing actual files. If a future subclass ever puts high-volume work here, add a purge alongside cleanup_integration_sync_sessions in config/schedule.yml; the [type, status, created_at] index exists to serve exactly that query.
Subclasses supply their own payload/result keys via store_*_metadata and implement #process!. See AsyncOperations::SeatLock.
Direct Known Subclasses
Constant Summary collapse
- ERROR_LIMIT =
1000
Instance Method Summary collapse
-
#enqueue ⇒ Object
Subclasses may override to pick a different queue or a dedicated job.
-
#fail!(message) ⇒ Object
save(validate: false), not update!: this runs from a rescue block, so a subclass validation failing here would raise a second exception and bury the original.
- #finish! ⇒ Object
- #in_progress? ⇒ Boolean
- #process! ⇒ Object
-
#stale? ⇒ Boolean
Heartbeat, not wall clock.
- #start! ⇒ Object
- #timeout ⇒ Object
Instance Method Details
#enqueue ⇒ Object
Subclasses may override to pick a different queue or a dedicated job.
35 36 37 |
# File 'app/models/spree_cm_commissioner/async_operation.rb', line 35 def enqueue SpreeCmCommissioner::AsyncOperationJob.perform_later(async_operation_id: id) end |
#fail!(message) ⇒ Object
save(validate: false), not update!: this runs from a rescue block, so a subclass validation failing here would raise a second exception and bury the original. Recording a failure must not be able to fail.
64 65 66 67 |
# File 'app/models/spree_cm_commissioner/async_operation.rb', line 64 def fail!() assign_attributes(status: :failed, finished_at: Time.current, error: .to_s.truncate(ERROR_LIMIT)) save(validate: false) end |
#finish! ⇒ Object
57 58 59 |
# File 'app/models/spree_cm_commissioner/async_operation.rb', line 57 def finish! update!(status: :done, finished_at: Time.current) end |
#in_progress? ⇒ Boolean
39 40 41 |
# File 'app/models/spree_cm_commissioner/async_operation.rb', line 39 def in_progress? queue? || progress? end |
#process! ⇒ Object
69 70 71 |
# File 'app/models/spree_cm_commissioner/async_operation.rb', line 69 def process! raise NotImplementedError, 'Subclasses must implement #process!' end |
#stale? ⇒ Boolean
Heartbeat, not wall clock. A running operation touches the row as it accumulates results, so real work never looks stale while a killed worker does. Without this the admin panel spins forever.
45 46 47 |
# File 'app/models/spree_cm_commissioner/async_operation.rb', line 45 def stale? in_progress? && updated_at < timeout.ago end |
#start! ⇒ Object
53 54 55 |
# File 'app/models/spree_cm_commissioner/async_operation.rb', line 53 def start! update!(status: :progress, started_at: Time.current) end |
#timeout ⇒ Object
49 50 51 |
# File 'app/models/spree_cm_commissioner/async_operation.rb', line 49 def timeout 20.minutes end |