bellbro 0.0.10 → 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 +4 -4
- data/lib/bellbro/hooks.rb +264 -0
- data/lib/bellbro/service.rb +35 -7
- data/lib/bellbro/sidekiq_utils.rb +38 -0
- data/lib/bellbro/trackable.rb +14 -11
- data/lib/bellbro/version.rb +1 -1
- data/lib/bellbro/worker.rb +23 -45
- data/lib/bellbro.rb +1 -0
- data/spec/trackable_spec.rb +1 -5
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b9a986f01ee5802f9a0de0140f43326ebc03bdf
|
4
|
+
data.tar.gz: 9523ec14d089eecce4b14ec9a193cd8f42ddfe01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab2080b1e3e50445ddcdcb2ad95d6ffc74f71cd35e5e85bfba8fc388c971da3d246312cd2a223ff1df1b7dab310cf4e936511114839d9943ec85dc1ae4f6b756
|
7
|
+
data.tar.gz: dd48e8a909e52659a22a55100c694b59b90354fe0c536b39c6b9247b7e8d6bbbeb6911b3815870f6555b61fc8dc0e0de3446b1ee297c28169cba62498e6f4cf1
|
@@ -0,0 +1,264 @@
|
|
1
|
+
module Bellbro
|
2
|
+
# Internal: Methods relating to supporting hooks around Sidekiq worker invocation.
|
3
|
+
module Hooks
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
extend ClassMethods
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# Public: Declare hooks to run around worker invocation. The around
|
12
|
+
# method may be called multiple times; subsequent calls append declared
|
13
|
+
# hooks to existing around hooks.
|
14
|
+
#
|
15
|
+
# hooks - Zero or more Symbol method names representing instance methods
|
16
|
+
# to be called around worker invocation. Each instance method
|
17
|
+
# invocation receives an argument representing the next link in
|
18
|
+
# the around hook chain.
|
19
|
+
# block - An optional block to be executed as a hook. If given, the block
|
20
|
+
# is executed after methods corresponding to any given Symbols.
|
21
|
+
#
|
22
|
+
# Examples
|
23
|
+
#
|
24
|
+
# class MyWorker
|
25
|
+
# include Worker
|
26
|
+
#
|
27
|
+
# around :time_execution
|
28
|
+
#
|
29
|
+
# around do |worker|
|
30
|
+
# puts "started"
|
31
|
+
# worker.call
|
32
|
+
# puts "finished"
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# def call
|
36
|
+
# puts "called"
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# private
|
40
|
+
#
|
41
|
+
# def time_execution(worker)
|
42
|
+
# context.start_time = Time.now
|
43
|
+
# worker.call
|
44
|
+
# context.finish_time = Time.now
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# Returns nothing.
|
49
|
+
def around(*hooks, &block)
|
50
|
+
hooks << block if block
|
51
|
+
hooks.each { |hook| around_hooks.push(hook) }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Public: Declare hooks to run before Worker invocation. The before
|
55
|
+
# method may be called multiple times; subsequent calls append declared
|
56
|
+
# hooks to existing before hooks.
|
57
|
+
#
|
58
|
+
# hooks - Zero or more Symbol method names representing instance methods
|
59
|
+
# to be called before worker invocation.
|
60
|
+
# block - An optional block to be executed as a hook. If given, the block
|
61
|
+
# is executed after methods corresponding to any given Symbols.
|
62
|
+
#
|
63
|
+
# Examples
|
64
|
+
#
|
65
|
+
# class MyWorker
|
66
|
+
# include Worker
|
67
|
+
#
|
68
|
+
# before :set_start_time
|
69
|
+
#
|
70
|
+
# before do
|
71
|
+
# puts "started"
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# def call
|
75
|
+
# puts "called"
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# private
|
79
|
+
#
|
80
|
+
# def set_start_time
|
81
|
+
# context.start_time = Time.now
|
82
|
+
# end
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
# Returns nothing.
|
86
|
+
def before(*hooks, &block)
|
87
|
+
hooks << block if block
|
88
|
+
hooks.each { |hook| before_hooks.push(hook) }
|
89
|
+
end
|
90
|
+
|
91
|
+
# Public: Declare hooks to run after Worker invocation. The after
|
92
|
+
# method may be called multiple times; subsequent calls prepend declared
|
93
|
+
# hooks to existing after hooks.
|
94
|
+
#
|
95
|
+
# hooks - Zero or more Symbol method names representing instance methods
|
96
|
+
# to be called after worker invocation.
|
97
|
+
# block - An optional block to be executed as a hook. If given, the block
|
98
|
+
# is executed before methods corresponding to any given Symbols.
|
99
|
+
#
|
100
|
+
# Examples
|
101
|
+
#
|
102
|
+
# class MyWorker
|
103
|
+
# include Worker
|
104
|
+
#
|
105
|
+
# after :set_finish_time
|
106
|
+
#
|
107
|
+
# after do
|
108
|
+
# puts "finished"
|
109
|
+
# end
|
110
|
+
#
|
111
|
+
# def call
|
112
|
+
# puts "called"
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# private
|
116
|
+
#
|
117
|
+
# def set_finish_time
|
118
|
+
# context.finish_time = Time.now
|
119
|
+
# end
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
# Returns nothing.
|
123
|
+
def after(*hooks, &block)
|
124
|
+
hooks << block if block
|
125
|
+
hooks.each { |hook| after_hooks.unshift(hook) }
|
126
|
+
end
|
127
|
+
|
128
|
+
# Internal: An Array of declared hooks to run around Worker
|
129
|
+
# invocation. The hooks appear in the order in which they will be run.
|
130
|
+
#
|
131
|
+
# Examples
|
132
|
+
#
|
133
|
+
# class MyWorker
|
134
|
+
# include Worker
|
135
|
+
#
|
136
|
+
# around :time_execution, :use_transaction
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
# MyWorker.around_hooks
|
140
|
+
# # => [:time_execution, :use_transaction]
|
141
|
+
#
|
142
|
+
# Returns an Array of Symbols and Procs.
|
143
|
+
def around_hooks
|
144
|
+
@around_hooks ||= []
|
145
|
+
end
|
146
|
+
|
147
|
+
# Internal: An Array of declared hooks to run before Worker
|
148
|
+
# invocation. The hooks appear in the order in which they will be run.
|
149
|
+
#
|
150
|
+
# Examples
|
151
|
+
#
|
152
|
+
# class MyWorker
|
153
|
+
# include Sidekiq::Worker
|
154
|
+
#
|
155
|
+
# before :set_start_time, :say_hello
|
156
|
+
# end
|
157
|
+
#
|
158
|
+
# MyWorker.before_hooks
|
159
|
+
# # => [:set_start_time, :say_hello]
|
160
|
+
#
|
161
|
+
# Returns an Array of Symbols and Procs.
|
162
|
+
def before_hooks
|
163
|
+
@before_hooks ||= []
|
164
|
+
end
|
165
|
+
|
166
|
+
# Internal: An Array of declared hooks to run before Worker
|
167
|
+
# invocation. The hooks appear in the order in which they will be run.
|
168
|
+
#
|
169
|
+
# Examples
|
170
|
+
#
|
171
|
+
# class MyWorker
|
172
|
+
# include Sidekiq::Worker
|
173
|
+
#
|
174
|
+
# after :set_finish_time, :say_goodbye
|
175
|
+
# end
|
176
|
+
#
|
177
|
+
# MyWorker.after_hooks
|
178
|
+
# # => [:say_goodbye, :set_finish_time]
|
179
|
+
#
|
180
|
+
# Returns an Array of Symbols and Procs.
|
181
|
+
def after_hooks
|
182
|
+
@after_hooks ||= []
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
# Internal: Run around, before and after hooks around yielded execution. The
|
189
|
+
# required block is surrounded with hooks and executed.
|
190
|
+
#
|
191
|
+
# Examples
|
192
|
+
#
|
193
|
+
# class MyProcessor
|
194
|
+
# include Bellbro::Hooks
|
195
|
+
#
|
196
|
+
# def process_with_hooks
|
197
|
+
# with_hooks do
|
198
|
+
# process
|
199
|
+
# end
|
200
|
+
# end
|
201
|
+
#
|
202
|
+
# def process
|
203
|
+
# puts "processed!"
|
204
|
+
# end
|
205
|
+
# end
|
206
|
+
#
|
207
|
+
# Returns nothing.
|
208
|
+
def with_hooks
|
209
|
+
run_around_hooks do
|
210
|
+
run_before_hooks
|
211
|
+
yield
|
212
|
+
run_after_hooks
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# Internal: Run around hooks.
|
217
|
+
#
|
218
|
+
# Returns nothing.
|
219
|
+
def run_around_hooks(&block)
|
220
|
+
self.class.around_hooks.reverse.inject(block) { |chain, hook|
|
221
|
+
proc { run_hook(hook, chain) }
|
222
|
+
}.call
|
223
|
+
end
|
224
|
+
|
225
|
+
# Internal: Run before hooks.
|
226
|
+
#
|
227
|
+
# Returns nothing.
|
228
|
+
def run_before_hooks
|
229
|
+
run_hooks(self.class.before_hooks)
|
230
|
+
end
|
231
|
+
|
232
|
+
# Internal: Run after hooks.
|
233
|
+
#
|
234
|
+
# Returns nothing.
|
235
|
+
def run_after_hooks
|
236
|
+
run_hooks(self.class.after_hooks)
|
237
|
+
end
|
238
|
+
|
239
|
+
# Internal: Run a colection of hooks. The "run_hooks" method is the common
|
240
|
+
# interface by which collections of either before or after hooks are run.
|
241
|
+
#
|
242
|
+
# hooks - An Array of Symbol and Proc hooks.
|
243
|
+
#
|
244
|
+
# Returns nothing.
|
245
|
+
def run_hooks(hooks)
|
246
|
+
hooks.each { |hook| run_hook(hook) }
|
247
|
+
end
|
248
|
+
|
249
|
+
# Internal: Run an individual hook. The "run_hook" method is the common
|
250
|
+
# interface by which an individual hook is run. If the given hook is a
|
251
|
+
# symbol, the method is invoked whether public or private. If the hook is a
|
252
|
+
# proc, the proc is evaluated in the context of the current instance.
|
253
|
+
#
|
254
|
+
# hook - A Symbol or Proc hook.
|
255
|
+
# args - Zero or more arguments to be passed as block arguments into the
|
256
|
+
# given block or as arguments into the method described by the given
|
257
|
+
# Symbol method name.
|
258
|
+
#
|
259
|
+
# Returns nothing.
|
260
|
+
def run_hook(hook, *args)
|
261
|
+
hook.is_a?(Symbol) ? send(hook, *args) : instance_exec(*args, &hook)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
data/lib/bellbro/service.rb
CHANGED
@@ -5,11 +5,27 @@ module Bellbro
|
|
5
5
|
include Bellbro::SidekiqUtils
|
6
6
|
include Bellbro::Trackable
|
7
7
|
|
8
|
-
SLEEP_INTERVAL = defined?(Rails) && Rails.env.test? ? 1 : 3600
|
9
|
-
track_with_schema jobs_started: Integer
|
10
|
-
|
11
8
|
attr_reader :thread, :thread_error, :jid
|
12
9
|
|
10
|
+
def self.poll_interval(arg)
|
11
|
+
if defined?(Rails) && Rails.env.test?
|
12
|
+
@sleep_interval = 0.5
|
13
|
+
else
|
14
|
+
@sleep_interval = arg
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.worker_class(arg)
|
19
|
+
@worker_class = arg
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.get_worker_class
|
23
|
+
@worker_class
|
24
|
+
end
|
25
|
+
|
26
|
+
poll_interval defined?(Rails) && Rails.env.test? ? 1 : 3600
|
27
|
+
track_with_schema jobs_started: Integer
|
28
|
+
|
13
29
|
def initialize
|
14
30
|
@done = false
|
15
31
|
@jid = Digest::MD5.hexdigest(Time.now.utc.to_s + Thread.current.object_id.to_s)
|
@@ -40,20 +56,23 @@ module Bellbro
|
|
40
56
|
begin
|
41
57
|
start_jobs
|
42
58
|
Service.mutex.synchronize { status_update }
|
43
|
-
sleep
|
59
|
+
sleep
|
44
60
|
end until @done
|
45
61
|
Service.mutex.synchronize { stop_tracking }
|
46
62
|
end
|
47
63
|
|
48
64
|
def start_jobs
|
49
65
|
each_job do |job|
|
50
|
-
|
51
|
-
jid
|
52
|
-
ring "Starting job #{jid} #{job[:klass]} with #{job[:arguments]}."
|
66
|
+
jid = worker_class.perform_async(job)
|
67
|
+
ring "Starting job #{jid} #{worker_class.name} with #{job.inspect}."
|
53
68
|
record_incr(:jobs_started)
|
54
69
|
end
|
55
70
|
end
|
56
71
|
|
72
|
+
def sleep
|
73
|
+
super(self.class.sleep_interval)
|
74
|
+
end
|
75
|
+
|
57
76
|
def each_job
|
58
77
|
# Override
|
59
78
|
[]
|
@@ -63,9 +82,18 @@ module Bellbro
|
|
63
82
|
!@done
|
64
83
|
end
|
65
84
|
|
85
|
+
def worker_class
|
86
|
+
@worker_class ||= self.class.get_worker_class
|
87
|
+
end
|
88
|
+
|
66
89
|
def self.mutex
|
67
90
|
$mutex ||= Mutex.new
|
68
91
|
end
|
92
|
+
|
93
|
+
def self.sleep_interval
|
94
|
+
@sleep_interval
|
95
|
+
end
|
96
|
+
|
69
97
|
end
|
70
98
|
|
71
99
|
end
|
@@ -1,6 +1,44 @@
|
|
1
1
|
module Bellbro
|
2
2
|
module SidekiqUtils
|
3
3
|
|
4
|
+
def _workers
|
5
|
+
retryable(on: Redis::TimeoutError) do
|
6
|
+
workers_for_class("#{self.name}")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def _jobs
|
11
|
+
retryable(on: Redis::TimeoutError) do
|
12
|
+
jobs_for_class("#{self.name}")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def active_workers
|
17
|
+
_workers.map do |w|
|
18
|
+
{
|
19
|
+
:domain => worker_domain(w),
|
20
|
+
:jid => worker_jid(w),
|
21
|
+
:time => worker_time(w)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def queued_jobs
|
27
|
+
_jobs.map { |j| {:domain => job_domain(j), :jid => job_jid(j)} }
|
28
|
+
end
|
29
|
+
|
30
|
+
def workers_with_domain(domain)
|
31
|
+
active_workers.select { |w| w[:domain] == domain }
|
32
|
+
end
|
33
|
+
|
34
|
+
def jobs_with_domain(domain)
|
35
|
+
queued_jobs.select { |j| j[:domain] == domain }
|
36
|
+
end
|
37
|
+
|
38
|
+
def jobs_in_flight_with_domain(domain)
|
39
|
+
jobs_with_domain(domain) + workers_with_domain(domain)
|
40
|
+
end
|
41
|
+
|
4
42
|
def workers
|
5
43
|
Sidekiq::Workers.new.map do |process_id, thread_id, worker|
|
6
44
|
worker
|
data/lib/bellbro/trackable.rb
CHANGED
@@ -4,17 +4,19 @@ module Bellbro
|
|
4
4
|
|
5
5
|
attr_reader :record
|
6
6
|
|
7
|
-
def self.included(
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
end
|
7
|
+
def self.included(base)
|
8
|
+
base.class_eval do
|
9
|
+
extend ClassMethods
|
10
|
+
end
|
11
|
+
end
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
module ClassMethods
|
14
|
+
def track_with_schema(hash)
|
15
|
+
@log_record_schema = hash
|
16
|
+
end
|
17
|
+
|
18
|
+
def log_record_schema
|
19
|
+
@log_record_schema
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
@@ -25,11 +27,12 @@ module Bellbro
|
|
25
27
|
@write_interval = opts[:write_interval] || 500
|
26
28
|
@count = 0
|
27
29
|
@tracking = true
|
28
|
-
initialize_log_record
|
30
|
+
initialize_log_record if @log_record_schema
|
29
31
|
status_update(true)
|
30
32
|
end
|
31
33
|
|
32
34
|
def status_update(force = false)
|
35
|
+
return unless @log_record_schema && Bellbro.logger
|
33
36
|
return unless force || ((@count += 1) % @write_interval) == 0
|
34
37
|
retryable { write_log(@record.to_json) }
|
35
38
|
end
|
data/lib/bellbro/version.rb
CHANGED
data/lib/bellbro/worker.rb
CHANGED
@@ -2,68 +2,46 @@ module Bellbro
|
|
2
2
|
class Worker < Bellbro::Bell
|
3
3
|
include Sidekiq::Worker
|
4
4
|
include Bellbro::Trackable
|
5
|
+
include Bellbro::Hooks
|
5
6
|
extend Bellbro::SidekiqUtils
|
6
7
|
|
7
|
-
attr_reader :
|
8
|
+
attr_reader :context
|
8
9
|
|
9
|
-
def
|
10
|
-
|
10
|
+
def perform(args)
|
11
|
+
return unless args.present?
|
12
|
+
set_context(args)
|
13
|
+
run_before_hooks
|
14
|
+
return unless should_run?
|
15
|
+
call
|
16
|
+
run_after_hooks
|
11
17
|
end
|
12
18
|
|
13
|
-
def
|
19
|
+
def call
|
14
20
|
# override
|
15
21
|
end
|
16
22
|
|
17
|
-
def
|
23
|
+
def should_run?
|
18
24
|
# override
|
25
|
+
self.class.should_run?
|
19
26
|
end
|
20
27
|
|
21
|
-
def
|
22
|
-
|
28
|
+
def debug?
|
29
|
+
@debug ||= !!context[:debug] rescue false
|
23
30
|
end
|
24
31
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
def self._workers
|
31
|
-
retryable(on: Redis::TimeoutError) do
|
32
|
-
workers_for_class("#{self.name}")
|
33
|
-
end
|
32
|
+
def self.should_run?
|
33
|
+
# override
|
34
|
+
true
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
-
retryable(on: Redis::TimeoutError) do
|
38
|
-
jobs_for_class("#{self.name}")
|
39
|
-
end
|
40
|
-
end
|
37
|
+
private
|
41
38
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
:time => worker_time(w)
|
48
|
-
}
|
39
|
+
def set_context(args)
|
40
|
+
if args.is_a?(Hash)
|
41
|
+
@context = args.symbolize_keys
|
42
|
+
else
|
43
|
+
@context = args
|
49
44
|
end
|
50
45
|
end
|
51
|
-
|
52
|
-
def self.queued_jobs
|
53
|
-
_jobs.map { |j| {:domain => job_domain(j), :jid => job_jid(j)} }
|
54
|
-
end
|
55
|
-
|
56
|
-
def self.workers_with_domain(domain)
|
57
|
-
active_workers.select { |w| w[:domain] == domain }
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.jobs_with_domain(domain)
|
61
|
-
queued_jobs.select { |j| j[:domain] == domain }
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.jobs_in_flight_with_domain(domain)
|
65
|
-
jobs_with_domain(domain) + workers_with_domain(domain)
|
66
|
-
end
|
67
46
|
end
|
68
|
-
|
69
47
|
end
|
data/lib/bellbro.rb
CHANGED
data/spec/trackable_spec.rb
CHANGED
@@ -10,10 +10,6 @@ class TrackWorker < Bellbro::Worker
|
|
10
10
|
status: String
|
11
11
|
)
|
12
12
|
|
13
|
-
def initialize(domain)
|
14
|
-
@domain = domain
|
15
|
-
end
|
16
|
-
|
17
13
|
def jid
|
18
14
|
"abc123"
|
19
15
|
end
|
@@ -21,7 +17,7 @@ end
|
|
21
17
|
|
22
18
|
describe Bellbro::Trackable do
|
23
19
|
before :each do
|
24
|
-
@worker = TrackWorker.new
|
20
|
+
@worker = TrackWorker.new
|
25
21
|
Sidekiq::Worker.clear_all
|
26
22
|
end
|
27
23
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bellbro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Stokes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -137,6 +137,7 @@ files:
|
|
137
137
|
- bellbro.gemspec
|
138
138
|
- lib/bellbro.rb
|
139
139
|
- lib/bellbro/bell.rb
|
140
|
+
- lib/bellbro/hooks.rb
|
140
141
|
- lib/bellbro/pool.rb
|
141
142
|
- lib/bellbro/retryable.rb
|
142
143
|
- lib/bellbro/ringable.rb
|