bluth 0.7.0 → 0.7.2
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.
- data/CHANGES.txt +20 -0
- data/Rakefile +1 -1
- data/VERSION.yml +1 -1
- data/bin/bluth +2 -0
- data/bluth.gemspec +5 -5
- data/lib/bluth.rb +18 -2
- data/lib/bluth/cli.rb +14 -7
- data/lib/bluth/timingbelt.rb +7 -6
- data/lib/bluth/worker.rb +85 -36
- data/try/30_timingbelt_try.rb +2 -3
- metadata +3 -3
data/CHANGES.txt
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
BLUTH, CHANGES
|
2
2
|
|
3
|
+
#### 0.7.2 (2011-04-10) ###############################
|
4
|
+
|
5
|
+
* FIXED: Bluth::TimingBelt.notch now caches notches by absolute time (not just HH:MM)
|
6
|
+
* CHANGE: Gracefully rescue Errno::ECONNREFUSED and try to reconnect
|
7
|
+
* ADDED: Bluth::Worker.reconnect!
|
8
|
+
* ADDED: Bluth::Worker.onerror
|
9
|
+
|
10
|
+
|
11
|
+
#### 0.7.1 (2011-03-06) ###############################
|
12
|
+
|
13
|
+
* FIXED: replace-worker command now always grabs the oldest worker
|
14
|
+
and gracefully exits when there's no workers.
|
15
|
+
* CHANGE: Bluth::Gob objects have a ttl of 2 hours (up from 1)
|
16
|
+
* CHANGE: Bluth::Worker.interval is now 1 sec (down from 2)
|
17
|
+
* CHANGE: Default queuetimeout is now 30 seconds (down from 30)
|
18
|
+
* ADDED: Bluth::Worker processes now handle USR1 and USR2 signals
|
19
|
+
for enabling/disabling debugging and increasing/decreasing
|
20
|
+
Bluth.queuetimeout (respectively)
|
21
|
+
|
22
|
+
|
3
23
|
#### 0.7.0 (2011-03-04) ###############################
|
4
24
|
|
5
25
|
* ADDED: backtrace field to Bluth::Gob
|
data/Rakefile
CHANGED
@@ -25,7 +25,7 @@ begin
|
|
25
25
|
gem.email = "delano@solutious.com"
|
26
26
|
gem.homepage = "http://github.com/delano/bluth"
|
27
27
|
gem.authors = ["Delano Mandelbaum"]
|
28
|
-
gem.add_dependency("familia", ">= 0.
|
28
|
+
gem.add_dependency("familia", ">= 0.7.1")
|
29
29
|
gem.add_dependency('sysinfo', '>= 0.7.3')
|
30
30
|
gem.add_dependency('annoy')
|
31
31
|
|
data/VERSION.yml
CHANGED
data/bin/bluth
CHANGED
@@ -66,6 +66,7 @@ class Bluth::CLI::Definition
|
|
66
66
|
|
67
67
|
#TODO: command :enqueue
|
68
68
|
|
69
|
+
#option :o, :ontheminute, "Start the worker precisely on the minute"
|
69
70
|
command :start_worker => Bluth::CLI
|
70
71
|
command :start_scheduler => Bluth::CLI
|
71
72
|
|
@@ -77,6 +78,7 @@ class Bluth::CLI::Definition
|
|
77
78
|
command :stop_scheduler => Bluth::CLI
|
78
79
|
|
79
80
|
about "Stop the oldest worker and start a new instance in its place."
|
81
|
+
#option :o, :ontheminute, "Start the worker precisely on the minute"
|
80
82
|
command :replace_worker => Bluth::CLI
|
81
83
|
|
82
84
|
command :workers => Bluth::CLI
|
data/bluth.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{bluth}
|
8
|
-
s.version = "0.7.
|
8
|
+
s.version = "0.7.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Delano Mandelbaum"]
|
12
|
-
s.date = %q{2011-
|
12
|
+
s.date = %q{2011-04-12}
|
13
13
|
s.default_executable = %q{bluth}
|
14
14
|
s.description = %q{A Redis queuing system built on top of Familia}
|
15
15
|
s.email = %q{delano@solutious.com}
|
@@ -50,16 +50,16 @@ Gem::Specification.new do |s|
|
|
50
50
|
s.specification_version = 3
|
51
51
|
|
52
52
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
53
|
-
s.add_runtime_dependency(%q<familia>, [">= 0.
|
53
|
+
s.add_runtime_dependency(%q<familia>, [">= 0.7.1"])
|
54
54
|
s.add_runtime_dependency(%q<sysinfo>, [">= 0.7.3"])
|
55
55
|
s.add_runtime_dependency(%q<annoy>, [">= 0"])
|
56
56
|
else
|
57
|
-
s.add_dependency(%q<familia>, [">= 0.
|
57
|
+
s.add_dependency(%q<familia>, [">= 0.7.1"])
|
58
58
|
s.add_dependency(%q<sysinfo>, [">= 0.7.3"])
|
59
59
|
s.add_dependency(%q<annoy>, [">= 0"])
|
60
60
|
end
|
61
61
|
else
|
62
|
-
s.add_dependency(%q<familia>, [">= 0.
|
62
|
+
s.add_dependency(%q<familia>, [">= 0.7.1"])
|
63
63
|
s.add_dependency(%q<sysinfo>, [">= 0.7.3"])
|
64
64
|
s.add_dependency(%q<annoy>, [">= 0"])
|
65
65
|
end
|
data/lib/bluth.rb
CHANGED
@@ -35,7 +35,7 @@ module Bluth
|
|
35
35
|
class Shutdown < Familia::Problem; end
|
36
36
|
@db = 0
|
37
37
|
@env = :dev
|
38
|
-
@queuetimeout =
|
38
|
+
@queuetimeout = 30 #.seconds
|
39
39
|
@handlers = []
|
40
40
|
@locks = []
|
41
41
|
@sysinfo = nil
|
@@ -66,6 +66,18 @@ module Bluth
|
|
66
66
|
def connect
|
67
67
|
instance_eval &onconnect unless onconnect.nil?
|
68
68
|
end
|
69
|
+
def reconnect! delay=5
|
70
|
+
sleep delay
|
71
|
+
success = begin
|
72
|
+
Familia.reconnect_all!
|
73
|
+
(Bluth::Gob.redis.ping.to_s.upcase == 'PONG')
|
74
|
+
rescue => ex
|
75
|
+
Familia.info " #{ex.message}"
|
76
|
+
false
|
77
|
+
end
|
78
|
+
Familia.info " reconnected: #{success}"
|
79
|
+
success
|
80
|
+
end
|
69
81
|
end
|
70
82
|
|
71
83
|
def Bluth.clear_locks
|
@@ -173,6 +185,10 @@ module Bluth
|
|
173
185
|
gob.current_queue = :running
|
174
186
|
gob.save
|
175
187
|
end
|
188
|
+
|
189
|
+
rescue Errno::ECONNREFUSED => ex
|
190
|
+
raise ex
|
191
|
+
|
176
192
|
rescue => ex
|
177
193
|
if queue.nil?
|
178
194
|
Familia.info "ERROR: #{ex.message}"
|
@@ -255,7 +271,7 @@ module Bluth
|
|
255
271
|
MAX_ATTEMPTS = 3.freeze unless defined?(Gob::MAX_ATTEMPTS)
|
256
272
|
include Familia
|
257
273
|
prefix [:bluth, :gob]
|
258
|
-
ttl
|
274
|
+
ttl 60*60*2 # 2 hours
|
259
275
|
index :jobid
|
260
276
|
field :jobid => Gibbler::Digest
|
261
277
|
field :handler => String
|
data/lib/bluth/cli.rb
CHANGED
@@ -29,7 +29,7 @@ module Bluth
|
|
29
29
|
def start_worker worker_class=Bluth::Worker
|
30
30
|
if @global.daemon
|
31
31
|
worker = worker_class.new
|
32
|
-
Familia.info "Created: #{worker.
|
32
|
+
Familia.info "Created: #{worker.index}"
|
33
33
|
worker.daemonize
|
34
34
|
worker.run
|
35
35
|
else
|
@@ -56,14 +56,21 @@ module Bluth
|
|
56
56
|
|
57
57
|
def replace_worker worker_class=Bluth::Worker
|
58
58
|
Bluth.connect
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
workers = worker_class.instances.members.select { |w| w.host == Bluth.sysinfo.hostname }
|
60
|
+
if workers.empty?
|
61
|
+
Familia.info "No workers running on #{Bluth.sysinfo.hostname}"
|
62
|
+
else
|
63
|
+
workers.sort! { |a,b| a.created <=> b.created }
|
64
|
+
oldest_worker = workers.first
|
65
|
+
Familia.info "Replacing #{oldest_worker.index}/#{oldest_worker.pid} (running since #{Time.at(oldest_worker.created).utc})"
|
66
|
+
kill_worker oldest_worker, worker_class
|
67
|
+
@global.daemon = true
|
68
|
+
start_worker worker_class
|
69
|
+
end
|
63
70
|
end
|
64
71
|
|
65
72
|
def workers worker_class=Bluth::Worker
|
66
|
-
Familia.info worker_class.all.collect &:
|
73
|
+
Familia.info worker_class.all.collect &:index
|
67
74
|
end
|
68
75
|
|
69
76
|
private
|
@@ -73,7 +80,7 @@ module Bluth
|
|
73
80
|
Familia.info "No such worker"
|
74
81
|
exit 1
|
75
82
|
else
|
76
|
-
Familia.info "Killing #{worker.
|
83
|
+
Familia.info "Killing #{worker.index}"
|
77
84
|
worker.kill @option.force
|
78
85
|
end
|
79
86
|
end
|
data/lib/bluth/timingbelt.rb
CHANGED
@@ -65,18 +65,19 @@ module Bluth
|
|
65
65
|
(time + (mins*60)).strftime('%H:%M')
|
66
66
|
end
|
67
67
|
def notch mins=0, filter=nil, time=now
|
68
|
+
cache_key = [now(mins, time).to_i, filter].join(':')
|
68
69
|
key = rediskey(stamp(mins, time), filter)
|
69
70
|
@notchcache ||= {}
|
70
|
-
if @notchcache[
|
71
|
-
@notchcache[
|
71
|
+
if @notchcache[cache_key].nil?
|
72
|
+
@notchcache[cache_key] ||= Familia::Set.new key,
|
72
73
|
:ttl => 2*60*60, # 2 hours
|
73
74
|
:extend => Bluth::TimingBelt::Notch,
|
74
75
|
:db => Bluth::TimingBelt.db
|
75
|
-
@notchcache[
|
76
|
-
@notchcache[
|
77
|
-
@notchcache[
|
76
|
+
@notchcache[cache_key].stamp = stamp(mins, time)
|
77
|
+
@notchcache[cache_key].filter = filter
|
78
|
+
@notchcache[cache_key].time = now(mins, time)
|
78
79
|
end
|
79
|
-
@notchcache[
|
80
|
+
@notchcache[cache_key]
|
80
81
|
end
|
81
82
|
def priority minutes=2, filter=nil, time=now
|
82
83
|
(0..minutes).to_a.reverse.collect { |min| notch(min*-1, filter, time) }
|
data/lib/bluth/worker.rb
CHANGED
@@ -78,15 +78,27 @@ module Bluth
|
|
78
78
|
me = new nil, nil, wid
|
79
79
|
super(me.index)
|
80
80
|
end
|
81
|
+
def reconnect! name=nil
|
82
|
+
Familia.info "Reconnecting #{name}"
|
83
|
+
attempt = 0
|
84
|
+
success = false
|
85
|
+
reconnect_tries.times {
|
86
|
+
attempt += 1
|
87
|
+
Familia.info " reconnecting in #{reconnect_delay} (\##{attempt} of #{reconnect_tries})..."
|
88
|
+
success = Bluth.reconnect! reconnect_delay
|
89
|
+
break if success
|
90
|
+
}
|
91
|
+
success
|
92
|
+
end
|
81
93
|
def run!(*args)
|
82
94
|
me = new
|
83
|
-
Familia.info "Created: #{me.
|
95
|
+
Familia.info "Created: #{me.index}"
|
84
96
|
me.run!
|
85
97
|
me
|
86
98
|
end
|
87
99
|
def run(*args)
|
88
100
|
me = new
|
89
|
-
Familia.info "Created: #{me.
|
101
|
+
Familia.info "Created: #{me.index}"
|
90
102
|
me.run
|
91
103
|
me
|
92
104
|
end
|
@@ -99,6 +111,10 @@ module Bluth
|
|
99
111
|
@onstart = blk unless blk.nil?
|
100
112
|
@onstart
|
101
113
|
end
|
114
|
+
def onerror &blk
|
115
|
+
@onerror = blk unless blk.nil?
|
116
|
+
@onerror
|
117
|
+
end
|
102
118
|
def onexit &blk
|
103
119
|
@onexit = blk unless blk.nil?
|
104
120
|
@onexit
|
@@ -113,9 +129,11 @@ module Bluth
|
|
113
129
|
end
|
114
130
|
|
115
131
|
class Worker < Storable
|
116
|
-
@interval =
|
132
|
+
@interval = 1 #.seconds
|
133
|
+
@reconnect_delay = 15 #.seconds
|
134
|
+
@reconnect_tries = 20
|
117
135
|
class << self
|
118
|
-
attr_accessor :interval
|
136
|
+
attr_accessor :interval, :reconnect_delay, :reconnect_tries
|
119
137
|
end
|
120
138
|
include WorkerBase
|
121
139
|
include Familia
|
@@ -143,17 +161,41 @@ module Bluth
|
|
143
161
|
end
|
144
162
|
end
|
145
163
|
|
164
|
+
def carefully
|
165
|
+
begin
|
166
|
+
yield
|
167
|
+
rescue Errno::ECONNREFUSED => ex
|
168
|
+
|
169
|
+
unless Bluth::Worker.reconnect! self.index
|
170
|
+
self.class.onerror.call ex, self if self.class.onerror
|
171
|
+
Familia.info "Reconnect failed :["
|
172
|
+
end
|
173
|
+
|
174
|
+
rescue => ex
|
175
|
+
if self.class.onerror
|
176
|
+
self.class.onerror.call ex, self
|
177
|
+
else
|
178
|
+
Familia.info ex.message
|
179
|
+
Familia.ld ex.backtrace
|
180
|
+
problem!
|
181
|
+
end
|
182
|
+
#if problem > 5
|
183
|
+
# ## TODO: SEND EMAIL
|
184
|
+
# task.unschedule unless task.nil? # Kill this worker b/c something is clearly wrong
|
185
|
+
# destroy!
|
186
|
+
# EM.stop
|
187
|
+
# exit 1
|
188
|
+
#end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
146
192
|
def run!
|
147
193
|
begin
|
148
194
|
Bluth.connect
|
149
195
|
self.class.runblock :onstart
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
Familia.info msg
|
154
|
-
Familia.trace :EXCEPTION, msg, caller[1] if Familia.debug?
|
155
|
-
self.class.runblock :onexit
|
156
|
-
destroy!
|
196
|
+
carefully do
|
197
|
+
find_gob
|
198
|
+
end
|
157
199
|
rescue Interrupt => ex
|
158
200
|
puts $/, "Exiting..."
|
159
201
|
self.class.runblock :onexit
|
@@ -164,25 +206,39 @@ module Bluth
|
|
164
206
|
def run
|
165
207
|
begin
|
166
208
|
@process_id = $$
|
167
|
-
scheduler = Rufus::Scheduler.start_new
|
209
|
+
@scheduler = Rufus::Scheduler.start_new
|
168
210
|
Bluth.connect
|
169
211
|
self.class.runblock :onstart
|
170
212
|
Familia.info "Setting interval: #{Worker.interval} sec (queuetimeout: #{Bluth.queuetimeout})"
|
171
213
|
Familia.reconnect_all! # Need to reconnect after daemonize
|
172
214
|
save
|
173
|
-
|
174
|
-
Familia.
|
175
|
-
|
176
|
-
find_gob task
|
215
|
+
Signal.trap("USR1") do
|
216
|
+
Familia.debug = (Familia.debug == false)
|
217
|
+
Familia.info "Debugging is #{Familia.debug ? 'enabled' : 'disabled'}"
|
177
218
|
end
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
219
|
+
@usr2_reduce = true
|
220
|
+
Signal.trap("USR2") do
|
221
|
+
@usr2_reduce = false if Bluth.queuetimeout <= 2
|
222
|
+
@usr2_reduce = true if Bluth.queuetimeout >= 60
|
223
|
+
if @usr2_reduce
|
224
|
+
#Worker.interval /= 2.0
|
225
|
+
Bluth.queuetimeout /= 2
|
226
|
+
else
|
227
|
+
#Worker.interval *= 2.0
|
228
|
+
Bluth.queuetimeout *= 2
|
229
|
+
end
|
230
|
+
Familia.info "Set intervals: #{Worker.interval} sec / #{Bluth.queuetimeout} sec"
|
231
|
+
end
|
232
|
+
## TODO: on_the_minute = Time.at(BS.quantize(Stella.now, 1.minute)+1.minute).utc ## first_at
|
233
|
+
## @option.ontheminute
|
234
|
+
@task = @scheduler.every Worker.interval, :blocking => true, :first_in => '2s' do |task|
|
235
|
+
carefully do
|
236
|
+
Familia.ld "#{$$} TICK @ #{Time.now.utc}" if Familia.debug?
|
237
|
+
find_gob task
|
238
|
+
end
|
239
|
+
end
|
240
|
+
@scheduler.join
|
241
|
+
|
186
242
|
rescue Interrupt => ex
|
187
243
|
puts <<-EOS.gsub(/(?:^|\n)\s*/, "\n")
|
188
244
|
Exiting...
|
@@ -191,13 +247,13 @@ module Bluth
|
|
191
247
|
EOS
|
192
248
|
# We reconnect to the queue in case we're currently
|
193
249
|
# waiting on a brpop (blocking pop) timeout.
|
194
|
-
self.class.runblock :onexit
|
195
250
|
destroy!
|
251
|
+
ensure
|
252
|
+
self.class.runblock :onexit
|
196
253
|
end
|
197
254
|
|
198
255
|
end
|
199
256
|
|
200
|
-
|
201
257
|
private
|
202
258
|
|
203
259
|
# DO NOT call return from this method
|
@@ -222,7 +278,7 @@ module Bluth
|
|
222
278
|
job.success!
|
223
279
|
self.success!
|
224
280
|
end
|
225
|
-
end
|
281
|
+
end
|
226
282
|
rescue Bluth::Shutdown => ex
|
227
283
|
msg = "Shutdown requested: #{ex.message}"
|
228
284
|
job.success! msg
|
@@ -239,18 +295,11 @@ module Bluth
|
|
239
295
|
job.failure! ex.message
|
240
296
|
self.failure!
|
241
297
|
rescue => ex
|
242
|
-
Familia.info ex.message
|
243
298
|
Familia.info ex.backtrace
|
244
299
|
job.retry! "#{ex.class}: #{ex.message}" if job
|
245
|
-
|
246
|
-
#if problem > 5
|
247
|
-
# ## TODO: SEND EMAIL
|
248
|
-
# task.unschedule unless task.nil? # Kill this worker b/c something is clearly wrong
|
249
|
-
# destroy!
|
250
|
-
# EM.stop
|
251
|
-
# exit 1
|
252
|
-
#end
|
300
|
+
raise ex
|
253
301
|
end
|
302
|
+
|
254
303
|
end
|
255
304
|
end
|
256
305
|
|
data/try/30_timingbelt_try.rb
CHANGED
@@ -9,11 +9,11 @@ Bluth::TimingBelt.redis.flushdb
|
|
9
9
|
|
10
10
|
## Knows now
|
11
11
|
Bluth::TimingBelt.now(0, @now).to_s
|
12
|
-
#=> '2011-02-14 00:00:00 UTC'
|
12
|
+
#=> RUBY_VERSION <= '1.9' ? 'Mon Feb 14 00:00:00 UTC 2011' : '2011-02-14 00:00:00 UTC'
|
13
13
|
|
14
14
|
## Now can have an offset
|
15
15
|
Bluth::TimingBelt.now(5, @now).to_s
|
16
|
-
#=> '2011-02-14 00:05:00 UTC'
|
16
|
+
#=> RUBY_VERSION <= '1.9' ? 'Mon Feb 14 00:05:00 UTC 2011' : '2011-02-14 00:05:00 UTC'
|
17
17
|
|
18
18
|
## Can create a timestamp
|
19
19
|
Bluth::TimingBelt.stamp 0, @now
|
@@ -94,7 +94,6 @@ notches.first.name unless notches.first.nil?
|
|
94
94
|
## Can calculate the difference between two notches
|
95
95
|
notch1 = Bluth::TimingBelt.notch
|
96
96
|
notch2 = Bluth::TimingBelt.notch 67
|
97
|
-
puts notch2.name
|
98
97
|
notch2 - notch1
|
99
98
|
#=> 67
|
100
99
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: bluth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.7.
|
5
|
+
version: 0.7.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Delano Mandelbaum
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-04-12 00:00:00 -04:00
|
14
14
|
default_executable: bluth
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
requirements:
|
22
22
|
- - ">="
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: 0.
|
24
|
+
version: 0.7.1
|
25
25
|
type: :runtime
|
26
26
|
version_requirements: *id001
|
27
27
|
- !ruby/object:Gem::Dependency
|