Class: SpreeCmCommissioner::WaitingRoom::AdvanceQueue
- Inherits:
-
Object
- Object
- SpreeCmCommissioner::WaitingRoom::AdvanceQueue
- Extended by:
- ServiceModuleThrowable
- Includes:
- Spree::ServiceModule::Base, FirestoreConnection
- Defined in:
- app/services/spree_cm_commissioner/waiting_room/advance_queue.rb
Overview
Merges the three independently-scheduled crons (Heartbeat::Sweep, Positions::Stamp, Admission::CallGuests) into one execution, sharing one Firestore client instead of each opening its own.
Ordering is the design, not an implementation detail: Sweep runs first so a stale doc it resolves frees a position before Stamp ever reads it; Stamp runs before CallGuests so every doc CallGuests selects is guaranteed to already have a position (no more call-before-stamp race), and so frontier_position always reflects the last already-landed writes rather than guessing about a cohort this tick's CallGuests hasn't even claimed yet — see Admission::CallGuests's class comment for why that keeps frontier lag bounded to one tick.
Also owns the lobby doc and its logs sub-doc: every step returns its fields (lobby:/logs:
in its result) rather than writing directly. logs: is accumulated and written once, at the
end — telemetry isn't user-facing, so batching it costs nothing. lobby: is instead flushed
incrementally, right after each step that has fields to publish: frontier_position (from
Stamp) lands the moment Stamp finishes, not gated behind CallGuests's own several sequential
Firestore round trips afterward — CallGuests's own capacity fields get a second, small merge
write once it finishes. frontier_position is the one field the app polls to count down "N
people ahead of you" in something close to real time, so it's the one write worth not
batching: one extra Firestore write per tick is cheap next to visibly stalling that counter
for however long CallGuests takes. Sweep never contributes lobby fields, so it never adds a
write. Also resolves the published records_path once (one lobby-doc read) and passes it into
CallGuests, rather than CallGuests reading the lobby doc itself.
Whatever succeeded gets flushed the moment it's known, even when a later step then fails — a CallGuests failure after Stamp already published never withholds frontier_position, since it already landed before CallGuests even ran.
Instance Method Summary collapse
Methods included from ServiceModuleThrowable
Methods included from FirestoreConnection
#firestore, #firestore_available?, #service_account
Instance Method Details
#call ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/services/spree_cm_commissioner/waiting_room/advance_queue.rb', line 35 def call started_at = Time.zone.now logs_fields = {} sweep_result = SpreeCmCommissioner::WaitingRoom::Heartbeat::Sweep.call(firestore: firestore) return publish_and_fail(logs_fields, started_at, sweep_result) if sweep_result.failure? publish_lobby(sweep_result.value[:lobby]) logs_fields.merge!({ sweep: sweep_result.value[:logs] }) stamp_result = SpreeCmCommissioner::WaitingRoom::Positions::Stamp.call(firestore: firestore) return publish_and_fail(logs_fields, started_at, stamp_result) if stamp_result.failure? publish_lobby(stamp_result.value[:lobby]) logs_fields.merge!({ stamp: stamp_result.value[:logs] }) call_result = SpreeCmCommissioner::WaitingRoom::Admission::CallGuests.call( firestore: firestore, records_path: records_path ) return publish_and_fail(logs_fields, started_at, call_result) if call_result.failure? publish_lobby(call_result.value[:lobby]) publish_logs(started_at, logs_fields.merge!({ call_guests: call_result.value[:logs] })) success( swept: sweep_result.value[:swept], stamped: stamp_result.value[:stamped], called_count: call_result.value[:called_count] ) end |