Module: Pgbus::Process::ConsumerPriority
- Defined in:
- lib/pgbus/process/consumer_priority.rb
Overview
Implements consumer priority by checking whether higher-priority workers are active for the same queues. When a higher-priority worker is healthy and not at its prefetch limit, lower-priority workers yield by using a longer polling interval.
Inspired by LavinMQ's consumer priority where higher-priority consumers are served first and lower-priority consumers wait until all higher-priority consumers are at their prefetch limit.
Constant Summary collapse
- CACHE_TTL =
Time-to-live (seconds) for cached max_active_priority lookups. The underlying data only changes on heartbeat cadence, so a short TTL avoids ~10 queries/second per prioritized worker at the default 0.1s polling interval.
5
Class Method Summary collapse
-
.effective_polling_interval(base_interval:, my_priority:, max_priority:) ⇒ Object
Calculate the effective polling interval for this worker.
-
.max_active_priority(queues, my_pid) ⇒ Object
Returns the highest consumer_priority among healthy workers that share at least one queue with the given queue list, excluding the current worker (by PID).
-
.reset_cache! ⇒ Object
Clears all cached max_active_priority entries.
-
.should_yield?(queues:, my_priority:, my_pid:) ⇒ Boolean
Check if this worker should yield to a higher-priority worker.
Class Method Details
.effective_polling_interval(base_interval:, my_priority:, max_priority:) ⇒ Object
Calculate the effective polling interval for this worker. Higher-priority workers use the base interval. Lower-priority workers multiply by a backoff factor.
90 91 92 93 94 95 |
# File 'lib/pgbus/process/consumer_priority.rb', line 90 def self.effective_polling_interval(base_interval:, my_priority:, max_priority:) return base_interval if my_priority >= max_priority # Lower-priority workers back off: 3x the base interval base_interval * 3 end |
.max_active_priority(queues, my_pid) ⇒ Object
Returns the highest consumer_priority among healthy workers that share at least one queue with the given queue list, excluding the current worker (by PID).
Results are cached per (sorted queues, pid) for CACHE_TTL seconds. On a miss the query runs outside the lock (a duplicate query on a race is harmless), then the value is stored under the mutex.
42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/pgbus/process/consumer_priority.rb', line 42 def self.max_active_priority(queues, my_pid) key = [queues.sort, my_pid] now = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) cached = @cache_mutex.synchronize { @cache[key] } return cached[:value] if cached && (now - cached[:at]) < CACHE_TTL value = compute_max_active_priority(queues, my_pid) @cache_mutex.synchronize { @cache[key] = { value: value, at: now } } value end |
.reset_cache! ⇒ Object
Clears all cached max_active_priority entries. Intended for spec isolation; also safe to call at runtime.
56 57 58 |
# File 'lib/pgbus/process/consumer_priority.rb', line 56 def self.reset_cache! @cache_mutex.synchronize { @cache.clear } end |
.should_yield?(queues:, my_priority:, my_pid:) ⇒ Boolean
Check if this worker should yield to a higher-priority worker. Returns true if a higher-priority healthy worker exists for any of the given queues.
26 27 28 29 30 31 32 33 |
# File 'lib/pgbus/process/consumer_priority.rb', line 26 def self.should_yield?(queues:, my_priority:, my_pid:) return false if my_priority >= max_active_priority(queues, my_pid) true rescue StandardError => e Pgbus.logger.debug { "[Pgbus] Consumer priority check failed: #{e.}" } false end |