Class: QueryGuard::Budget
- Inherits:
-
Object
- Object
- QueryGuard::Budget
- Defined in:
- lib/query_guard/budget.rb
Overview
Budget system for enforcing query SLOs on controllers and jobs. Supports modes: :log (warn only), :notify (callback), :raise (exception).
Defined Under Namespace
Classes: Violation
Instance Attribute Summary collapse
-
#mode ⇒ Object
Returns the value of attribute mode.
-
#on_violation ⇒ Object
Returns the value of attribute on_violation.
-
#rules ⇒ Object
readonly
Returns the value of attribute rules.
Instance Method Summary collapse
-
#budget_for(key) ⇒ Object
Check if a budget exists for the given key.
-
#check(key, stats) ⇒ Object
Check stats against budget and return violations.
-
#enforce!(key, violations) ⇒ Object
Enforce budget violations according to current mode.
-
#for(key, **limits) ⇒ Object
DSL: Define a budget for a specific controller action.
-
#for_job(job_class_or_name, **limits) ⇒ Object
DSL: Define a budget for a background job.
-
#initialize ⇒ Budget
constructor
A new instance of Budget.
Constructor Details
#initialize ⇒ Budget
Returns a new instance of Budget.
11 12 13 14 15 |
# File 'lib/query_guard/budget.rb', line 11 def initialize @rules = {} @mode = :log @on_violation = nil end |
Instance Attribute Details
#mode ⇒ Object
Returns the value of attribute mode.
9 10 11 |
# File 'lib/query_guard/budget.rb', line 9 def mode @mode end |
#on_violation ⇒ Object
Returns the value of attribute on_violation.
9 10 11 |
# File 'lib/query_guard/budget.rb', line 9 def on_violation @on_violation end |
#rules ⇒ Object (readonly)
Returns the value of attribute rules.
9 10 11 |
# File 'lib/query_guard/budget.rb', line 9 def rules @rules end |
Instance Method Details
#budget_for(key) ⇒ Object
Check if a budget exists for the given key
60 61 62 63 |
# File 'lib/query_guard/budget.rb', line 60 def budget_for(key) normalized = normalize_key(key) @rules[normalized] end |
#check(key, stats) ⇒ Object
Check stats against budget and return violations
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/query_guard/budget.rb', line 66 def check(key, stats) budget = budget_for(key) return [] unless budget violations = [] if budget[:count] && stats[:count] > budget[:count] violations << { type: :budget_exceeded_count, key: key, actual: stats[:count], limit: budget[:count] } end if budget[:duration_ms] && stats[:total_duration_ms] > budget[:duration_ms] violations << { type: :budget_exceeded_duration, key: key, actual: stats[:total_duration_ms], limit: budget[:duration_ms] } end violations end |
#enforce!(key, violations) ⇒ Object
Enforce budget violations according to current mode
94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/query_guard/budget.rb', line 94 def enforce!(key, violations) return if violations.empty? case @mode when :log log_violations(key, violations) when :notify notify_violations(key, violations) when :raise raise_violations(key, violations) end end |
#for(key, **limits) ⇒ Object
DSL: Define a budget for a specific controller action. Examples:
budget.for("users#index", count: 10, duration_ms: 500)
budget.for("posts#show", count: 5)
21 22 23 24 25 26 |
# File 'lib/query_guard/budget.rb', line 21 def for(key, **limits) normalized = normalize_key(key) @rules[normalized] ||= {} @rules[normalized].merge!(limits) self end |
#for_job(job_class_or_name, **limits) ⇒ Object
DSL: Define a budget for a background job. Examples:
budget.for_job("EmailJob", count: 50, duration_ms: 2000)
budget.for_job(EmailJob, count: 50)
32 33 34 35 36 37 38 |
# File 'lib/query_guard/budget.rb', line 32 def for_job(job_class_or_name, **limits) key = job_class_or_name.is_a?(String) ? job_class_or_name : job_class_or_name.to_s normalized = normalize_key("job:#{key}") @rules[normalized] ||= {} @rules[normalized].merge!(limits) self end |