boss_queue 0.1.10 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +17 -12
- data/VERSION +1 -1
- data/boss_queue.gemspec +1 -1
- data/lib/boss_queue/boss_queue.rb +28 -30
- data/lib/boss_queue/job.rb +5 -1
- data/spec/boss_queue_spec.rb +62 -45
- metadata +2 -2
data/README.md
CHANGED
@@ -19,21 +19,25 @@ boss_queue uses an Amazon SQS queue and a Amazon DynamoDB table for each environ
|
|
19
19
|
AWS.config(:access_key_id => <access_key_id>,
|
20
20
|
:secret_access_key => <secret_access_key>)
|
21
21
|
|
22
|
+
queue = BossQueue.new # default queue name
|
23
|
+
# or
|
24
|
+
queue = BossQueue.new(:queue => 'emails') # customized queue name (so you can have separate job queues)
|
25
|
+
|
22
26
|
BossQueue.environment = 'development'
|
23
|
-
|
24
|
-
|
27
|
+
queue.create_table
|
28
|
+
queue.create_queue
|
25
29
|
|
26
30
|
BossQueue.environment = 'staging'
|
27
|
-
|
28
|
-
|
31
|
+
queue.create_table
|
32
|
+
queue.create_queue
|
29
33
|
|
30
34
|
# BossQueue.create_table(read_capacity, write_capacity)
|
31
35
|
# One read capacity unit = two eventually consistent reads per second, for items up 4 KB in size.
|
32
36
|
# One write capacity unit = one write per second, for items up to 1 KB in size.
|
33
37
|
|
34
38
|
BossQueue.environment = 'production'
|
35
|
-
|
36
|
-
|
39
|
+
queue.create_table(50, 10)
|
40
|
+
queue.create_queue
|
37
41
|
|
38
42
|
|
39
43
|
Alternatively, in each of the respective environments, do:
|
@@ -55,18 +59,19 @@ Usage
|
|
55
59
|
=====
|
56
60
|
|
57
61
|
myobject = MyClass.new
|
58
|
-
|
62
|
+
# default failure action is 'retry' which retries up to four times
|
63
|
+
queue = BossQueue.new(:failure_action => 'none', :queue => 'emails')
|
59
64
|
|
60
65
|
# can enqueue instance methods (assumes that objects have an id and a #find(id) method)
|
61
|
-
|
66
|
+
queue.enqueue(myobject, :method_to_execute, arg1, arg2)
|
62
67
|
# enqueue with a delay of up to 900 seconds (15 minutes)
|
63
|
-
|
68
|
+
queue.enqueue_with_delay(60, myobject, :method_to_execute, arg1, arg2, arg3)
|
64
69
|
|
65
70
|
# can enqueue class methods
|
66
|
-
|
67
|
-
|
71
|
+
queue.enqueue(MyClass, :method_to_execute)
|
72
|
+
queue.enqueue_with_delay(60, MyClass, :method_to_execute, arg1, arg2)
|
68
73
|
|
69
|
-
|
74
|
+
queue.work
|
70
75
|
|
71
76
|
# failures are left in the DynamoDB table with the failed boolean set to true
|
72
77
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/boss_queue.gemspec
CHANGED
@@ -1,50 +1,48 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
3
|
class BossQueue
|
4
|
-
@@environment
|
4
|
+
@@environment = nil
|
5
5
|
|
6
|
-
def
|
7
|
-
|
6
|
+
def initialize(options={})
|
7
|
+
@failure_action = options[:failure_action] if options[:failure_action]
|
8
|
+
@queue_postfix = options[:queue] ? '_' + options[:queue] : ''
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
def self.failure_action
|
13
|
-
@@failure_action ||= 'retry'
|
11
|
+
def self.environment=(env)
|
12
|
+
@@environment = env
|
14
13
|
end
|
15
14
|
|
16
|
-
def
|
17
|
-
|
15
|
+
def failure_action
|
16
|
+
@failure_action ||= 'retry'
|
18
17
|
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
"#{self.queue_prefix}boss_queue_jobs"
|
19
|
+
def table_name
|
20
|
+
"#{BossQueue.queue_prefix}boss_queue_jobs"
|
23
21
|
end
|
24
22
|
|
25
|
-
def
|
26
|
-
"#{
|
23
|
+
def queue_name
|
24
|
+
"#{BossQueue.queue_prefix}boss_queue#{@queue_postfix}"
|
27
25
|
end
|
28
26
|
|
29
27
|
|
30
|
-
def
|
28
|
+
def create_table(read_capacity=1, write_capacity=1, options={})
|
31
29
|
create_opts = {}
|
32
30
|
create_opts[:hash_key] = { :id => :string }
|
33
31
|
|
34
|
-
AWS::DynamoDB.new.tables.create(
|
32
|
+
AWS::DynamoDB.new.tables.create(table_name, read_capacity, write_capacity, create_opts)
|
35
33
|
end
|
36
34
|
|
37
|
-
def
|
38
|
-
AWS::SQS::QueueCollection.new.create(
|
35
|
+
def create_queue
|
36
|
+
AWS::SQS::QueueCollection.new.create(queue_name, :default_visibility_timeout => 5 * 60)
|
39
37
|
end
|
40
38
|
|
41
|
-
def
|
39
|
+
def work
|
42
40
|
work_done = false
|
43
|
-
|
41
|
+
sqs_queue.receive_message do |job_id|
|
44
42
|
# When a block is given, each message is yielded to the block and then deleted as long as the block exits normally - http://docs.aws.amazon.com/AWSRubySDK/latest/frames.html
|
45
43
|
begin
|
46
44
|
job = BossQueue::Job.shard(table_name).find(job_id.body)
|
47
|
-
job.
|
45
|
+
job.sqs_queue = sqs_queue
|
48
46
|
job.work
|
49
47
|
work_done = true
|
50
48
|
rescue AWS::Record::RecordNotFound
|
@@ -53,17 +51,17 @@ class BossQueue
|
|
53
51
|
work_done
|
54
52
|
end
|
55
53
|
|
56
|
-
def
|
57
|
-
job =
|
54
|
+
def enqueue(class_or_instance, method_name, *args)
|
55
|
+
job = create_job(class_or_instance, method_name, *args)
|
58
56
|
job.enqueue
|
59
57
|
end
|
60
58
|
|
61
|
-
def
|
62
|
-
job =
|
59
|
+
def enqueue_with_delay(delay, class_or_instance, method_name, *args)
|
60
|
+
job = create_job(class_or_instance, method_name, *args)
|
63
61
|
job.enqueue_with_delay(delay)
|
64
62
|
end
|
65
63
|
|
66
|
-
def
|
64
|
+
def create_job(class_or_instance, method_name, *args) # :nodoc:
|
67
65
|
job = BossQueue::Job.shard(table_name).new
|
68
66
|
if class_or_instance.is_a?(Class)
|
69
67
|
class_name = class_or_instance.to_s
|
@@ -74,8 +72,8 @@ class BossQueue
|
|
74
72
|
instance_id = class_or_instance.id
|
75
73
|
job.kind = "#{class_name}##{method_name}"
|
76
74
|
end
|
77
|
-
job.queue_name =
|
78
|
-
job.failure_action =
|
75
|
+
job.queue_name = queue_name
|
76
|
+
job.failure_action = failure_action
|
79
77
|
job.model_class_name = class_name
|
80
78
|
job.model_id = instance_id unless instance_id.nil?
|
81
79
|
job.job_method = method_name.to_s
|
@@ -84,8 +82,8 @@ class BossQueue
|
|
84
82
|
job
|
85
83
|
end
|
86
84
|
|
87
|
-
def
|
88
|
-
AWS::SQS.new.queues[AWS::SQS.new.queues.url_for(
|
85
|
+
def sqs_queue # :nodoc:
|
86
|
+
@sqs_queue ||= AWS::SQS.new.queues[AWS::SQS.new.queues.url_for(queue_name)]
|
89
87
|
end
|
90
88
|
|
91
89
|
def self.environment # :nodoc:
|
data/lib/boss_queue/job.rb
CHANGED
@@ -66,10 +66,14 @@ class BossQueue
|
|
66
66
|
60 * 2**(failed_attempts - 1)
|
67
67
|
end
|
68
68
|
|
69
|
+
def sqs_queue=(queue_obj) # :nodoc:
|
70
|
+
@sqs_queue = queue_obj
|
71
|
+
end
|
72
|
+
|
69
73
|
private
|
70
74
|
|
71
75
|
def sqs_queue
|
72
|
-
AWS::SQS.new.queues[AWS::SQS.new.queues.url_for(queue_name)]
|
76
|
+
@sqs_queue ||= AWS::SQS.new.queues[AWS::SQS.new.queues.url_for(queue_name)]
|
73
77
|
end
|
74
78
|
|
75
79
|
# from ActiveSupport source: http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-constantize
|
data/spec/boss_queue_spec.rb
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe "BossQueue module" do
|
4
|
+
before(:each) do
|
5
|
+
BossQueue.environment = 'test'
|
6
|
+
|
7
|
+
BossQueue::Job.any_instance.stub(:kind=)
|
8
|
+
BossQueue::Job.any_instance.stub(:queue_name=)
|
9
|
+
BossQueue::Job.any_instance.stub(:failure_action=)
|
10
|
+
BossQueue::Job.any_instance.stub(:model_class_name=)
|
11
|
+
BossQueue::Job.any_instance.stub(:model_id=)
|
12
|
+
BossQueue::Job.any_instance.stub(:job_method=)
|
13
|
+
BossQueue::Job.any_instance.stub(:job_arguments=)
|
14
|
+
BossQueue::Job.any_instance.stub(:save!)
|
15
|
+
BossQueue::Job.any_instance.stub(:enqueue)
|
16
|
+
end
|
4
17
|
|
5
18
|
it "should respond to environment" do
|
6
19
|
BossQueue.should respond_to(:environment)
|
@@ -10,17 +23,13 @@ describe "BossQueue module" do
|
|
10
23
|
BossQueue.should respond_to(:environment=)
|
11
24
|
end
|
12
25
|
|
13
|
-
it "should respond to failure_action" do
|
14
|
-
BossQueue.should respond_to(:failure_action)
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should respond to failure_action=" do
|
18
|
-
BossQueue.should respond_to(:failure_action=)
|
19
|
-
end
|
20
|
-
|
21
26
|
describe "#failure_action" do
|
22
27
|
it "should default to 'retry'" do
|
23
|
-
BossQueue.failure_action.should == 'retry'
|
28
|
+
BossQueue.new.failure_action.should == 'retry'
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should be overridable by a :failure_action option on initialize" do
|
32
|
+
BossQueue.new(:failure_action => 'none').failure_action.should == 'none'
|
24
33
|
end
|
25
34
|
end
|
26
35
|
|
@@ -32,35 +41,35 @@ describe "BossQueue module" do
|
|
32
41
|
context "when @@environment is 'development'" do
|
33
42
|
it "should be 'dev_boss_queue_jobs'" do
|
34
43
|
BossQueue.environment = 'development'
|
35
|
-
BossQueue.table_name.should == 'dev_boss_queue_jobs'
|
44
|
+
BossQueue.new.table_name.should == 'dev_boss_queue_jobs'
|
36
45
|
end
|
37
46
|
end
|
38
47
|
|
39
48
|
context "when @@environment is 'production'" do
|
40
49
|
it "should be 'boss_queue_jobs'" do
|
41
50
|
BossQueue.environment = 'production'
|
42
|
-
BossQueue.table_name.should == 'boss_queue_jobs'
|
51
|
+
BossQueue.new.table_name.should == 'boss_queue_jobs'
|
43
52
|
end
|
44
53
|
end
|
45
54
|
|
46
55
|
context "when @@environment is 'staging'" do
|
47
56
|
it "should be 'staging_boss_queue_jobs'" do
|
48
57
|
BossQueue.environment = 'staging'
|
49
|
-
BossQueue.table_name.should == 'staging_boss_queue_jobs'
|
58
|
+
BossQueue.new.table_name.should == 'staging_boss_queue_jobs'
|
50
59
|
end
|
51
60
|
end
|
52
61
|
|
53
62
|
context "when @@environment is 'staging'" do
|
54
63
|
it "should be 'staging_boss_queue_jobs'" do
|
55
64
|
BossQueue.environment = 'staging'
|
56
|
-
BossQueue.table_name.should == 'staging_boss_queue_jobs'
|
65
|
+
BossQueue.new.table_name.should == 'staging_boss_queue_jobs'
|
57
66
|
end
|
58
67
|
end
|
59
68
|
|
60
69
|
context "when @@environment is nil" do
|
61
70
|
it "should raise an exception" do
|
62
71
|
lambda {
|
63
|
-
BossQueue.table_name
|
72
|
+
BossQueue.new.table_name
|
64
73
|
}.should raise_error
|
65
74
|
end
|
66
75
|
end
|
@@ -75,38 +84,45 @@ describe "BossQueue module" do
|
|
75
84
|
context "when @@environment is 'development'" do
|
76
85
|
it "should be 'dev_boss_queue'" do
|
77
86
|
BossQueue.environment = 'development'
|
78
|
-
BossQueue.queue_name.should == 'dev_boss_queue'
|
87
|
+
BossQueue.new.queue_name.should == 'dev_boss_queue'
|
79
88
|
end
|
80
89
|
end
|
81
90
|
|
82
91
|
context "when @@environment is 'production'" do
|
83
92
|
it "should be 'boss_queue'" do
|
84
93
|
BossQueue.environment = 'production'
|
85
|
-
BossQueue.queue_name.should == 'boss_queue'
|
94
|
+
BossQueue.new.queue_name.should == 'boss_queue'
|
86
95
|
end
|
87
96
|
end
|
88
97
|
|
89
98
|
context "when @@environment is 'staging'" do
|
90
99
|
it "should be 'staging_boss_queue'" do
|
91
100
|
BossQueue.environment = 'staging'
|
92
|
-
BossQueue.queue_name.should == 'staging_boss_queue'
|
101
|
+
BossQueue.new.queue_name.should == 'staging_boss_queue'
|
93
102
|
end
|
94
103
|
end
|
95
104
|
|
96
105
|
context "when @@environment is 'staging'" do
|
97
106
|
it "should be 'staging_boss_queue'" do
|
98
107
|
BossQueue.environment = 'staging'
|
99
|
-
BossQueue.queue_name.should == 'staging_boss_queue'
|
108
|
+
BossQueue.new.queue_name.should == 'staging_boss_queue'
|
100
109
|
end
|
101
110
|
end
|
102
111
|
|
103
112
|
context "when @@environment is nil" do
|
104
113
|
it "should raise an exception" do
|
105
114
|
lambda {
|
106
|
-
BossQueue.queue_name
|
115
|
+
BossQueue.new.queue_name
|
107
116
|
}.should raise_error
|
108
117
|
end
|
109
118
|
end
|
119
|
+
|
120
|
+
context "when a queue option is included in the initializer" do
|
121
|
+
it "should append that to the queue name" do
|
122
|
+
BossQueue.environment = 'production'
|
123
|
+
BossQueue.new(:queue => 'emails').queue_name.should == 'boss_queue_emails'
|
124
|
+
end
|
125
|
+
end
|
110
126
|
end
|
111
127
|
|
112
128
|
describe "#enqueue" do
|
@@ -129,8 +145,7 @@ describe "BossQueue module" do
|
|
129
145
|
|
130
146
|
context "when a class" do
|
131
147
|
it "should initialize a new BossQueue::Job object, save and call enqueue on it" do
|
132
|
-
|
133
|
-
BossQueue.failure_action = 'retry'
|
148
|
+
queue = BossQueue.new
|
134
149
|
BossQueue::Job.any_instance.should_receive(:kind=).with('TestClass@test_class_method')
|
135
150
|
BossQueue::Job.any_instance.should_receive(:queue_name=).with('test_boss_queue')
|
136
151
|
BossQueue::Job.any_instance.should_receive(:failure_action=).with('retry')
|
@@ -140,14 +155,13 @@ describe "BossQueue module" do
|
|
140
155
|
BossQueue::Job.any_instance.should_receive(:job_arguments=).with(@argument_json)
|
141
156
|
BossQueue::Job.any_instance.should_receive(:save!)
|
142
157
|
BossQueue::Job.any_instance.should_receive(:enqueue)
|
143
|
-
|
158
|
+
queue.enqueue(TestClass, :test_class_method, 'a', 'b', { 'c' => 2, 'd' => 1 })
|
144
159
|
end
|
145
160
|
end
|
146
161
|
|
147
162
|
context "when a class instance" do
|
148
163
|
it "should initialize a new BossQueue::Job object, save and call enqueue on it" do
|
149
|
-
|
150
|
-
BossQueue.failure_action = 'retry'
|
164
|
+
queue = BossQueue.new
|
151
165
|
BossQueue::Job.any_instance.should_receive(:kind=).with('TestClass#test_instance_method')
|
152
166
|
BossQueue::Job.any_instance.should_receive(:queue_name=).with('test_boss_queue')
|
153
167
|
BossQueue::Job.any_instance.should_receive(:failure_action=).with('retry')
|
@@ -157,7 +171,7 @@ describe "BossQueue module" do
|
|
157
171
|
BossQueue::Job.any_instance.should_receive(:job_arguments=).with(@argument_json)
|
158
172
|
BossQueue::Job.any_instance.should_receive(:save!)
|
159
173
|
BossQueue::Job.any_instance.should_receive(:enqueue)
|
160
|
-
|
174
|
+
queue.enqueue(TestClass.new, :test_instance_method, 'a', 'b', { 'c' => 2, 'd' => 1 })
|
161
175
|
end
|
162
176
|
end
|
163
177
|
|
@@ -171,8 +185,7 @@ describe "BossQueue module" do
|
|
171
185
|
|
172
186
|
context "when a class" do
|
173
187
|
it "should initialize a new BossQueue::Job object, save and call enqueue on it" do
|
174
|
-
|
175
|
-
BossQueue.failure_action = 'retry'
|
188
|
+
queue = BossQueue.new
|
176
189
|
BossQueue::Job.any_instance.should_receive(:kind=).with('TestClass@test_class_method')
|
177
190
|
BossQueue::Job.any_instance.should_receive(:queue_name=).with('test_boss_queue')
|
178
191
|
BossQueue::Job.any_instance.should_receive(:failure_action=).with('retry')
|
@@ -182,14 +195,13 @@ describe "BossQueue module" do
|
|
182
195
|
BossQueue::Job.any_instance.should_receive(:job_arguments=).with(@argument_json)
|
183
196
|
BossQueue::Job.any_instance.should_receive(:save!)
|
184
197
|
BossQueue::Job.any_instance.should_receive(:enqueue_with_delay).with(60)
|
185
|
-
|
198
|
+
queue.enqueue_with_delay(60, TestClass, :test_class_method, 'a', 'b', { 'c' => 2, 'd' => 1 })
|
186
199
|
end
|
187
200
|
end
|
188
201
|
|
189
202
|
context "when a class instance" do
|
190
203
|
it "should initialize a new BossQueue::Job object, save and call enqueue on it" do
|
191
|
-
|
192
|
-
BossQueue.failure_action = 'retry'
|
204
|
+
queue = BossQueue.new
|
193
205
|
BossQueue::Job.any_instance.should_receive(:kind=).with('TestClass#test_instance_method')
|
194
206
|
BossQueue::Job.any_instance.should_receive(:queue_name=).with('test_boss_queue')
|
195
207
|
BossQueue::Job.any_instance.should_receive(:failure_action=).with('retry')
|
@@ -199,7 +211,7 @@ describe "BossQueue module" do
|
|
199
211
|
BossQueue::Job.any_instance.should_receive(:job_arguments=).with(@argument_json)
|
200
212
|
BossQueue::Job.any_instance.should_receive(:save!)
|
201
213
|
BossQueue::Job.any_instance.should_receive(:enqueue_with_delay).with(60)
|
202
|
-
|
214
|
+
queue.enqueue_with_delay(60, TestClass.new, :test_instance_method, 'a', 'b', { 'c' => 2, 'd' => 1 })
|
203
215
|
end
|
204
216
|
end
|
205
217
|
|
@@ -207,59 +219,64 @@ describe "BossQueue module" do
|
|
207
219
|
|
208
220
|
describe "#work" do
|
209
221
|
before(:each) do
|
210
|
-
@
|
222
|
+
@sqs_queue = double('queue')
|
211
223
|
AWS::SQS.stub_chain(:new, :queues, :url_for).and_return('queue_url')
|
212
|
-
AWS::SQS.stub_chain(:new, :queues, :[]).and_return(@
|
224
|
+
AWS::SQS.stub_chain(:new, :queues, :[]).and_return(@sqs_queue)
|
213
225
|
|
214
226
|
@sqs_message = double('message')
|
215
227
|
@sqs_message.stub(:body).and_return('ijk')
|
216
|
-
@
|
228
|
+
@sqs_queue.stub(:receive_message)
|
217
229
|
|
218
230
|
@job = double('job')
|
219
231
|
@job.stub(:work)
|
220
|
-
@job.stub(:
|
232
|
+
@job.stub(:sqs_queue=)
|
221
233
|
BossQueue::Job.stub_chain(:shard, :find).and_return(@job)
|
222
234
|
end
|
223
235
|
|
224
|
-
it "should dequeue from SQS" do
|
225
|
-
@
|
226
|
-
BossQueue.work
|
236
|
+
it "should dequeue from SQS using the value of sqs_queue_url" do
|
237
|
+
@sqs_queue.should_receive(:receive_message).and_yield(@sqs_message)
|
238
|
+
BossQueue.new.work
|
227
239
|
end
|
228
240
|
|
229
241
|
context "when something is dequeued from SQS" do
|
230
242
|
before(:each) do
|
231
|
-
@
|
243
|
+
@sqs_queue.should_receive(:receive_message).and_yield(@sqs_message)
|
232
244
|
end
|
233
245
|
|
234
246
|
it "should use the dequeued id to retrieve a BossQueue::Job object" do
|
235
247
|
shard = double('shard')
|
236
|
-
BossQueue::Job.should_receive(:shard).with(BossQueue.table_name).and_return(shard)
|
248
|
+
BossQueue::Job.should_receive(:shard).with(BossQueue.new.table_name).and_return(shard)
|
237
249
|
shard.should_receive(:find).with('ijk').and_return(@job)
|
238
|
-
BossQueue.work
|
250
|
+
BossQueue.new.work
|
239
251
|
end
|
240
252
|
|
241
253
|
context "when the dequeued id does not match a BossQueue::Job object" do
|
242
254
|
it "should not raise an exception" do
|
243
255
|
BossQueue::Job.stub_chain(:shard, :find).and_raise(AWS::Record::RecordNotFound.new)
|
244
256
|
lambda {
|
245
|
-
BossQueue.work
|
257
|
+
BossQueue.new.work
|
246
258
|
}.should_not raise_error
|
247
259
|
end
|
248
260
|
end
|
249
261
|
|
262
|
+
it "should set the sqs_queue of the job since we already did the work of retrieving it's url" do
|
263
|
+
@job.should_receive(:sqs_queue=).with(@sqs_queue)
|
264
|
+
BossQueue.new.work
|
265
|
+
end
|
266
|
+
|
250
267
|
it "should call work on the BossQueue::Job object" do
|
251
268
|
@job.should_receive(:work)
|
252
|
-
BossQueue.work
|
269
|
+
BossQueue.new.work
|
253
270
|
end
|
254
271
|
|
255
272
|
it "should return true" do
|
256
|
-
BossQueue.work.should be_true
|
273
|
+
BossQueue.new.work.should be_true
|
257
274
|
end
|
258
275
|
end
|
259
276
|
|
260
277
|
context "when nothing is dequeued from SQS" do
|
261
278
|
it "should return false" do
|
262
|
-
BossQueue.work.should be_false
|
279
|
+
BossQueue.new.work.should be_false
|
263
280
|
end
|
264
281
|
end
|
265
282
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boss_queue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -160,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
160
160
|
version: '0'
|
161
161
|
segments:
|
162
162
|
- 0
|
163
|
-
hash:
|
163
|
+
hash: 539574413423499853
|
164
164
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
165
|
none: false
|
166
166
|
requirements:
|