# frozen_string_literal: true # HubLoad - Calculates dynamic event sampling rate based on system load # # This service monitors SolidQueue depth and adjusts sampling rates to prevent # the Hub from being overwhelmed while ensuring critical events are always captured. class HubLoad # Queue depth thresholds THRESHOLDS = { normal: 0..1_000, # 100% sampling moderate: 1_001..5_000, # 50% sampling high: 5_001..10_000, # 20% sampling critical: 10_001..Float::INFINITY # 5% sampling }.freeze SAMPLING_RATES = { normal: { allowed: 1.0, blocked: 1.0, rate_limited: 1.0 }, moderate: { allowed: 0.5, blocked: 1.0, rate_limited: 1.0 }, high: { allowed: 0.2, blocked: 1.0, rate_limited: 1.0 }, critical: { allowed: 0.05, blocked: 1.0, rate_limited: 1.0 } }.freeze # Get current sampling configuration based on load def self.current_sampling load_level = calculate_load_level rates = SAMPLING_RATES[load_level] { allowed_requests: rates[:allowed], blocked_requests: rates[:blocked], rate_limited_requests: rates[:rate_limited], effective_until: next_sync_time, load_level: load_level, queue_depth: queue_depth } end # Calculate when sampling should be rechecked (next agent sync) def self.next_sync_time 10.seconds.from_now.iso8601(3) end # Get current queue depth def self.queue_depth # SolidQueue stores jobs in the jobs table # Count pending/running jobs only SolidQueue::Job.where(finished_at: nil).count rescue StandardError => e Rails.logger.error "Failed to get queue depth: #{e.message}" 0 end # Determine load level based on queue depth def self.calculate_load_level depth = queue_depth THRESHOLDS.each do |level, range| return level if range.cover?(depth) end :critical # Fallback end # Check if hub is under heavy load def self.overloaded? calculate_load_level.in?([:high, :critical]) end # Get load statistics for monitoring def self.stats { queue_depth: queue_depth, load_level: calculate_load_level, sampling_rates: SAMPLING_RATES[calculate_load_level], overloaded: overloaded? } end end