Class: WhereIsWaldo::Configuration
- Inherits:
-
Object
- Object
- WhereIsWaldo::Configuration
- Defined in:
- lib/where_is_waldo/configuration.rb
Instance Attribute Summary collapse
-
#adapter ⇒ Object
Storage settings :adapter - :database or :redis :table_name - defaults to 'presences' :redis_client - custom Redis instance (optional) :redis_prefix - key prefix for Redis (for multi-app setups).
-
#authenticate_proc ⇒ Object
ActionCable settings :channel_name - defaults to 'WhereIsWaldo::PresenceChannel' :authenticate_proc - proc to authenticate connection, receives request.
-
#broadcast_audience ⇒ Object
Default audience resolver for the Broadcastable concern.
-
#channel_name ⇒ Object
ActionCable settings :channel_name - defaults to 'WhereIsWaldo::PresenceChannel' :authenticate_proc - proc to authenticate connection, receives request.
-
#heartbeat_interval ⇒ Object
Timing :timeout - seconds until considered offline (default: 90) :heartbeat_interval - expected heartbeat frequency (default: 30).
-
#redis_client ⇒ Object
Storage settings :adapter - :database or :redis :table_name - defaults to 'presences' :redis_client - custom Redis instance (optional) :redis_prefix - key prefix for Redis (for multi-app setups).
-
#redis_prefix ⇒ Object
Storage settings :adapter - :database or :redis :table_name - defaults to 'presences' :redis_client - custom Redis instance (optional) :redis_prefix - key prefix for Redis (for multi-app setups).
-
#roster_cache_ttl ⇒ Object
Tuning (pull/nudge).
-
#roster_members ⇒ Object
Live presence roster ("who's around in my org/account") ===.
-
#roster_members_association ⇒ Object
Live presence roster ("who's around in my org/account") ===.
-
#roster_mode ⇒ Object
roster_mode: delivery strategy, per account.
-
#roster_nudge_jitter ⇒ Object
Tuning (pull/nudge).
-
#roster_org ⇒ Object
Live presence roster ("who's around in my org/account") ===.
-
#roster_poll_interval ⇒ Object
Tuning (pull/nudge).
-
#roster_viewers_of ⇒ Object
roster_visible_to: given a VIEWER, return the AR scope of subjects that viewer may see (for :poll/:nudge snapshots + diffs).
-
#roster_visible_to ⇒ Object
roster_visible_to: given a VIEWER, return the AR scope of subjects that viewer may see (for :poll/:nudge snapshots + diffs).
-
#session_column ⇒ Object
Column names - fully configurable :session_column - unique identifier per connection/tab (e.g., :session_id, :jti) :subject_column - who is present (e.g., :user_id, :member_id, :student_id).
-
#subject_class ⇒ Object
Subject model (e.g., 'User', 'Member', 'Student') Required for scope-based broadcasting and queries.
-
#subject_column ⇒ Object
Column names - fully configurable :session_column - unique identifier per connection/tab (e.g., :session_id, :jti) :subject_column - who is present (e.g., :user_id, :member_id, :student_id).
-
#subject_data_proc ⇒ Object
Optional: proc that returns hash of subject info for presence data Called with the subject record to build presence hash.
-
#suppress_presence_proc ⇒ Object
:suppress_presence_proc - callable that decides, per connection, whether to SKIP presence registration for that subscriber.
-
#table_name ⇒ Object
Storage settings :adapter - :database or :redis :table_name - defaults to 'presences' :redis_client - custom Redis instance (optional) :redis_prefix - key prefix for Redis (for multi-app setups).
-
#timeout ⇒ Object
Timing :timeout - seconds until considered offline (default: 90) :heartbeat_interval - expected heartbeat frequency (default: 30).
Instance Method Summary collapse
-
#build_subject_data(subject) ⇒ Object
Build subject data hash from a subject record.
-
#initialize ⇒ Configuration
constructor
A new instance of Configuration.
-
#members_association ⇒ Object
Association name used to derive the default roster from an org when roster_members is not configured (e.g. subject_class "User" => :users).
-
#resolve_members(org) ⇒ Object
Resolve the AR scope of member subjects for an org (nil if not resolvable).
-
#resolve_mode(account) ⇒ Object
Resolve the delivery mode for an account.
-
#resolve_roster_org(subject) ⇒ Object
Resolve the org/container record for a subject (nil if unset/absent).
-
#resolve_viewers_of(subject) ⇒ Object
Resolve the AR scope of viewers allowed to see a SUBJECT (:fanout only).
-
#resolve_visible_to(viewer) ⇒ Object
Resolve the AR scope of subjects a VIEWER may see.
-
#roster_enabled? ⇒ Boolean
True when the live-presence roster feature is configured.
-
#subject_class_constant ⇒ Object
Helper to get subject class constant.
-
#timeout_duration ⇒ Object
Helper to get timeout as duration.
Constructor Details
#initialize ⇒ Configuration
Returns a new instance of Configuration.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/where_is_waldo/configuration.rb', line 104 def initialize # Storage defaults @adapter = :database @table_name = "presences" @redis_client = nil @redis_prefix = "where_is_waldo" # Column defaults @session_column = :session_id @subject_column = :subject_id # Subject model (required) @subject_class = nil @subject_data_proc = nil # Timing defaults @timeout = 90 @heartbeat_interval = 30 # ActionCable defaults @channel_name = "WhereIsWaldo::PresenceChannel" @authenticate_proc = nil @suppress_presence_proc = nil # Broadcastable default audience (set per app) @broadcast_audience = nil # Presence roster (set per app to enable) @roster_org = nil @roster_members = nil @roster_members_association = nil @roster_visible_to = nil @roster_viewers_of = nil @roster_mode = :poll @roster_poll_interval = 15 @roster_cache_ttl = 90 @roster_nudge_jitter = 0.5 end |
Instance Attribute Details
#adapter ⇒ Object
Storage settings :adapter - :database or :redis :table_name - defaults to 'presences' :redis_client - custom Redis instance (optional) :redis_prefix - key prefix for Redis (for multi-app setups)
10 11 12 |
# File 'lib/where_is_waldo/configuration.rb', line 10 def adapter @adapter end |
#authenticate_proc ⇒ Object
ActionCable settings :channel_name - defaults to 'WhereIsWaldo::PresenceChannel' :authenticate_proc - proc to authenticate connection, receives request
33 34 35 |
# File 'lib/where_is_waldo/configuration.rb', line 33 def authenticate_proc @authenticate_proc end |
#broadcast_audience ⇒ Object
Default audience resolver for the Broadcastable concern. A lambda that, given a record, returns the AR scope to broadcast to (e.g. that record's account members). Set once per app to match its container, e.g.:
config.broadcast_audience = ->(rec) { rec.account.users }
Models may override per-model via broadcasts_realtime(scope: ...).
57 58 59 |
# File 'lib/where_is_waldo/configuration.rb', line 57 def broadcast_audience @broadcast_audience end |
#channel_name ⇒ Object
ActionCable settings :channel_name - defaults to 'WhereIsWaldo::PresenceChannel' :authenticate_proc - proc to authenticate connection, receives request
33 34 35 |
# File 'lib/where_is_waldo/configuration.rb', line 33 def channel_name @channel_name end |
#heartbeat_interval ⇒ Object
Timing :timeout - seconds until considered offline (default: 90) :heartbeat_interval - expected heartbeat frequency (default: 30)
28 29 30 |
# File 'lib/where_is_waldo/configuration.rb', line 28 def heartbeat_interval @heartbeat_interval end |
#redis_client ⇒ Object
Storage settings :adapter - :database or :redis :table_name - defaults to 'presences' :redis_client - custom Redis instance (optional) :redis_prefix - key prefix for Redis (for multi-app setups)
10 11 12 |
# File 'lib/where_is_waldo/configuration.rb', line 10 def redis_client @redis_client end |
#redis_prefix ⇒ Object
Storage settings :adapter - :database or :redis :table_name - defaults to 'presences' :redis_client - custom Redis instance (optional) :redis_prefix - key prefix for Redis (for multi-app setups)
10 11 12 |
# File 'lib/where_is_waldo/configuration.rb', line 10 def redis_prefix @redis_prefix end |
#roster_cache_ttl ⇒ Object
Tuning (pull/nudge). roster_nudge_jitter (seconds) spreads clients' re-poll after a nudge so a change doesn't stampede every viewer at once.
102 103 104 |
# File 'lib/where_is_waldo/configuration.rb', line 102 def roster_cache_ttl @roster_cache_ttl end |
#roster_members ⇒ Object
Live presence roster ("who's around in my org/account") ===
roster_org: given a subject, return the org/container record that defines the roster boundary. Its class + id key the single shared roster ActionCable stream, so every member of the same org subscribes to ONE stream and a presence change is a single O(1) broadcast (not per-member fan-out). Required to enable the roster feature — nil leaves it inert. config.roster_org = ->(subject) { subject.account }
roster_members: given that org, return the AR scope of member subjects
shown in the roster. Optional — defaults to org.public_send(
roster_members_association: association used to build the default roster from the org when roster_members is unset (defaults to the pluralized subject_class, e.g. :users).
77 78 79 |
# File 'lib/where_is_waldo/configuration.rb', line 77 def roster_members @roster_members end |
#roster_members_association ⇒ Object
Live presence roster ("who's around in my org/account") ===
roster_org: given a subject, return the org/container record that defines the roster boundary. Its class + id key the single shared roster ActionCable stream, so every member of the same org subscribes to ONE stream and a presence change is a single O(1) broadcast (not per-member fan-out). Required to enable the roster feature — nil leaves it inert. config.roster_org = ->(subject) { subject.account }
roster_members: given that org, return the AR scope of member subjects
shown in the roster. Optional — defaults to org.public_send(
roster_members_association: association used to build the default roster from the org when roster_members is unset (defaults to the pluralized subject_class, e.g. :users).
77 78 79 |
# File 'lib/where_is_waldo/configuration.rb', line 77 def roster_members_association @roster_members_association end |
#roster_mode ⇒ Object
roster_mode: delivery strategy, per account. A symbol, or a callable resolving an account -> mode. MUST be a function of the account (uniform for all its members). Default :poll (safe: server-side filtered). :poll - heartbeat/poll, server-filtered, ~interval latency :broadcast - instant shared-stream push, NO filtering (open account) :nudge - :poll + content-free trigger (Phase 2) :fanout - per-viewer push (Phase 3) config.roster_mode = ->(account) { account.everyone_admin? ? :broadcast : :poll }
98 99 100 |
# File 'lib/where_is_waldo/configuration.rb', line 98 def roster_mode @roster_mode end |
#roster_nudge_jitter ⇒ Object
Tuning (pull/nudge). roster_nudge_jitter (seconds) spreads clients' re-poll after a nudge so a change doesn't stampede every viewer at once.
102 103 104 |
# File 'lib/where_is_waldo/configuration.rb', line 102 def roster_nudge_jitter @roster_nudge_jitter end |
#roster_org ⇒ Object
Live presence roster ("who's around in my org/account") ===
roster_org: given a subject, return the org/container record that defines the roster boundary. Its class + id key the single shared roster ActionCable stream, so every member of the same org subscribes to ONE stream and a presence change is a single O(1) broadcast (not per-member fan-out). Required to enable the roster feature — nil leaves it inert. config.roster_org = ->(subject) { subject.account }
roster_members: given that org, return the AR scope of member subjects
shown in the roster. Optional — defaults to org.public_send(
roster_members_association: association used to build the default roster from the org when roster_members is unset (defaults to the pluralized subject_class, e.g. :users).
77 78 79 |
# File 'lib/where_is_waldo/configuration.rb', line 77 def roster_org @roster_org end |
#roster_poll_interval ⇒ Object
Tuning (pull/nudge). roster_nudge_jitter (seconds) spreads clients' re-poll after a nudge so a change doesn't stampede every viewer at once.
102 103 104 |
# File 'lib/where_is_waldo/configuration.rb', line 102 def roster_poll_interval @roster_poll_interval end |
#roster_viewers_of ⇒ Object
roster_visible_to: given a VIEWER, return the AR scope of subjects that viewer may see (for :poll/:nudge snapshots + diffs). Handles any visibility rule server-side. Defaults to the viewer's whole org roster (everyone-sees-everyone) when unset. config.roster_visible_to = ->(viewer) { viewer.visible_users }
roster_viewers_of: given a SUBJECT, return the AR scope of viewers allowed to see it (ONLY used by :fanout, Phase 3). Must be the exact inverse of roster_visible_to.
88 89 90 |
# File 'lib/where_is_waldo/configuration.rb', line 88 def roster_viewers_of @roster_viewers_of end |
#roster_visible_to ⇒ Object
roster_visible_to: given a VIEWER, return the AR scope of subjects that viewer may see (for :poll/:nudge snapshots + diffs). Handles any visibility rule server-side. Defaults to the viewer's whole org roster (everyone-sees-everyone) when unset. config.roster_visible_to = ->(viewer) { viewer.visible_users }
roster_viewers_of: given a SUBJECT, return the AR scope of viewers allowed to see it (ONLY used by :fanout, Phase 3). Must be the exact inverse of roster_visible_to.
88 89 90 |
# File 'lib/where_is_waldo/configuration.rb', line 88 def roster_visible_to @roster_visible_to end |
#session_column ⇒ Object
Column names - fully configurable :session_column - unique identifier per connection/tab (e.g., :session_id, :jti) :subject_column - who is present (e.g., :user_id, :member_id, :student_id)
15 16 17 |
# File 'lib/where_is_waldo/configuration.rb', line 15 def session_column @session_column end |
#subject_class ⇒ Object
Subject model (e.g., 'User', 'Member', 'Student') Required for scope-based broadcasting and queries
19 20 21 |
# File 'lib/where_is_waldo/configuration.rb', line 19 def subject_class @subject_class end |
#subject_column ⇒ Object
Column names - fully configurable :session_column - unique identifier per connection/tab (e.g., :session_id, :jti) :subject_column - who is present (e.g., :user_id, :member_id, :student_id)
15 16 17 |
# File 'lib/where_is_waldo/configuration.rb', line 15 def subject_column @subject_column end |
#subject_data_proc ⇒ Object
Optional: proc that returns hash of subject info for presence data Called with the subject record to build presence hash
23 24 25 |
# File 'lib/where_is_waldo/configuration.rb', line 23 def subject_data_proc @subject_data_proc end |
#suppress_presence_proc ⇒ Object
:suppress_presence_proc - callable that decides, per connection, whether
to SKIP presence registration for that subscriber. Receives the
ActionCable connection (host apps can read session/cookies/env off it,
e.g. via connection.request). Returns truthy to suppress.
A suppressed subscriber still subscribes normally — they receive
broadcasts to where_is_waldo:subject:<id> (WhereIsWaldo.broadcast_to*
signaling) and any other Waldo capability — they just don't register a
Presence row / heartbeat / roster transition. Use for cases where the
WebSocket session is legitimate but shouldn't be counted as "the subject
is present", e.g. support-user impersonation tabs.
config.suppress_presence_proc = ->(connection) {
connection.request.session[:su_user].present?
}
50 51 52 |
# File 'lib/where_is_waldo/configuration.rb', line 50 def suppress_presence_proc @suppress_presence_proc end |
#table_name ⇒ Object
Storage settings :adapter - :database or :redis :table_name - defaults to 'presences' :redis_client - custom Redis instance (optional) :redis_prefix - key prefix for Redis (for multi-app setups)
10 11 12 |
# File 'lib/where_is_waldo/configuration.rb', line 10 def table_name @table_name end |
#timeout ⇒ Object
Timing :timeout - seconds until considered offline (default: 90) :heartbeat_interval - expected heartbeat frequency (default: 30)
28 29 30 |
# File 'lib/where_is_waldo/configuration.rb', line 28 def timeout @timeout end |
Instance Method Details
#build_subject_data(subject) ⇒ Object
Build subject data hash from a subject record
215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/where_is_waldo/configuration.rb', line 215 def build_subject_data(subject) return {} unless subject if subject_data_proc subject_data_proc.call(subject) elsif subject.respond_to?(:id) { id: subject.id } else {} end end |
#members_association ⇒ Object
Association name used to derive the default roster from an org when roster_members is not configured (e.g. subject_class "User" => :users).
164 165 166 167 168 169 |
# File 'lib/where_is_waldo/configuration.rb', line 164 def members_association return roster_members_association if roster_members_association return nil if subject_class.blank? subject_class.to_s.demodulize.underscore.pluralize.to_sym end |
#resolve_members(org) ⇒ Object
Resolve the AR scope of member subjects for an org (nil if not resolvable).
172 173 174 175 176 177 178 179 180 |
# File 'lib/where_is_waldo/configuration.rb', line 172 def resolve_members(org) return nil unless org if roster_members roster_members.call(org) elsif (assoc = members_association) && org.respond_to?(assoc) org.public_send(assoc) end end |
#resolve_mode(account) ⇒ Object
Resolve the delivery mode for an account. Callable roster_mode is invoked with the account; a bare symbol is returned as-is. Defaults to :poll.
208 209 210 211 212 |
# File 'lib/where_is_waldo/configuration.rb', line 208 def resolve_mode(account) mode = roster_mode mode = mode.call(account) if mode.respond_to?(:call) (mode || :poll).to_sym end |
#resolve_roster_org(subject) ⇒ Object
Resolve the org/container record for a subject (nil if unset/absent).
156 157 158 159 160 |
# File 'lib/where_is_waldo/configuration.rb', line 156 def resolve_roster_org(subject) return nil unless roster_org && subject roster_org.call(subject) end |
#resolve_viewers_of(subject) ⇒ Object
Resolve the AR scope of viewers allowed to see a SUBJECT (:fanout only).
200 201 202 203 204 |
# File 'lib/where_is_waldo/configuration.rb', line 200 def resolve_viewers_of(subject) return nil unless roster_viewers_of && subject roster_viewers_of.call(subject) end |
#resolve_visible_to(viewer) ⇒ Object
Resolve the AR scope of subjects a VIEWER may see. Defaults to the viewer's whole org roster (everyone-sees-everyone) when unset.
189 190 191 192 193 194 195 196 197 |
# File 'lib/where_is_waldo/configuration.rb', line 189 def resolve_visible_to(viewer) return nil unless viewer if roster_visible_to roster_visible_to.call(viewer) else resolve_members(resolve_roster_org(viewer)) end end |
#roster_enabled? ⇒ Boolean
True when the live-presence roster feature is configured.
183 184 185 |
# File 'lib/where_is_waldo/configuration.rb', line 183 def roster_enabled? !roster_org.nil? end |
#subject_class_constant ⇒ Object
Helper to get subject class constant
149 150 151 152 153 |
# File 'lib/where_is_waldo/configuration.rb', line 149 def subject_class_constant return nil if subject_class.blank? subject_class.is_a?(String) ? subject_class.safe_constantize : subject_class end |
#timeout_duration ⇒ Object
Helper to get timeout as duration
144 145 146 |
# File 'lib/where_is_waldo/configuration.rb', line 144 def timeout_duration timeout.is_a?(ActiveSupport::Duration) ? timeout : timeout.seconds end |