quebert 1.0.9 → 1.11.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.
- data/Gemfile +0 -1
- data/Guardfile +1 -4
- data/lib/quebert/backend/beanstalk.rb +27 -15
- data/lib/quebert/command_line_runner.rb +16 -14
- data/lib/quebert/controller/beanstalk.rb +3 -3
- data/lib/quebert/job.rb +17 -21
- data/lib/quebert/version.rb +2 -2
- data/lib/quebert/worker.rb +19 -10
- data/quebert.gemspec +1 -1
- data/spec/configuration_spec.rb +4 -2
- data/spec/consumer_spec.rb +20 -20
- data/spec/worker_spec.rb +6 -7
- metadata +8 -6
data/Gemfile
CHANGED
data/Guardfile
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
# More info at https://github.com/guard/guard#readme
|
3
|
-
|
4
|
-
guard 'rspec', :version => 1, :cli => '--colour --format nested' do
|
1
|
+
guard 'rspec', :version => 2, :cli => '--colour --format nested' do
|
5
2
|
watch(%r{^spec/.+_spec\.rb$})
|
6
3
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
4
|
watch('spec/spec_helper.rb') { "spec" }
|
@@ -1,36 +1,48 @@
|
|
1
|
-
require '
|
1
|
+
require 'beaneater'
|
2
2
|
|
3
3
|
module Quebert
|
4
4
|
module Backend
|
5
5
|
|
6
6
|
# Manage jobs on a Beanstalk queue out of process
|
7
|
-
class Beanstalk
|
7
|
+
class Beanstalk
|
8
8
|
def put(job, *args)
|
9
|
-
|
9
|
+
priority, delay, ttr = args
|
10
|
+
opts = {}
|
11
|
+
opts[:pri] = priority unless priority.nil?
|
12
|
+
opts[:delay] = delay unless delay.nil?
|
13
|
+
opts[:ttr] = ttr unless ttr.nil?
|
14
|
+
@tube.put job.to_json, opts
|
10
15
|
end
|
11
|
-
|
12
|
-
def
|
13
|
-
|
16
|
+
|
17
|
+
def reserve_without_controller(timeout=nil)
|
18
|
+
@tube.reserve timeout
|
14
19
|
end
|
15
|
-
|
16
|
-
|
17
|
-
|
20
|
+
|
21
|
+
def reserve(timeout=nil)
|
22
|
+
Controller::Beanstalk.new reserve_without_controller(timeout), self
|
23
|
+
end
|
24
|
+
|
25
|
+
def peek(state)
|
26
|
+
@tube.peek state
|
27
|
+
end
|
28
|
+
|
18
29
|
# For testing purposes... I think there's a better way to do this though.
|
19
30
|
def drain!
|
20
|
-
while
|
31
|
+
while peek(:ready) do
|
21
32
|
reserve_without_controller.delete
|
22
33
|
end
|
23
|
-
while
|
34
|
+
while peek(:delayed) do
|
24
35
|
reserve_without_controller.delete
|
25
36
|
end
|
26
|
-
while
|
27
|
-
|
37
|
+
while peek(:buried) do
|
38
|
+
@tube.kick
|
28
39
|
reserve_without_controller.delete
|
29
40
|
end
|
30
41
|
end
|
31
42
|
|
32
|
-
def initialize(host,
|
33
|
-
|
43
|
+
def initialize(host, tube)
|
44
|
+
@pool = Beaneater::Pool.new Array(host)
|
45
|
+
@tube = @pool.tubes[tube]
|
34
46
|
end
|
35
47
|
def self.configure(opts={})
|
36
48
|
opts[:host] ||= ['127.0.0.1:11300']
|
@@ -1,45 +1,47 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
1
3
|
module Quebert
|
2
4
|
class CommandLineRunner
|
3
|
-
|
5
|
+
|
4
6
|
attr_accessor :arguments, :command, :options
|
5
|
-
|
7
|
+
|
6
8
|
def initialize(argv)
|
7
9
|
@argv = argv
|
8
|
-
|
10
|
+
|
9
11
|
# Default options values
|
10
12
|
@options = {
|
11
13
|
:chdir => Dir.pwd
|
12
14
|
}
|
13
|
-
|
15
|
+
|
14
16
|
parse!
|
15
17
|
end
|
16
|
-
|
18
|
+
|
17
19
|
def parser
|
18
20
|
@parser ||= OptionParser.new do |opts|
|
19
21
|
opts.banner = "Usage: quebert [options]"
|
20
|
-
|
22
|
+
|
21
23
|
opts.separator ""
|
22
|
-
|
23
|
-
opts.on("-l", "--log FILE", "File to redirect output " +
|
24
|
+
|
25
|
+
opts.on("-l", "--log FILE", "File to redirect output " +
|
24
26
|
"(default: #{@options[:log]})") { |file| @options[:log] = file }
|
25
|
-
opts.on("-P", "--pid FILE", "File to store PID " +
|
27
|
+
opts.on("-P", "--pid FILE", "File to store PID " +
|
26
28
|
"(default: #{@options[:pid]})") { |file| @options[:pid] = file }
|
27
29
|
opts.on("-C", "--config FILE", "Load options from config file") { |file| @options[:config] = file }
|
28
30
|
opts.on("-c", "--chdir DIR", "Change to dir before starting") { |dir| @options[:chdir] = File.expand_path(dir) }
|
29
31
|
end
|
30
32
|
end
|
31
|
-
|
33
|
+
|
32
34
|
# Parse the options.
|
33
35
|
def parse!
|
34
36
|
parser.parse! @argv
|
35
37
|
@command = @argv.shift
|
36
38
|
@arguments = @argv
|
37
39
|
end
|
38
|
-
|
40
|
+
|
39
41
|
def self.dispatch(args = ARGV)
|
40
42
|
runner = new(args)
|
41
43
|
params = runner.options
|
42
|
-
|
44
|
+
|
43
45
|
if dir = params[:chdir]
|
44
46
|
Dir.chdir dir
|
45
47
|
end
|
@@ -55,10 +57,10 @@ module Quebert
|
|
55
57
|
if config = params[:config] || auto_config
|
56
58
|
require config
|
57
59
|
end
|
58
|
-
|
60
|
+
|
59
61
|
Worker.new.start
|
60
62
|
end
|
61
|
-
|
63
|
+
|
62
64
|
private
|
63
65
|
def self.auto_config
|
64
66
|
rails_env_path = './config/environment.rb'
|
@@ -52,7 +52,7 @@ module Quebert
|
|
52
52
|
log "Job deleted", :error
|
53
53
|
rescue Job::Release
|
54
54
|
log "Releasing with priority: #{@job.priority} and delay: #{@job.delay}", :error
|
55
|
-
beanstalk_job.release @job.priority, @job.delay
|
55
|
+
beanstalk_job.release :pri => @job.priority, :delay => @job.delay
|
56
56
|
log "Job released", :error
|
57
57
|
rescue Job::Bury
|
58
58
|
log "Burrying job", :error
|
@@ -86,10 +86,10 @@ module Quebert
|
|
86
86
|
log "Job burried"
|
87
87
|
else
|
88
88
|
log "TTR exceeded. Releasing with priority: #{@job.priority} and delay: #{delay}"
|
89
|
-
beanstalk_job.release @job.priority, delay
|
89
|
+
beanstalk_job.release :pri => @job.priority, :delay => delay
|
90
90
|
log "Job released"
|
91
91
|
end
|
92
|
-
rescue ::
|
92
|
+
rescue ::Beaneater::NotFoundError => e
|
93
93
|
log "Job ran longer than allowed. Beanstalk already deleted it!!!!", :error
|
94
94
|
# Sometimes the timer doesn't behave correctly and this job actually runs longer than
|
95
95
|
# allowed. At that point the beanstalk job no longer exists anymore. Lets let it go and don't blow up.
|
data/lib/quebert/job.rb
CHANGED
@@ -6,20 +6,20 @@ module Quebert
|
|
6
6
|
|
7
7
|
attr_reader :args
|
8
8
|
attr_accessor :priority, :delay, :ttr
|
9
|
-
|
9
|
+
|
10
10
|
DEFAULT_JOB_PRIORITY = 65536
|
11
11
|
DEFAULT_JOB_DELAY = 0
|
12
12
|
DEFAULT_JOB_TTR = 10
|
13
13
|
|
14
|
-
# A buffer time in seconds added to the Beanstalk TTR for Quebert to do its own job cleanup
|
14
|
+
# A buffer time in seconds added to the Beanstalk TTR for Quebert to do its own job cleanup
|
15
15
|
# The job will perform based on the Beanstalk TTR, but Beanstalk hangs on to the job just a
|
16
16
|
# little longer so that Quebert can bury the job or schedule a retry with the appropriate delay
|
17
17
|
QUEBERT_TTR_BUFFER = 5
|
18
18
|
|
19
19
|
NotImplemented = Class.new(StandardError)
|
20
|
-
|
20
|
+
|
21
21
|
Action = Class.new(Exception)
|
22
|
-
|
22
|
+
|
23
23
|
Bury = Class.new(Action)
|
24
24
|
Delete = Class.new(Action)
|
25
25
|
Release = Class.new(Action)
|
@@ -28,7 +28,7 @@ module Quebert
|
|
28
28
|
|
29
29
|
def initialize(*args)
|
30
30
|
opts = args.last.is_a?(::Hash) ? args.pop : nil
|
31
|
-
|
31
|
+
|
32
32
|
@priority = DEFAULT_JOB_PRIORITY
|
33
33
|
@delay = DEFAULT_JOB_DELAY
|
34
34
|
@ttr = DEFAULT_JOB_TTR
|
@@ -36,7 +36,7 @@ module Quebert
|
|
36
36
|
if opts
|
37
37
|
beanstalk_opts = opts.delete(:beanstalk)
|
38
38
|
args << opts unless opts.empty?
|
39
|
-
|
39
|
+
|
40
40
|
if beanstalk_opts
|
41
41
|
@priority = beanstalk_opts[:priority] if beanstalk_opts[:priority]
|
42
42
|
@delay = beanstalk_opts[:delay] if beanstalk_opts[:delay]
|
@@ -46,41 +46,37 @@ module Quebert
|
|
46
46
|
|
47
47
|
@args = args.dup.freeze
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
def perform(*args)
|
51
51
|
raise NotImplemented
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
# Runs the perform method that somebody else should be implementing
|
55
55
|
def perform!
|
56
56
|
# Honor the timeout and kill the job in ruby-space. Beanstalk
|
57
57
|
# should be cleaning up this job and returning it to the queue
|
58
58
|
# as well.
|
59
|
-
|
60
|
-
Quebert::Timeout.timeout(@ttr){ perform(*args) }
|
61
|
-
rescue ::Timeout::Error => e
|
62
|
-
raise Job::Timeout, e.message, e.backtrace
|
63
|
-
end
|
59
|
+
Quebert::Timeout.timeout(@ttr, Job::Timeout){ perform(*args) }
|
64
60
|
end
|
65
|
-
|
61
|
+
|
66
62
|
def enqueue
|
67
63
|
self.class.backend.put self, @priority, @delay, @ttr + QUEBERT_TTR_BUFFER
|
68
64
|
end
|
69
|
-
|
65
|
+
|
70
66
|
def to_json
|
71
67
|
JSON.generate(Serializer::Job.serialize(self))
|
72
68
|
end
|
73
|
-
|
69
|
+
|
74
70
|
def self.from_json(json)
|
75
71
|
if hash = JSON.parse(json) and not hash.empty?
|
76
72
|
Serializer::Job.deserialize(hash)
|
77
73
|
end
|
78
74
|
end
|
79
|
-
|
75
|
+
|
80
76
|
def self.backend=(backend)
|
81
77
|
@backend = backend
|
82
78
|
end
|
83
|
-
|
79
|
+
|
84
80
|
def self.backend
|
85
81
|
@backend || Quebert.configuration.backend
|
86
82
|
end
|
@@ -89,13 +85,13 @@ module Quebert
|
|
89
85
|
def delete!
|
90
86
|
raise Delete
|
91
87
|
end
|
92
|
-
|
88
|
+
|
93
89
|
def release!
|
94
90
|
raise Release
|
95
91
|
end
|
96
|
-
|
92
|
+
|
97
93
|
def bury!
|
98
94
|
raise Bury
|
99
95
|
end
|
100
96
|
end
|
101
|
-
end
|
97
|
+
end
|
data/lib/quebert/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Quebert
|
2
|
-
VERSION = "1.0
|
3
|
-
end
|
2
|
+
VERSION = "1.11.0"
|
3
|
+
end
|
data/lib/quebert/worker.rb
CHANGED
@@ -3,29 +3,38 @@ module Quebert
|
|
3
3
|
include Logging
|
4
4
|
|
5
5
|
attr_accessor :exception_handler, :backend
|
6
|
-
|
6
|
+
|
7
7
|
def initialize
|
8
8
|
yield self if block_given?
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
# Start the worker backend and intercept exceptions if a handler is provided
|
12
12
|
def start
|
13
13
|
Signal.trap('TERM') { safe_stop }
|
14
14
|
Signal.trap('INT') { safe_stop }
|
15
15
|
|
16
16
|
logger.info "Worker started with #{backend.class.name} backend\n"
|
17
|
-
while @controller = backend.reserve do
|
17
|
+
while @controller = backend.reserve do
|
18
18
|
begin
|
19
19
|
@controller.perform
|
20
|
-
rescue Exception =>
|
21
|
-
|
22
|
-
|
20
|
+
rescue Exception => error
|
21
|
+
if exception_handler
|
22
|
+
exception_handler.call(
|
23
|
+
error,
|
24
|
+
:controller => @controller,
|
25
|
+
:pid => $$,
|
26
|
+
:worker => self
|
27
|
+
)
|
28
|
+
else
|
29
|
+
raise error
|
30
|
+
end
|
31
|
+
end
|
23
32
|
@controller = nil
|
24
33
|
|
25
34
|
stop if @terminate_sent
|
26
35
|
end
|
27
36
|
end
|
28
|
-
|
37
|
+
|
29
38
|
def safe_stop
|
30
39
|
if @terminate_sent
|
31
40
|
logger.info "Ok! I get the point. Shutting down immediately."
|
@@ -41,14 +50,14 @@ module Quebert
|
|
41
50
|
logger.info "Worker stopping\n"
|
42
51
|
exit 0
|
43
52
|
end
|
44
|
-
|
53
|
+
|
45
54
|
protected
|
46
55
|
def backend
|
47
56
|
@backend ||= Quebert.config.backend
|
48
57
|
end
|
49
|
-
|
58
|
+
|
50
59
|
def exception_handler
|
51
60
|
@exception_handler ||= Quebert.config.worker.exception_handler
|
52
61
|
end
|
53
62
|
end
|
54
|
-
end
|
63
|
+
end
|
data/quebert.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
# specify any dependencies here; for example:
|
22
22
|
# s.add_development_dependency "rspec"
|
23
23
|
s.add_runtime_dependency "json"
|
24
|
-
s.add_runtime_dependency "
|
24
|
+
s.add_runtime_dependency "beaneater"
|
25
25
|
|
26
26
|
s.add_development_dependency 'rspec', '2.7.0'
|
27
27
|
end
|
data/spec/configuration_spec.rb
CHANGED
@@ -10,8 +10,10 @@ describe Configuration do
|
|
10
10
|
backend = @config.backend
|
11
11
|
backend.should be_instance_of(Quebert::Backend::Beanstalk)
|
12
12
|
# Blech, gross nastiness in their lib, but we need to look in to see if this stuff as configed
|
13
|
-
backend.instance_variable_get('@
|
14
|
-
|
13
|
+
pool = backend.instance_variable_get('@pool')
|
14
|
+
pool.connections.first.address.should eql('localhost:11300')
|
15
|
+
tube = backend.instance_variable_get('@tube')
|
16
|
+
tube.name.should eql('quebert-config-test')
|
15
17
|
end
|
16
18
|
|
17
19
|
end
|
data/spec/consumer_spec.rb
CHANGED
@@ -25,63 +25,63 @@ describe Controller::Beanstalk do
|
|
25
25
|
|
26
26
|
it "should delete job off queue after succesful run" do
|
27
27
|
@q.put Adder.new(1, 2)
|
28
|
-
@q.
|
28
|
+
@q.peek(:ready).should_not be_nil
|
29
29
|
@q.reserve.perform.should eql(3)
|
30
|
-
@q.
|
30
|
+
@q.peek(:ready).should be_nil
|
31
31
|
end
|
32
32
|
|
33
33
|
it "should bury job if an exception occurs in job" do
|
34
34
|
@q.put Exceptional.new
|
35
|
-
@q.
|
35
|
+
@q.peek(:ready).should_not be_nil
|
36
36
|
lambda{ @q.reserve.perform }.should raise_exception
|
37
|
-
@q.
|
37
|
+
@q.peek(:buried).should_not be_nil
|
38
38
|
end
|
39
39
|
|
40
40
|
it "should bury an AR job if an exception occurs deserializing it" do
|
41
41
|
@user = User.new(:first_name => "John", :last_name => "Doe", :email => "jdoe@gmail.com")
|
42
42
|
@user.id = 1
|
43
43
|
@q.put Serializer::ActiveRecord.serialize(@user)
|
44
|
-
@q.
|
44
|
+
@q.peek(:ready).should_not be_nil
|
45
45
|
lambda{ @q.reserve.perform }.should raise_exception
|
46
|
-
@q.
|
46
|
+
@q.peek(:buried).should_not be_nil
|
47
47
|
end
|
48
48
|
|
49
49
|
context "job actions" do
|
50
50
|
it "should delete job" do
|
51
51
|
@q.put DeleteJob.new
|
52
|
-
@q.
|
52
|
+
@q.peek(:ready).should_not be_nil
|
53
53
|
@q.reserve.perform
|
54
|
-
@q.
|
54
|
+
@q.peek(:ready).should be_nil
|
55
55
|
end
|
56
56
|
|
57
57
|
it "should release job" do
|
58
58
|
@q.put ReleaseJob.new
|
59
|
-
@q.
|
59
|
+
@q.peek(:ready).should_not be_nil
|
60
60
|
@q.reserve.perform
|
61
|
-
@q.
|
61
|
+
@q.peek(:ready).should_not be_nil
|
62
62
|
end
|
63
63
|
|
64
64
|
it "should bury job" do
|
65
65
|
@q.put BuryJob.new
|
66
|
-
@q.
|
67
|
-
@q.
|
66
|
+
@q.peek(:ready).should_not be_nil
|
67
|
+
@q.peek(:buried).should be_nil
|
68
68
|
@q.reserve.perform
|
69
|
-
@q.
|
70
|
-
@q.
|
69
|
+
@q.peek(:ready).should be_nil
|
70
|
+
@q.peek(:buried).should_not be_nil
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
74
|
it "should retry a job with a delay and then bury" do
|
75
75
|
TimeoutJob.backend = @q
|
76
76
|
TimeoutJob.new.enqueue
|
77
|
-
@q.
|
77
|
+
@q.peek(:ready).should_not be_nil
|
78
78
|
job = @q.reserve
|
79
79
|
job.beanstalk_job.stats["releases"].should eql(0)
|
80
80
|
job.beanstalk_job.stats["delay"].should eql(0)
|
81
81
|
lambda{job.perform}.should raise_exception(Quebert::Job::Timeout)
|
82
82
|
|
83
|
-
@q.
|
84
|
-
beanstalk_job = @q.
|
83
|
+
@q.peek(:ready).should be_nil
|
84
|
+
beanstalk_job = @q.peek(:delayed)
|
85
85
|
beanstalk_job.should_not be_nil
|
86
86
|
beanstalk_job.stats["releases"].should eql(1)
|
87
87
|
beanstalk_job.stats["delay"].should eql(Quebert::Controller::Beanstalk::TIMEOUT_RETRY_GROWTH_RATE**beanstalk_job.stats["releases"])
|
@@ -92,8 +92,8 @@ describe Controller::Beanstalk do
|
|
92
92
|
Quebert::Controller::Beanstalk::MAX_TIMEOUT_RETRY_DELAY = 1
|
93
93
|
lambda{@q.reserve.perform}.should raise_exception(Quebert::Job::Timeout)
|
94
94
|
|
95
|
-
@q.
|
96
|
-
@q.
|
97
|
-
@q.
|
95
|
+
@q.peek(:ready).should be_nil
|
96
|
+
@q.peek(:delayed).should be_nil
|
97
|
+
@q.peek(:buried).should_not be_nil
|
98
98
|
end
|
99
99
|
end
|
data/spec/worker_spec.rb
CHANGED
@@ -7,11 +7,11 @@ describe Worker do
|
|
7
7
|
w.backend = @q
|
8
8
|
end
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
it "should start" do
|
12
12
|
@w.start
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
context "pluggable exception handler" do
|
16
16
|
it "should raise exception if nothing is provided" do
|
17
17
|
@q.put Exceptional.new
|
@@ -20,15 +20,14 @@ describe Worker do
|
|
20
20
|
|
21
21
|
it "should default to Quebert.config.worker.exception_handler handler" do
|
22
22
|
@q.put Exceptional.new
|
23
|
-
Quebert.config.worker.exception_handler = Proc.new{|e| e.should be_instance_of(Exception) }
|
24
|
-
@w.exception_handler = Proc.new{|e| e.should be_instance_of(Exception) }
|
23
|
+
Quebert.config.worker.exception_handler = Proc.new{|e, opts| e.should be_instance_of(Exception) }
|
25
24
|
lambda{ @w.start }.should_not raise_exception
|
26
25
|
end
|
27
|
-
|
26
|
+
|
28
27
|
it "should intercept exceptions" do
|
29
28
|
@q.put Exceptional.new
|
30
|
-
@w.exception_handler = Proc.new{|e| e.should be_instance_of(Exception) }
|
29
|
+
@w.exception_handler = Proc.new{|e, opts| e.should be_instance_of(Exception) }
|
31
30
|
lambda{ @w.start }.should_not raise_exception
|
32
31
|
end
|
33
32
|
end
|
34
|
-
end
|
33
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quebert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 59
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 11
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.9
|
10
|
+
version: 1.11.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brad Gessler
|
@@ -17,7 +17,8 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2012-
|
20
|
+
date: 2012-12-21 00:00:00 -06:00
|
21
|
+
default_executable:
|
21
22
|
dependencies:
|
22
23
|
- !ruby/object:Gem::Dependency
|
23
24
|
name: json
|
@@ -34,7 +35,7 @@ dependencies:
|
|
34
35
|
type: :runtime
|
35
36
|
version_requirements: *id001
|
36
37
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
+
name: beaneater
|
38
39
|
prerelease: false
|
39
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
40
41
|
none: false
|
@@ -121,6 +122,7 @@ files:
|
|
121
122
|
- spec/support/jobs.rb
|
122
123
|
- spec/support_spec.rb
|
123
124
|
- spec/worker_spec.rb
|
125
|
+
has_rdoc: true
|
124
126
|
homepage: http://github.com/polleverywhere/quebert
|
125
127
|
licenses: []
|
126
128
|
|
@@ -150,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
152
|
requirements: []
|
151
153
|
|
152
154
|
rubyforge_project: quebert
|
153
|
-
rubygems_version: 1.
|
155
|
+
rubygems_version: 1.6.2
|
154
156
|
signing_key:
|
155
157
|
specification_version: 3
|
156
158
|
summary: A worker queue framework built around beanstalkd
|