bellbro 0.0.10 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|