Class: SpreeCmCommissioner::VotingSessions::PublishToFirestore

Inherits:
Object
  • Object
show all
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(meta_payload(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.message}")
  failure(nil, e.message)
end