aeternitas 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +8 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +289 -0
- data/Rakefile +6 -0
- data/aeternitas.gemspec +44 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/aeternitas.rb +80 -0
- data/lib/aeternitas/errors.rb +48 -0
- data/lib/aeternitas/guard.rb +199 -0
- data/lib/aeternitas/metrics.rb +162 -0
- data/lib/aeternitas/metrics/counter.rb +18 -0
- data/lib/aeternitas/metrics/ratio.rb +67 -0
- data/lib/aeternitas/metrics/ten_minutes_resolution.rb +40 -0
- data/lib/aeternitas/metrics/values.rb +18 -0
- data/lib/aeternitas/pollable.rb +197 -0
- data/lib/aeternitas/pollable/configuration.rb +64 -0
- data/lib/aeternitas/pollable/dsl.rb +124 -0
- data/lib/aeternitas/pollable_meta_data.rb +73 -0
- data/lib/aeternitas/polling_frequency.rb +24 -0
- data/lib/aeternitas/sidekiq.rb +5 -0
- data/lib/aeternitas/sidekiq/middleware.rb +31 -0
- data/lib/aeternitas/sidekiq/poll_job.rb +30 -0
- data/lib/aeternitas/source.rb +62 -0
- data/lib/aeternitas/storage_adapter.rb +46 -0
- data/lib/aeternitas/storage_adapter/file.rb +73 -0
- data/lib/aeternitas/version.rb +3 -0
- data/lib/generators/aeternitas/install_generator.rb +35 -0
- data/lib/generators/aeternitas/templates/add_aeternitas.rb.erb +25 -0
- data/lib/generators/aeternitas/templates/initializer.rb +10 -0
- data/logo.png +0 -0
- data/logo.svg +198 -0
- metadata +289 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
module Aeternitas
|
2
|
+
module Metrics
|
3
|
+
# Wrapper for {TabsTabs::Metrics::Counter::Stats}.
|
4
|
+
# It is for Counter metrics.
|
5
|
+
class Counter
|
6
|
+
include Enumerable
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators :@tabstabs_stats, :min, :max, :avg, :each, :to_a, :first, :last
|
10
|
+
|
11
|
+
# Create a new Wrapper
|
12
|
+
# @param [TabsTabs::Metrics::Counter::Stats] tabstabs_stats the wrapped stats.
|
13
|
+
def initialize(tabstabs_stats)
|
14
|
+
@tabstabs_stats = tabstabs_stats
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Aeternitas
|
2
|
+
module Metrics
|
3
|
+
# Stores time series data for ratios
|
4
|
+
# @!attribute [r] from
|
5
|
+
# @return [DateTime] start of the time series
|
6
|
+
# @!attribute [r] to
|
7
|
+
# @return [DateTime] end of the time series
|
8
|
+
# @!attribute [r] resolution
|
9
|
+
# @return [Symbol] resolution of the time series
|
10
|
+
# @!attribute [r] values
|
11
|
+
# @return [Array] time series data
|
12
|
+
# The time series values have the following format:
|
13
|
+
# {
|
14
|
+
# timestamp: DateTime("2000-01-01 00:00:00 UTC"),
|
15
|
+
# ratio: 0.01
|
16
|
+
# }
|
17
|
+
class Ratio
|
18
|
+
include Enumerable
|
19
|
+
|
20
|
+
attr_reader :from, :to, :resolution, :values
|
21
|
+
|
22
|
+
# Create a new ratio time series
|
23
|
+
# @param [DateTime] from start of the time series
|
24
|
+
# @param [DateTime] to end of the time series
|
25
|
+
# @param [Symbol] resolution time series resolution
|
26
|
+
# @param [Array] values time series data
|
27
|
+
def initialize(from, to, resolution, values)
|
28
|
+
@from = from
|
29
|
+
@to = to
|
30
|
+
@resolution = resolution
|
31
|
+
@values = values
|
32
|
+
end
|
33
|
+
|
34
|
+
def each(&block)
|
35
|
+
@values.each(&block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_a
|
39
|
+
@values.to_a
|
40
|
+
end
|
41
|
+
|
42
|
+
# Computes the minimum ration within the time series.
|
43
|
+
# @return [Float] the minimum ratio
|
44
|
+
def min
|
45
|
+
@values.min_by { |v| v['ratio'] }['ratio']
|
46
|
+
end
|
47
|
+
|
48
|
+
# Computes the maximum ration within the time series.
|
49
|
+
# @return [Float] the maximum ratio
|
50
|
+
def max
|
51
|
+
@values.max_by { |v| v['ratio'] }['ratio']
|
52
|
+
end
|
53
|
+
|
54
|
+
# Computes the average ration within the time series.
|
55
|
+
# @return [Float] the average ratio
|
56
|
+
def avg
|
57
|
+
return 0 if count.zero?
|
58
|
+
p @values
|
59
|
+
@values.inject(0) { |sum, v| sum + v[:ratio] } / @values.count
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s
|
63
|
+
values.to_s
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Aeternitas
|
2
|
+
module Metrics
|
3
|
+
# A TabsTabs resolution represeting 10 minute intervals.
|
4
|
+
module TenMinutesResolution
|
5
|
+
include TabsTabs::Resolutionable
|
6
|
+
extend self
|
7
|
+
|
8
|
+
PATTERN = '%Y-%m-%d-%H-%M'.freeze
|
9
|
+
|
10
|
+
def name
|
11
|
+
:ten_minutes
|
12
|
+
end
|
13
|
+
|
14
|
+
def serialize(ts)
|
15
|
+
Time.utc(ts.year, ts.month, ts.day, ts.hour, (ts.min / 10).to_i).strftime(PATTERN)
|
16
|
+
end
|
17
|
+
|
18
|
+
def deserialize(str)
|
19
|
+
dt = DateTime.strptime(str, PATTERN)
|
20
|
+
normalize(dt)
|
21
|
+
end
|
22
|
+
|
23
|
+
def from_seconds(s)
|
24
|
+
s / 10.minutes
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_seconds
|
28
|
+
10.minutes
|
29
|
+
end
|
30
|
+
|
31
|
+
def add(ts, number)
|
32
|
+
ts + number * 10.minutes
|
33
|
+
end
|
34
|
+
|
35
|
+
def normalize(ts)
|
36
|
+
Time.utc(ts.year, ts.month, ts.day, ts.hour, ts.min)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Aeternitas
|
2
|
+
module Metrics
|
3
|
+
# Wrapper for {TabsTabs::Metrics::Value::Stats}.
|
4
|
+
# It is for Value metrics.
|
5
|
+
class Values
|
6
|
+
include Enumerable
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators :@tabstabs_stats, :sum, :min, :max, :avg, :each, :to_a, :first, :last
|
10
|
+
|
11
|
+
# Create a new Wrapper
|
12
|
+
# @param [TabsTabs::Metrics::Value::Stats] tabstabs_stats the wrapped stats.
|
13
|
+
def initialize(tabstabs_stats)
|
14
|
+
@tabstabs_stats = tabstabs_stats
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'aeternitas/pollable/configuration'
|
2
|
+
require 'aeternitas/pollable/dsl'
|
3
|
+
|
4
|
+
module Aeternitas
|
5
|
+
# Mixin that enables the frequent polling of the receiving class.
|
6
|
+
# Classes including this method must implement the .poll method.
|
7
|
+
# Polling behaviour can be configured via {.pollable_options}.
|
8
|
+
# @note Can only be used by classes inheriting from ActiveRecord::Base
|
9
|
+
# @example
|
10
|
+
# class MyWebsitePollable < ActiveRecord::Base
|
11
|
+
# includes Aeternitas::Pollable
|
12
|
+
#
|
13
|
+
# polling_options do
|
14
|
+
# polling_frequency :daily
|
15
|
+
# lock_key ->(obj) {obj.url}
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def poll
|
19
|
+
# response = HTTParty.get(self.url)
|
20
|
+
# raise StandardError, "#{self.url} responded with #{response.status}" unless response.success?
|
21
|
+
# HttpSource.create!(content: response.parsed_response)
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
module Pollable
|
25
|
+
extend ActiveSupport::Concern
|
26
|
+
|
27
|
+
included do
|
28
|
+
raise StandardError, 'Aeternitas::Pollable must inherit from ActiveRecord::Base' unless self.ancestors.include?(ActiveRecord::Base)
|
29
|
+
|
30
|
+
has_one :pollable_meta_data, as: :pollable,
|
31
|
+
dependent: :destroy,
|
32
|
+
class_name: 'Aeternitas::PollableMetaData'
|
33
|
+
|
34
|
+
has_many :sources, as: :pollable,
|
35
|
+
dependent: :destroy,
|
36
|
+
class_name: 'Aeternitas::Source'
|
37
|
+
|
38
|
+
validates :pollable_meta_data, presence: true
|
39
|
+
|
40
|
+
before_validation ->(pollable) do
|
41
|
+
pollable.pollable_meta_data ||= pollable.build_pollable_meta_data(state: 'waiting')
|
42
|
+
pollable.pollable_meta_data.pollable_class = pollable.class.name
|
43
|
+
end
|
44
|
+
|
45
|
+
after_commit ->(pollable) { Aeternitas::Metrics.log(:pollables_created, pollable.class) }, on: :create
|
46
|
+
|
47
|
+
delegate :next_polling, :last_polling, :disable_polling, to: :pollable_meta_data
|
48
|
+
end
|
49
|
+
|
50
|
+
# This method runs the polling workflow
|
51
|
+
def execute_poll
|
52
|
+
_before_poll
|
53
|
+
|
54
|
+
begin
|
55
|
+
guard.with_lock { poll }
|
56
|
+
rescue StandardError => e
|
57
|
+
if pollable_configuration.deactivation_errors.include?(e.class)
|
58
|
+
disable_polling(e)
|
59
|
+
return false
|
60
|
+
elsif pollable_configuration.ignored_errors.include?(e.class)
|
61
|
+
pollable_meta_data.has_errored!
|
62
|
+
raise Aeternitas::Errors::Ignored, e
|
63
|
+
else
|
64
|
+
pollable_meta_data.has_errored!
|
65
|
+
raise e
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
_after_poll
|
70
|
+
rescue StandardError => e
|
71
|
+
begin
|
72
|
+
log_poll_error(e)
|
73
|
+
ensure
|
74
|
+
raise e
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
# This method implements the class specific polling behaviour.
|
81
|
+
# It is only called after the lock was acquired successfully.
|
82
|
+
#
|
83
|
+
# @abstract This method must be implemented when {Aeternitas::Pollable} is included
|
84
|
+
def poll
|
85
|
+
raise NotImplementedError, "#{self.class.name} does not implement #poll, required by Aeternitas::Pollable"
|
86
|
+
end
|
87
|
+
|
88
|
+
# Registers the instance as pollable.
|
89
|
+
#
|
90
|
+
# @note Manual registration is only needed if the object was created before
|
91
|
+
# {Aeternitas::Pollable} was included. Otherwise it is done automatically after creation.
|
92
|
+
def register_pollable
|
93
|
+
self.pollable_meta_data ||= create_pollable_meta_data(
|
94
|
+
state: 'waiting',
|
95
|
+
pollable_class: self.class.name
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
def guard
|
100
|
+
guard_key = pollable_configuration.guard_options[:key].call(self)
|
101
|
+
guard_timeout = pollable_configuration.guard_options[:timeout]
|
102
|
+
guard_cooldown = pollable_configuration.guard_options[:cooldown]
|
103
|
+
Aeternitas::Guard.new(guard_key, guard_cooldown, guard_timeout)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Access the Pollables configuration
|
107
|
+
#
|
108
|
+
# @return [Aeternitas::Pollable::Configuration] the pollables configuration
|
109
|
+
def pollable_configuration
|
110
|
+
self.class.pollable_configuration
|
111
|
+
end
|
112
|
+
|
113
|
+
# Creates a new source with the given content if it does not exist
|
114
|
+
# @example
|
115
|
+
# #...
|
116
|
+
# def poll
|
117
|
+
# response = HTTParty.get("http://example.com")
|
118
|
+
# add_source(response.parsed_response)
|
119
|
+
# end
|
120
|
+
# #...
|
121
|
+
# @param [String] raw_content the sources raw content
|
122
|
+
# @return [Aeternitas::Source] the newly created or existing source
|
123
|
+
def add_source(raw_content)
|
124
|
+
source = self.sources.create(raw_content: raw_content)
|
125
|
+
return nil unless source.persisted?
|
126
|
+
|
127
|
+
Aeternitas::Metrics.log(:sources_created, self.class)
|
128
|
+
source
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
# Run all prepolling methods
|
134
|
+
def _before_poll
|
135
|
+
@start_time = Time.now
|
136
|
+
Aeternitas::Metrics.log(:polls, self.class)
|
137
|
+
|
138
|
+
pollable_configuration.before_polling.each { |action| action.call(self) }
|
139
|
+
pollable_meta_data.poll!
|
140
|
+
end
|
141
|
+
|
142
|
+
# Run all postpolling methods
|
143
|
+
def _after_poll
|
144
|
+
pollable_meta_data.wait! do
|
145
|
+
pollable_meta_data.update_attributes!(
|
146
|
+
last_polling: Time.now,
|
147
|
+
next_polling: pollable_configuration.polling_frequency.call(self)
|
148
|
+
)
|
149
|
+
end
|
150
|
+
|
151
|
+
pollable_configuration.after_polling.each { |action| action.call(self) }
|
152
|
+
|
153
|
+
if @start_time
|
154
|
+
execution_time = Time.now - @start_time
|
155
|
+
Aeternitas::Metrics.log_value(:execution_time, self.class, execution_time)
|
156
|
+
Aeternitas::Metrics.log(:guard_timeout_exceeded, self.class) if execution_time > pollable_configuration.guard_options[:timeout]
|
157
|
+
@start_time = nil
|
158
|
+
end
|
159
|
+
Aeternitas::Metrics.log(:successful_polls, self.class)
|
160
|
+
end
|
161
|
+
|
162
|
+
def log_poll_error(e)
|
163
|
+
if e.is_a? Aeternitas::Guard::GuardIsLocked
|
164
|
+
Aeternitas::Metrics.log(:guard_locked, self.class)
|
165
|
+
Aeternitas::Metrics.log_value(:guard_timeout, self.class, e.timeout - Time.now)
|
166
|
+
elsif e.is_a? Aeternitas::Errors::Ignored
|
167
|
+
Aeternitas::Metrics.log(:ignored_error, self.class)
|
168
|
+
Aeternitas::Metrics.log(:failed_polls, self.class)
|
169
|
+
else
|
170
|
+
Aeternitas::Metrics.log(:failed_polls, self.class)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
class_methods do
|
175
|
+
# Access the Pollables configuration
|
176
|
+
# @return [Aeternitas::Pollable::Configuration] the pollables configuration
|
177
|
+
def pollable_configuration
|
178
|
+
@pollable_configuration ||= Aeternitas::Pollable::Configuration.new
|
179
|
+
end
|
180
|
+
|
181
|
+
def pollable_configuration=(config)
|
182
|
+
@pollable_configuration = config
|
183
|
+
end
|
184
|
+
|
185
|
+
# Configure the polling process.
|
186
|
+
# For available configuration options see {Aeternitas::Pollable::Configuration} and {Aeternitas::Pollable::DSL}
|
187
|
+
def polling_options(&block)
|
188
|
+
Aeternitas::Pollable::Dsl.new(self.pollable_configuration, &block)
|
189
|
+
end
|
190
|
+
|
191
|
+
def inherited(other)
|
192
|
+
super
|
193
|
+
other.pollable_configuration = @pollable_configuration.copy
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Aeternitas
|
2
|
+
module Pollable
|
3
|
+
# Holds the configuration of a pollable class
|
4
|
+
# @!attribute [rw] polling_frequency
|
5
|
+
# Method that calculates the next polling time after a successful poll.
|
6
|
+
# (Default: {Aeternitas::PollingFrequency::DAILY})
|
7
|
+
# @!attribute [rw] before_polling
|
8
|
+
# Methods to be run before each poll
|
9
|
+
# @!attribute [rw] after_polling
|
10
|
+
# Methods to be run after each successful poll
|
11
|
+
# @!attribute [rw] queue
|
12
|
+
# Sidekiq queue the poll job will be enqueued in (Default: 'polling')
|
13
|
+
# @!attribute [rw] guard_options
|
14
|
+
# Configuration of the pollables lock (Default: key => class+id, cooldown => 5.seconds, timeout => 10.minutes)
|
15
|
+
# @!attribute [rw] deactivation_errors
|
16
|
+
# The pollable instance will be deactivated if any of these errors occur while polling
|
17
|
+
# @!attribute [rw] ignored_errors
|
18
|
+
# Errors in this list will be wrapped by {Aeternitas::Error::Ignored} if they occur while polling
|
19
|
+
# (i.e. ignore in your exception tracker)
|
20
|
+
# @!attribute [rw] sleep_on_guard_locked
|
21
|
+
# When set to true poll jobs (and effectively the Sidekiq worker thread) will sleep until the
|
22
|
+
# lock is released if the lock could not be acquired. (Default: true)
|
23
|
+
class Configuration
|
24
|
+
attr_accessor :deactivation_errors,
|
25
|
+
:before_polling,
|
26
|
+
:queue,
|
27
|
+
:polling_frequency,
|
28
|
+
:after_polling,
|
29
|
+
:guard_options,
|
30
|
+
:ignored_errors,
|
31
|
+
:sleep_on_guard_locked
|
32
|
+
|
33
|
+
# Creates a new Configuration with default options
|
34
|
+
def initialize
|
35
|
+
@polling_frequency = Aeternitas::PollingFrequency::DAILY
|
36
|
+
@before_polling = []
|
37
|
+
@after_polling = []
|
38
|
+
@guard_options = {
|
39
|
+
key: ->(obj) { return obj.class.name.to_s },
|
40
|
+
timeout: 10.minutes,
|
41
|
+
cooldown: 5.seconds
|
42
|
+
}
|
43
|
+
@deactivation_errors = []
|
44
|
+
@ignored_errors = []
|
45
|
+
@queue = 'polling'
|
46
|
+
@sleep_on_guard_locked = true
|
47
|
+
end
|
48
|
+
|
49
|
+
def copy
|
50
|
+
config = Configuration.new
|
51
|
+
config.polling_frequency = self.polling_frequency
|
52
|
+
config.before_polling = self.before_polling.deep_dup
|
53
|
+
config.after_polling = self.after_polling.deep_dup
|
54
|
+
config.guard_options = self.guard_options.deep_dup
|
55
|
+
config.deactivation_errors = self.deactivation_errors.deep_dup
|
56
|
+
config.ignored_errors = self.ignored_errors.deep_dup
|
57
|
+
config.queue = self.queue
|
58
|
+
config.sleep_on_guard_locked = self.sleep_on_guard_locked
|
59
|
+
config
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Aeternitas
|
2
|
+
module Pollable
|
3
|
+
# DSL wrapper to conveniently configure pollables
|
4
|
+
class Dsl
|
5
|
+
# Create a new DSL instance and configure the configuration with the given block
|
6
|
+
# @param [Aeternitas::Pollable::Configuration] configuration a pollables configuration
|
7
|
+
# @param [Proc] block configuration block
|
8
|
+
def initialize(configuration, &block)
|
9
|
+
@configuration = configuration
|
10
|
+
instance_eval(&block)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Configures the polling frequency. This can be either the name of a {Aeternitas::PollingFrequency}
|
14
|
+
# or a lambda that receives a pollable instance and returns a DateTime
|
15
|
+
#
|
16
|
+
# @param [Symbol, Proc] frequency Sets the polling frequency.
|
17
|
+
# representing the next polling time.
|
18
|
+
# @example using a preset
|
19
|
+
# polling_frequency :weekly
|
20
|
+
# @example using a custom block
|
21
|
+
# polling_frequency ->(pollable) {Time.now + 1.month + Time.now - pollable.created_at.to_i / 3.month * 1.month}
|
22
|
+
# @todo allow custom methods via reference
|
23
|
+
def polling_frequency(frequency)
|
24
|
+
if frequency.is_a?(Symbol)
|
25
|
+
@configuration.polling_frequency = Aeternitas::PollingFrequency.by_name(frequency)
|
26
|
+
else
|
27
|
+
@configuration.polling_frequency = frequency
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Configures a method that will be run before every poll
|
32
|
+
#
|
33
|
+
# @param [Symbol, Block] method method or method name
|
34
|
+
# @example method by reference
|
35
|
+
# before_polling :my_method
|
36
|
+
# ...
|
37
|
+
# def my_method(pollable) do_something end
|
38
|
+
# @example method by block
|
39
|
+
# before_polling ->(pollable) {do_something}
|
40
|
+
def before_polling(method)
|
41
|
+
if method.is_a?(Symbol)
|
42
|
+
@configuration.before_polling << ->(pollable) { pollable.send(method) }
|
43
|
+
else
|
44
|
+
@configuration.before_polling << method
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Configures a method that will be run after every successful poll
|
49
|
+
#
|
50
|
+
# @param [Symbol, Block] method method or method name
|
51
|
+
# @example method by reference
|
52
|
+
# after:polling :my_method
|
53
|
+
# ...
|
54
|
+
# def my_method(pollable) do_something end
|
55
|
+
# @example method by block
|
56
|
+
# after_polling ->(pollable) {do_something}
|
57
|
+
def after_polling(method)
|
58
|
+
if method.is_a?(Symbol)
|
59
|
+
@configuration.after_polling << ->(pollable) { pollable.send(method) }
|
60
|
+
else
|
61
|
+
@configuration.after_polling << method
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Configure errors that will cause the pollable instance to be deactivated immediately during poll.
|
66
|
+
#
|
67
|
+
# @param [Object] error_class error classes
|
68
|
+
def deactivate_on(*error_class)
|
69
|
+
@configuration.deactivation_errors |= error_class
|
70
|
+
end
|
71
|
+
|
72
|
+
# Configure errors that will be wrapped in {Aeternitas::Error::Ignored}.
|
73
|
+
# Use this to group exceptions which should be ignored in your exception tracker.
|
74
|
+
#
|
75
|
+
# @param [Object] error_class error classes
|
76
|
+
def ignore_error(*error_class)
|
77
|
+
@configuration.ignored_errors |= error_class
|
78
|
+
end
|
79
|
+
|
80
|
+
# Configure the Sidekiq queue into which the instance's poll jobs will be enqueued.
|
81
|
+
# @param [String] queue name of the Sidekiq queue
|
82
|
+
def queue(queue)
|
83
|
+
@configuration.queue = queue
|
84
|
+
end
|
85
|
+
|
86
|
+
# Configure the guard key. This can be either a fixed String, a method reference or a block
|
87
|
+
#
|
88
|
+
# @param [String, Symbol, Proc] key lock key
|
89
|
+
# @example using a fixed String
|
90
|
+
# guard_key "MyLockKey"
|
91
|
+
# @example using a method reference
|
92
|
+
# guard_key :url
|
93
|
+
# @example using a block
|
94
|
+
# guard_key ->(pollable) {URI.parse(pollable.url).host}
|
95
|
+
def guard_key(key)
|
96
|
+
@configuration.guard_options[:key] = case key
|
97
|
+
when Symbol
|
98
|
+
->(obj) { return obj.send(key) }
|
99
|
+
when Proc
|
100
|
+
key
|
101
|
+
else
|
102
|
+
->(obj) { return key.to_s }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Configure the guard.
|
107
|
+
# @see guard_key
|
108
|
+
# @see Aeternitas::Guard
|
109
|
+
# @param [Hash] options guard options
|
110
|
+
def guard_options(options)
|
111
|
+
@configuration.guard_options.merge!(options)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Configure the behaviour of poll jobs if a lock can't be acquired.
|
115
|
+
# When set to true poll jobs (and effectively the Sidekiq worker thread) will sleep until the
|
116
|
+
# lock is released if the lock could not be acquired.
|
117
|
+
# @param [Boolean] switch true|false
|
118
|
+
def sleep_on_guard_locked(switch)
|
119
|
+
@configuration.sleep_on_guard_locked = switch
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|