Class: CrmNavbarRefreshWorker
- Inherits:
-
Object
- Object
- CrmNavbarRefreshWorker
- Includes:
- Sidekiq::Job
- Defined in:
- app/workers/crm_navbar_refresh_worker.rb
Overview
Renders and broadcasts one navbar fragment for one user.
Coalescing: a burst of N events all asking us to refresh the same
(user, badge) collapses into one job. The first call writes a "pending"
Redis key with a 2s TTL and schedules the job to run +2s later; subsequent
calls within that window see the key and short-circuit. The job clears the
key when it runs, so the next event after the window opens a fresh window.
This means at most one broadcast per (user, badge) per 2 seconds — bounded
load even during a flood of inbound SMS / voicemails / emails.
Constant Summary collapse
- COALESCE_WINDOW =
Coalesce window.
2.seconds
- PENDING_KEY =
Key used for pending.
'crm_navbar_pending'
Class Method Summary collapse
- .pending_key(user_id, badge) ⇒ Object
-
.schedule(user_id:, badge:) ⇒ Object
Public entry point.
Instance Method Summary collapse
-
#perform(user_id, badge) ⇒ void
Performs a scheduled navbar refresh for the given user and badge.
Class Method Details
.pending_key(user_id, badge) ⇒ Object
42 43 44 |
# File 'app/workers/crm_navbar_refresh_worker.rb', line 42 def pending_key(user_id, badge) "#{PENDING_KEY}:#{user_id}:#{badge}" end |
.schedule(user_id:, badge:) ⇒ Object
Public entry point. Returns true if a refresh was scheduled, false if
an existing pending refresh will already cover this event.
30 31 32 33 34 35 36 37 38 39 40 |
# File 'app/workers/crm_navbar_refresh_worker.rb', line 30 def schedule(user_id:, badge:) key = pending_key(user_id, badge) acquired = Sidekiq.redis do |r| # SET key 1 NX EX 2 — atomic "set if absent with TTL". r.set(key, '1', nx: true, ex: COALESCE_WINDOW.to_i) end return false unless acquired perform_in(COALESCE_WINDOW, user_id, badge.to_s) true end |
Instance Method Details
#perform(user_id, badge) ⇒ void
This method returns an undefined value.
Performs a scheduled navbar refresh for the given user and badge.
Deletes the pending Redis marker for the (user, badge), clears the user's cached CRM navbar totals so fresh counts are used, and triggers the broadcaster to refresh the specified badge fragment.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/workers/crm_navbar_refresh_worker.rb', line 53 def perform(user_id, badge) Sidekiq.redis { |r| r.del(self.class.pending_key(user_id, badge)) } user = Employee.find_by(id: user_id) return unless user return unless CrmNavbarBroadcaster::BADGES.key?(badge.to_sym) # Drop the cached totals so the broadcaster's partial render computes # the latest counts. Without this, broadcasts would re-render whatever # was cached when the underlying record changed and bypass the live # update we're trying to push. CrmNavbarCounts.bust_cache(user) CrmNavbarBroadcaster.refresh(user, badge: badge.to_sym) end |