Class: Delayed::Priority
- Inherits:
-
Numeric
- Object
- Numeric
- Delayed::Priority
- Defined in:
- lib/delayed/priority.rb
Constant Summary collapse
- DEFAULT_NAMES =
A Delayed::Priority represents a value that exists within a named range. Here are the default ranges and their names:
0-9: interactive
10-19: user_visible 20-29: eventual
30+: reporting
Ranges can be customized. They must be positive and must include a name for priority >= 0. The following config will produce ranges 0-99 (high), 100-499 (medium) and 500+ (low):
> Delayed::Priority.names = { high: 0, medium: 100, low: 500 }
{ interactive: 0, # These jobs will actively hinder end-user interactions until they are complete, e.g. work behind a loading spinner user_visible: 10, # These jobs have end-user-visible side effects that will not obviously impact customers, e.g. welcome emails eventual: 20, # These jobs affect business process that are tolerant to some degree of queue backlog, e.g. syncing with other services reporting: 30, # These jobs are for processes that can complete on a slower timeline, e.g. daily report generation }.freeze
- DEFAULT_ALERTS =
Priorities can be mapped to alerting thresholds for job age (time since run_at), runtime, and attempts. These thresholds can be used to emit events or metrics. Here are the default values (for the default priorities):
Age Alerts ==========
interactive: 1 minute user_visible: 3 minutes eventual: 1.5 hours reporting: 4 hours
Run Time Alerts ======
interactive: 30 seconds user_visible: 90 seconds eventual: 5 minutes reporting: 10 minutes
Attempts Alerts =====
interactive: 3 attempts user_visible: 5 attempts eventual: 8 attempts reporting: 8 attempts
Alerting thresholds can be customized. The keys must match ‘Delayed::Priority.names`.
Delayed::Priority.alerts = {
high: { age: 30.seconds, run_time: 15.seconds, attempts: 3 }, medium: { age: 2.minutes, run_time: 1.minute, attempts: 6 }, low: { age: 10.minutes, run_time: 2.minutes, attempts: 9 },
}
{ interactive: { age: 1.minute, run_time: 30.seconds, attempts: 3 }, user_visible: { age: 3.minutes, run_time: 90.seconds, attempts: 5 }, eventual: { age: 1.5.hours, run_time: 5.minutes, attempts: 8 }, reporting: { age: 4.hours, run_time: 10.minutes, attempts: 8 }, }.freeze
Class Attribute Summary collapse
-
.assign_at_midpoint ⇒ Object
writeonly
Sets the attribute assign_at_midpoint.
Instance Attribute Summary collapse
-
#value ⇒ Object
readonly
Returns the value of attribute value.
Class Method Summary collapse
- .alerts ⇒ Object
- .alerts=(alerts) ⇒ Object
- .assign_at_midpoint? ⇒ Boolean
- .names ⇒ Object
- .names=(names) ⇒ Object
- .names_to_priority ⇒ Object
- .ranges ⇒ Object
Instance Method Summary collapse
- #+(other) ⇒ Object
- #-(other) ⇒ Object
- #<=>(other) ⇒ Object
- #alert_age ⇒ Object
- #alert_attempts ⇒ Object
- #alert_run_time ⇒ Object
- #coerce(other) ⇒ Object
-
#initialize(value) ⇒ Priority
constructor
A new instance of Priority.
- #name ⇒ Object
- #to_d ⇒ Object
Constructor Details
#initialize(value) ⇒ Priority
Returns a new instance of Priority.
145 146 147 148 149 |
# File 'lib/delayed/priority.rb', line 145 def initialize(value) super() value = self.class.names_to_priority[value] if value.is_a?(Symbol) @value = value.to_i end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args) ⇒ Object (private)
196 197 198 199 200 201 202 |
# File 'lib/delayed/priority.rb', line 196 def method_missing(method_name, *args) if method_name.to_s.end_with?('?') && self.class.names.key?(method_name.to_s[0..-2].to_sym) method_name.to_s[0..-2] == to_s else super end end |
Class Attribute Details
.assign_at_midpoint=(value) ⇒ Object (writeonly)
Sets the attribute assign_at_midpoint
60 61 62 |
# File 'lib/delayed/priority.rb', line 60 def assign_at_midpoint=(value) @assign_at_midpoint = value end |
Instance Attribute Details
#value ⇒ Object (readonly)
Returns the value of attribute value.
140 141 142 |
# File 'lib/delayed/priority.rb', line 140 def value @value end |
Class Method Details
.alerts ⇒ Object
66 67 68 |
# File 'lib/delayed/priority.rb', line 66 def alerts @alerts || default_alerts end |
.alerts=(alerts) ⇒ Object
79 80 81 82 83 84 85 86 |
# File 'lib/delayed/priority.rb', line 79 def alerts=(alerts) if alerts unknown_names = alerts.keys - names.keys raise "unknown priority name(s): #{unknown_names}" if unknown_names.any? end @alerts = alerts&.sort_by { |k, _| names.keys.index(k) }&.to_h end |
.assign_at_midpoint? ⇒ Boolean
88 89 90 |
# File 'lib/delayed/priority.rb', line 88 def assign_at_midpoint? @assign_at_midpoint || false end |
.names ⇒ Object
62 63 64 |
# File 'lib/delayed/priority.rb', line 62 def names @names || default_names end |
.names=(names) ⇒ Object
70 71 72 73 74 75 76 77 |
# File 'lib/delayed/priority.rb', line 70 def names=(names) raise "must include a name for priority >= 0" if names && !names.value?(0) @ranges = nil @alerts = nil @names_to_priority = nil @names = names&.sort_by(&:last)&.to_h&.transform_values { |v| new(v) } end |
.names_to_priority ⇒ Object
98 99 100 101 102 103 104 105 |
# File 'lib/delayed/priority.rb', line 98 def names_to_priority @names_to_priority ||= if assign_at_midpoint? names_to_midpoint_priority else names end end |
.ranges ⇒ Object
92 93 94 95 96 |
# File 'lib/delayed/priority.rb', line 92 def ranges @ranges ||= names.zip(names.except(names.keys.first)).each_with_object({}) do |((name, lower), (_, upper)), obj| obj[name] = (lower...(upper || Float::INFINITY)) end end |
Instance Method Details
#+(other) ⇒ Object
181 182 183 184 |
# File 'lib/delayed/priority.rb', line 181 def +(other) other = other.to_i if other.is_a?(self.class) self.class.new(to_i + other) end |
#-(other) ⇒ Object
176 177 178 179 |
# File 'lib/delayed/priority.rb', line 176 def -(other) other = other.to_i if other.is_a?(self.class) self.class.new(to_i - other) end |
#<=>(other) ⇒ Object
171 172 173 174 |
# File 'lib/delayed/priority.rb', line 171 def <=>(other) other = other.to_i if other.is_a?(self.class) to_i <=> other end |
#alert_age ⇒ Object
155 156 157 |
# File 'lib/delayed/priority.rb', line 155 def alert_age self.class.alerts.dig(name, :age) end |
#alert_attempts ⇒ Object
163 164 165 |
# File 'lib/delayed/priority.rb', line 163 def alert_attempts self.class.alerts.dig(name, :attempts) end |
#alert_run_time ⇒ Object
159 160 161 |
# File 'lib/delayed/priority.rb', line 159 def alert_run_time self.class.alerts.dig(name, :run_time) end |
#coerce(other) ⇒ Object
167 168 169 |
# File 'lib/delayed/priority.rb', line 167 def coerce(other) [self.class.new(other), self] end |
#name ⇒ Object
151 152 153 |
# File 'lib/delayed/priority.rb', line 151 def name @name ||= self.class.ranges.find { |(_, r)| r.include?(to_i) }&.first end |
#to_d ⇒ Object
186 187 188 |
# File 'lib/delayed/priority.rb', line 186 def to_d to_i.to_d end |