Class: CrmNavbarLiveUsers
- Inherits:
-
Object
- Object
- CrmNavbarLiveUsers
- Defined in:
- app/services/crm_navbar_live_users.rb
Overview
Tracks which CRM users currently have the navbar mounted (i.e. are sitting
on a CRM page right now).
The navbar's Stimulus controller heartbeats this endpoint roughly every
2 minutes; entries auto-expire after TTL_SECONDS so a user who closes
the tab or sleeps the laptop drops out without explicit cleanup.
TTL is generous (5 min) relative to the 2-min heartbeat so a single
missed beat (transient network blip, brief tab freeze) doesn't drop the
user from the live set and miss broadcasts.
Stored as a single Redis sorted-set whose score is a unix timestamp.
Reads transparently garbage-collect entries older than the TTL.
This registry exists so that broadcasters can short-circuit before doing
any rendering work — there's no point computing a per-user badge for
someone who isn't on a CRM page. CrmNavbarPeriodicRefreshWorker also
reads this list to fan out the 5-min backstop refreshes.
Constant Summary collapse
- KEY =
Key.
'crm_navbar:live_users'- TTL_SECONDS =
Ttl seconds.
300
Class Method Summary collapse
-
.list ⇒ Array<Integer>
Returns the array of user IDs currently considered live.
-
.live?(user_id) ⇒ Boolean
Checks whether a user is still considered live.
-
.reset! ⇒ void
Clears the live-users registry.
-
.touch(user_id) ⇒ Boolean
Marks a user as currently viewing the CRM.
Class Method Details
.list ⇒ Array<Integer>
Returns the array of user IDs currently considered live.
Also garbage-collects expired entries as a side effect.
57 58 59 60 61 62 63 |
# File 'app/services/crm_navbar_live_users.rb', line 57 def list cutoff = (Time.current - TTL_SECONDS).to_f with_redis do |r| r.zremrangebyscore(KEY, '-inf', "(#{cutoff}") r.zrange(KEY, 0, -1).map(&:to_i) end end |
.live?(user_id) ⇒ Boolean
Checks whether a user is still considered live.
69 70 71 72 73 |
# File 'app/services/crm_navbar_live_users.rb', line 69 def live?(user_id) cutoff = (Time.current - TTL_SECONDS).to_f score = with_redis { |r| r.zscore(KEY, user_id.to_s) } score.present? && score >= cutoff end |
.reset! ⇒ void
This method returns an undefined value.
Clears the live-users registry.
Used by tests to start from a known empty set.
80 81 82 |
# File 'app/services/crm_navbar_live_users.rb', line 80 def reset! with_redis { |r| r.del(KEY) } end |
.touch(user_id) ⇒ Boolean
Marks a user as currently viewing the CRM.
Idempotent — repeated calls just bump the user's timestamp.
40 41 42 43 44 45 46 47 48 49 50 |
# File 'app/services/crm_navbar_live_users.rb', line 40 def touch(user_id) now = Time.current.to_f with_redis do |r| r.zadd(KEY, now, user_id.to_s) # Bound the size of the sorted set; stale entries are garbage collected # on every list/live? read but adding a TTL guards against a long-idle # Redis still holding ancient entries. r.expire(KEY, 1.day.to_i) end true end |