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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41861361bc83b68a51bc52e215bc4807abf67d6a
4
- data.tar.gz: b29769f4efc8e9735bdef5901a95a8b530e080a3
3
+ metadata.gz: 2b9a986f01ee5802f9a0de0140f43326ebc03bdf
4
+ data.tar.gz: 9523ec14d089eecce4b14ec9a193cd8f42ddfe01
5
5
  SHA512:
6
- metadata.gz: 5dafcf250ba4889ba5167b9aa75889c733873a25617f88e1eb6ba7c2afa786547c2490fae1a72f48b92e84cf1eda16d60f1eeceb24a8728b27348376dd1eb9b1
7
- data.tar.gz: 23b14ea36b6a74aa2522fb98f79fecff069172dfa8b5dd4acbab297f473c0c8239850e80daf9ed8a26d24e8182c4069543aacbd6e5e6427beb14ce70fbdb9e60
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
@@ -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 self.class::SLEEP_INTERVAL
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
- klass = job[:klass].constantize
51
- jid = klass.perform_async(job[:arguments])
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
@@ -4,17 +4,19 @@ module Bellbro
4
4
 
5
5
  attr_reader :record
6
6
 
7
- def self.included(klass)
8
- class << klass
9
- def track_with_schema(hash)
10
- self.class_eval do
11
- @log_record_schema = hash
12
- end
13
- end
7
+ def self.included(base)
8
+ base.class_eval do
9
+ extend ClassMethods
10
+ end
11
+ end
14
12
 
15
- def log_record_schema
16
- @log_record_schema
17
- end
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
@@ -1,3 +1,3 @@
1
1
  module Bellbro
2
- VERSION = '0.0.10'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -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 :domain
8
+ attr_reader :context
8
9
 
9
- def init(opts)
10
- # override
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 perform(opts)
19
+ def call
14
20
  # override
15
21
  end
16
22
 
17
- def clean_up
23
+ def should_run?
18
24
  # override
25
+ self.class.should_run?
19
26
  end
20
27
 
21
- def transition
22
- # override
28
+ def debug?
29
+ @debug ||= !!context[:debug] rescue false
23
30
  end
24
31
 
25
- def i_am_alone_with_this_domain?
26
- self.class.jobs_with_domain(@domain).select { |j| jid != j[:jid] }.empty? &&
27
- self.class.workers_with_domain(@domain).select { |j| jid != j[:jid] }.empty?
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
- def self._jobs
37
- retryable(on: Redis::TimeoutError) do
38
- jobs_for_class("#{self.name}")
39
- end
40
- end
37
+ private
41
38
 
42
- def self.active_workers
43
- _workers.map do |w|
44
- {
45
- :domain => worker_domain(w),
46
- :jid => worker_jid(w),
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
@@ -9,6 +9,7 @@ require 'airbrake'
9
9
 
10
10
  %w(
11
11
  bellbro/settings.rb
12
+ bellbro/hooks.rb
12
13
  bellbro/retryable.rb
13
14
  bellbro/ringable.rb
14
15
  bellbro/trackable.rb
@@ -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('www.retailer.com')
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.10
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-07 00:00:00.000000000 Z
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