Class: SpreeCmCommissioner::VotingSessions::PublishToFirestore
- Inherits:
-
Object
- Object
- SpreeCmCommissioner::VotingSessions::PublishToFirestore
- Includes:
- Spree::ServiceModule::Base, FirestoreConnection
- Defined in:
- app/services/spree_cm_commissioner/voting_sessions/publish_to_firestore.rb
Overview
Publishes a voting session's live state to Cloud Firestore so the show screen updates without a pull-to-refresh.
Firestore layout (already read by cm-market-vendor-app/hang_meas):
episodes/{episode_id}/voting_sessions/{session_id} — session state + vote window
episodes/{episode_id}/voting_sessions/{session_id}/contestants/current — reveal state, one entry per contestant
Nested under the episode (rather than a top-level voting_sessions/id collection) because every mobile call site already has the episode id in hand before it ever needs a voting session's live state — the episode screen loads it directly, and every other screen reaches a session through a ShowModel/VotingSessionModel that only exposes the episode as a nested object, not a bare id — so nesting mirrors how the app actually navigates to this data.
State fields live directly on the session document itself (not a nested meta/current child) so the app can open a single collection listener on episodes/episode_id/voting_sessions — one subscription that streams every session's list-relevant fields (status, visible, can_vote, position, name) AND, for whichever session is selected, its full detail (vote_open_at, vote_close_at, paused, vote_duration_seconds), with no separate per-session document-listener and no separate index document to keep in sync.
Field names match VotingSessionMetaModel.fromJson in packages/core/lib/core/models/spree/voting_session_meta_model.dart, kept in lockstep with this file — both sides changed together (vote_open_at/vote_close_at/paused replacing the original started_at/closes_at/paused_reason) specifically to stop colliding with VotingSessionSerializer/VotingSessionModel's own opens_at/closes_at, which mean the show's time slot, not the vote window. That parser ignores unknown keys, so the extra fields below (server_time, vote_duration_seconds, status, position, name) are safe to publish ahead of any Flutter change.
Note: this does NOT write the results/current doc — the live leaderboard the app also reads still has no Rails writer.
Instance Method Summary collapse
Methods included from FirestoreConnection
#firestore, #firestore_available?, #service_account
Instance Method Details
#call(voting_session:) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'app/services/spree_cm_commissioner/voting_sessions/publish_to_firestore.rb', line 38 def call(voting_session:) return success(:skipped) unless firestore_available? session_document(voting_session).set((voting_session), merge: true) session_document(voting_session).col('contestants').doc('current').set(contestants_payload(voting_session), merge: true) success(voting_session) rescue StandardError => e # A Firestore outage must not take the dashboard down with it: the session's own columns # are already committed and the REST API still serves the correct state, so the app # degrades to its pre-existing pull-to-refresh behaviour rather than breaking. Rails.logger.error("[VotingSessions::PublishToFirestore] session=#{voting_session.id} #{e.class}: #{e.}") failure(nil, e.) end |