Class: CrmNavbarRefreshWorker

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

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.

Parameters:

  • user_id (Integer)

    ID of the Employee to refresh for.

  • badge (String, Symbol)

    The badge key identifying which navbar badge to refresh.



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