sidekiq 2.12.0 → 2.12.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- data/Changes.md +13 -0
- data/Pro-Changes.md +1 -1
- data/README.md +1 -1
- data/lib/sidekiq/api.rb +26 -6
- data/lib/sidekiq/client.rb +7 -3
- data/lib/sidekiq/exception_handler.rb +1 -1
- data/lib/sidekiq/scheduled.rb +2 -5
- data/lib/sidekiq/testing.rb +9 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +16 -0
- data/sidekiq.gemspec +1 -1
- data/test/test_api.rb +16 -7
- data/test/test_exception_handler.rb +7 -3
- data/test/test_scheduled.rb +63 -24
- data/test/test_testing.rb +17 -0
- data/test/test_web.rb +0 -1
- data/web/locales/en.yml +1 -0
- data/web/locales/pt-br.yml +1 -0
- data/web/views/retry.slim +5 -0
- metadata +4 -4
data/Changes.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
2.12.1
|
2
|
+
-----------
|
3
|
+
|
4
|
+
- Force Celluloid 0.14.1 as 0.14.0 has a serious bug. [#954]
|
5
|
+
- Scheduled and Retry jobs now use Sidekiq::Client to push
|
6
|
+
jobs onto the queue, so they use client middleware. [dimko, #948]
|
7
|
+
- Record the timestamp when jobs are enqueued. Add
|
8
|
+
Sidekiq::Job#enqueued\_at to query the time. [mariovisic, #944]
|
9
|
+
- Add Sidekiq::Queue#latency - calculates diff between now and
|
10
|
+
enqueued\_at for the oldest job in the queue.
|
11
|
+
- Add testing method `perform_one` that dequeues and performs a single job.
|
12
|
+
This is mainly to aid testing jobs that spawn other jobs. [fumin, #963]
|
13
|
+
|
1
14
|
2.12.0
|
2
15
|
-----------
|
3
16
|
|
data/Pro-Changes.md
CHANGED
data/README.md
CHANGED
data/lib/sidekiq/api.rb
CHANGED
@@ -128,6 +128,14 @@ module Sidekiq
|
|
128
128
|
Sidekiq.redis { |con| con.llen(@rname) }
|
129
129
|
end
|
130
130
|
|
131
|
+
def latency
|
132
|
+
entry = Sidekiq.redis do |conn|
|
133
|
+
conn.lrange(@rname, -1, -1)
|
134
|
+
end.first
|
135
|
+
return 0 unless entry
|
136
|
+
Time.now.to_f - Sidekiq.load_json(entry)['enqueued_at']
|
137
|
+
end
|
138
|
+
|
131
139
|
def each(&block)
|
132
140
|
page = 0
|
133
141
|
page_size = 50
|
@@ -186,10 +194,18 @@ module Sidekiq
|
|
186
194
|
@item['jid']
|
187
195
|
end
|
188
196
|
|
197
|
+
def enqueued_at
|
198
|
+
Time.at(@item['enqueued_at'])
|
199
|
+
end
|
200
|
+
|
189
201
|
def queue
|
190
202
|
@queue
|
191
203
|
end
|
192
204
|
|
205
|
+
def latency
|
206
|
+
Time.now.to_f - @item['enqueued_at']
|
207
|
+
end
|
208
|
+
|
193
209
|
##
|
194
210
|
# Remove this job from the queue.
|
195
211
|
def delete
|
@@ -234,7 +250,7 @@ module Sidekiq
|
|
234
250
|
results.map do |message|
|
235
251
|
msg = Sidekiq.load_json(message)
|
236
252
|
msg['retry_count'] = msg['retry_count'] - 1
|
237
|
-
|
253
|
+
Sidekiq::Client.push(msg)
|
238
254
|
end
|
239
255
|
end
|
240
256
|
end
|
@@ -372,15 +388,16 @@ module Sidekiq
|
|
372
388
|
# WARNING WARNING WARNING
|
373
389
|
#
|
374
390
|
# This is live data that can change every millisecond.
|
375
|
-
# If you
|
391
|
+
# If you call #size => 5 and then expect #each to be
|
376
392
|
# called 5 times, you're going to have a bad time.
|
377
393
|
#
|
378
394
|
# workers = Sidekiq::Workers.new
|
379
395
|
# workers.size => 2
|
380
|
-
# workers.each do |name, work|
|
381
|
-
# # name is a unique identifier per
|
396
|
+
# workers.each do |name, work, started_at|
|
397
|
+
# # name is a unique identifier per worker
|
382
398
|
# # work is a Hash which looks like:
|
383
399
|
# # { 'queue' => name, 'run_at' => timestamp, 'payload' => msg }
|
400
|
+
# # started_at is a String rep of the time when the worker started working on the job
|
384
401
|
# end
|
385
402
|
|
386
403
|
class Workers
|
@@ -390,9 +407,12 @@ module Sidekiq
|
|
390
407
|
Sidekiq.redis do |conn|
|
391
408
|
workers = conn.smembers("workers")
|
392
409
|
workers.each do |w|
|
393
|
-
msg = conn.
|
410
|
+
msg, time = conn.multi do
|
411
|
+
conn.get("worker:#{w}")
|
412
|
+
conn.get("worker:#{w}:started")
|
413
|
+
end
|
394
414
|
next unless msg
|
395
|
-
block.call(w, Sidekiq.load_json(msg))
|
415
|
+
block.call(w, Sidekiq.load_json(msg), time)
|
396
416
|
end
|
397
417
|
end
|
398
418
|
end
|
data/lib/sidekiq/client.rb
CHANGED
@@ -62,7 +62,7 @@ module Sidekiq
|
|
62
62
|
normed = normalize_item(items)
|
63
63
|
payloads = items['args'].map do |args|
|
64
64
|
raise ArgumentError, "Bulk arguments must be an Array of Arrays: [[1], [2]]" if !args.is_a?(Array)
|
65
|
-
process_single(items['class'], normed.merge('args' => args, 'jid' => SecureRandom.hex(12)))
|
65
|
+
process_single(items['class'], normed.merge('args' => args, 'jid' => SecureRandom.hex(12), 'enqueued_at' => Time.now.to_f))
|
66
66
|
end.compact
|
67
67
|
|
68
68
|
pushed = false
|
@@ -94,7 +94,10 @@ module Sidekiq
|
|
94
94
|
pushed = false
|
95
95
|
Sidekiq.redis do |conn|
|
96
96
|
if payloads.first['at']
|
97
|
-
pushed = conn.zadd('schedule', payloads.map
|
97
|
+
pushed = conn.zadd('schedule', payloads.map do |hash|
|
98
|
+
at = hash.delete('at').to_s
|
99
|
+
[at, Sidekiq.dump_json(hash)]
|
100
|
+
end)
|
98
101
|
else
|
99
102
|
q = payloads.first['queue']
|
100
103
|
to_push = payloads.map { |entry| Sidekiq.dump_json(entry) }
|
@@ -129,7 +132,8 @@ module Sidekiq
|
|
129
132
|
normalized_item = Sidekiq::Worker::ClassMethods::DEFAULT_OPTIONS.merge(item)
|
130
133
|
end
|
131
134
|
|
132
|
-
normalized_item['jid']
|
135
|
+
normalized_item['jid'] ||= SecureRandom.hex(12)
|
136
|
+
normalized_item['enqueued_at'] = Time.now.to_f
|
133
137
|
normalized_item
|
134
138
|
end
|
135
139
|
|
@@ -33,7 +33,7 @@ module Sidekiq
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def send_to_exception_notifier(msg, ex)
|
36
|
-
::ExceptionNotifier.
|
36
|
+
::ExceptionNotifier::Notifier.background_exception_notification(ex, :data => { :message => msg }).deliver
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
data/lib/sidekiq/scheduled.rb
CHANGED
@@ -33,15 +33,12 @@ module Sidekiq
|
|
33
33
|
# going wrong between the time jobs are popped from the scheduled queue and when
|
34
34
|
# they are pushed onto a work queue and losing the jobs.
|
35
35
|
while message = conn.zrangebyscore(sorted_set, '-inf', now, :limit => [0, 1]).first do
|
36
|
-
|
36
|
+
|
37
37
|
# Pop item off the queue and add it to the work queue. If the job can't be popped from
|
38
38
|
# the queue, it's because another process already popped it so we can move on to the
|
39
39
|
# next one.
|
40
40
|
if conn.zrem(sorted_set, message)
|
41
|
-
|
42
|
-
conn.sadd('queues', msg['queue'])
|
43
|
-
conn.lpush("queue:#{msg['queue']}", message)
|
44
|
-
end
|
41
|
+
Sidekiq::Client.push(Sidekiq.load_json(message))
|
45
42
|
logger.debug { "enqueued #{sorted_set}: #{message}" }
|
46
43
|
end
|
47
44
|
end
|
data/lib/sidekiq/testing.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Sidekiq
|
2
2
|
|
3
|
+
class EmptyQueueError < RuntimeError; end
|
4
|
+
|
3
5
|
class Client
|
4
6
|
class << self
|
5
7
|
alias_method :raw_push_old, :raw_push
|
@@ -87,6 +89,13 @@ module Sidekiq
|
|
87
89
|
new.perform(*job['args'])
|
88
90
|
end
|
89
91
|
end
|
92
|
+
|
93
|
+
# Pop out a single job and perform it
|
94
|
+
def perform_one
|
95
|
+
raise(EmptyQueueError, "perform_one called with empty job queue") if jobs.empty?
|
96
|
+
job = jobs.shift
|
97
|
+
new.perform(*job['args'])
|
98
|
+
end
|
90
99
|
end
|
91
100
|
|
92
101
|
class << self
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -2,6 +2,8 @@ require 'yaml'
|
|
2
2
|
require 'sinatra/base'
|
3
3
|
require 'slim'
|
4
4
|
|
5
|
+
raise "The Sidekiq Web UI requires slim 1.3.8 or greater. You have slim v#{Slim::VERSION}" if Gem::Version.new(Slim::VERSION) < Gem::Version.new('1.3.8')
|
6
|
+
|
5
7
|
require 'sidekiq'
|
6
8
|
require 'sidekiq/api'
|
7
9
|
require 'sidekiq/paginator'
|
@@ -105,6 +107,20 @@ module Sidekiq
|
|
105
107
|
args.map { |arg| a = arg.inspect; a.size > count ? "#{a[0..count]}..." : a }.join(", ")
|
106
108
|
end
|
107
109
|
|
110
|
+
RETRY_JOB_KEYS = Set.new(%w(
|
111
|
+
queue class args retry_count retried_at failed_at
|
112
|
+
jid error_message error_class backtrace
|
113
|
+
error_backtrace enqueued_at
|
114
|
+
))
|
115
|
+
|
116
|
+
def retry_extra_items(retry_job)
|
117
|
+
@retry_extra_items ||= {}.tap do |extra|
|
118
|
+
retry_job.item.each do |key, value|
|
119
|
+
extra[key] = value unless RETRY_JOB_KEYS.include?(key)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
108
124
|
def tabs
|
109
125
|
@tabs ||= {
|
110
126
|
"Dashboard" => '',
|
data/sidekiq.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.add_dependency 'redis', '>= 3.0'
|
18
18
|
gem.add_dependency 'redis-namespace'
|
19
19
|
gem.add_dependency 'connection_pool', '>= 1.0.0'
|
20
|
-
gem.add_dependency 'celluloid', '>= 0.14.
|
20
|
+
gem.add_dependency 'celluloid', '>= 0.14.1'
|
21
21
|
gem.add_dependency 'json'
|
22
22
|
gem.add_development_dependency 'sinatra'
|
23
23
|
gem.add_development_dependency 'slim'
|
data/test/test_api.rb
CHANGED
@@ -164,6 +164,7 @@ class TestApi < Minitest::Test
|
|
164
164
|
it 'shows queue as empty' do
|
165
165
|
q = Sidekiq::Queue.new
|
166
166
|
assert_equal 0, q.size
|
167
|
+
assert_equal 0, q.latency
|
167
168
|
end
|
168
169
|
|
169
170
|
class ApiWorker
|
@@ -172,12 +173,18 @@ class TestApi < Minitest::Test
|
|
172
173
|
|
173
174
|
it 'can enumerate jobs' do
|
174
175
|
q = Sidekiq::Queue.new
|
175
|
-
|
176
|
-
|
176
|
+
Time.stub(:now, Time.new(2012, 12, 26)) do
|
177
|
+
ApiWorker.perform_async(1, 'mike')
|
178
|
+
assert_equal ['TestApi::ApiWorker'], q.map(&:klass)
|
179
|
+
|
180
|
+
job = q.first
|
181
|
+
assert_equal 24, job.jid.size
|
182
|
+
assert_equal [1, 'mike'], job.args
|
183
|
+
assert_equal Time.new(2012, 12, 26), job.enqueued_at
|
177
184
|
|
178
|
-
|
179
|
-
|
180
|
-
|
185
|
+
end
|
186
|
+
|
187
|
+
assert q.latency > 10_000_000
|
181
188
|
|
182
189
|
q = Sidekiq::Queue.new('other')
|
183
190
|
assert_equal 0, q.size
|
@@ -192,11 +199,11 @@ class TestApi < Minitest::Test
|
|
192
199
|
end
|
193
200
|
|
194
201
|
it 'can find job by id in sorted sets' do
|
195
|
-
q = Sidekiq::Queue.new
|
196
202
|
job_id = ApiWorker.perform_in(100, 1, 'jason')
|
197
203
|
job = Sidekiq::ScheduledSet.new.find_job(job_id)
|
198
204
|
refute_nil job
|
199
205
|
assert_equal job_id, job.jid
|
206
|
+
assert_in_delta job.latency, 0.0, 0.01
|
200
207
|
end
|
201
208
|
|
202
209
|
it 'can find job by id in queues' do
|
@@ -310,13 +317,15 @@ class TestApi < Minitest::Test
|
|
310
317
|
c.multi do
|
311
318
|
c.sadd('workers', s)
|
312
319
|
c.set("worker:#{s}", data)
|
320
|
+
c.set("worker:#{s}:started", Time.now.to_s)
|
313
321
|
end
|
314
322
|
end
|
315
323
|
|
316
324
|
assert_equal 1, w.size
|
317
|
-
w.each do |x, y|
|
325
|
+
w.each do |x, y, z|
|
318
326
|
assert_equal s, x
|
319
327
|
assert_equal 'default', y['queue']
|
328
|
+
assert_equal Time.now.year, DateTime.parse(z).year
|
320
329
|
end
|
321
330
|
end
|
322
331
|
|
@@ -73,7 +73,8 @@ class TestExceptionHandler < Minitest::Test
|
|
73
73
|
|
74
74
|
describe "with fake ExceptionNotifier" do
|
75
75
|
before do
|
76
|
-
::ExceptionNotifier =
|
76
|
+
::ExceptionNotifier = Module.new
|
77
|
+
::ExceptionNotifier::Notifier = MiniTest::Mock.new
|
77
78
|
end
|
78
79
|
|
79
80
|
after do
|
@@ -81,9 +82,12 @@ class TestExceptionHandler < Minitest::Test
|
|
81
82
|
end
|
82
83
|
|
83
84
|
it "notifies ExceptionNotifier" do
|
84
|
-
::
|
85
|
+
mail = MiniTest::Mock.new
|
86
|
+
mail.expect(:deliver,nil)
|
87
|
+
::ExceptionNotifier::Notifier.expect(:background_exception_notification,mail,[TEST_EXCEPTION, :data => { :message => { :b => 2 } }])
|
85
88
|
Component.new.invoke_exception(:b => 2)
|
86
|
-
::ExceptionNotifier.verify
|
89
|
+
::ExceptionNotifier::Notifier.verify
|
90
|
+
mail.verify
|
87
91
|
end
|
88
92
|
end
|
89
93
|
|
data/test/test_scheduled.rb
CHANGED
@@ -14,33 +14,72 @@ class TestScheduled < Minitest::Test
|
|
14
14
|
Sidekiq.redis do |conn|
|
15
15
|
conn.flushdb
|
16
16
|
end
|
17
|
+
|
18
|
+
@error_1 = { 'class' => ScheduledWorker.name, 'args' => [0], 'queue' => 'queue_1' }
|
19
|
+
@error_2 = { 'class' => ScheduledWorker.name, 'args' => [1], 'queue' => 'queue_2' }
|
20
|
+
@error_3 = { 'class' => ScheduledWorker.name, 'args' => [2], 'queue' => 'queue_3' }
|
21
|
+
@future_1 = { 'class' => ScheduledWorker.name, 'args' => [3], 'queue' => 'queue_4' }
|
22
|
+
@future_2 = { 'class' => ScheduledWorker.name, 'args' => [4], 'queue' => 'queue_5' }
|
23
|
+
@future_3 = { 'class' => ScheduledWorker.name, 'args' => [5], 'queue' => 'queue_6' }
|
24
|
+
|
25
|
+
@retry = Sidekiq::RetrySet.new
|
26
|
+
@scheduled = Sidekiq::ScheduledSet.new
|
27
|
+
@poller = Sidekiq::Scheduled::Poller.new
|
28
|
+
end
|
29
|
+
|
30
|
+
class Stopper
|
31
|
+
def call(worker_class, message, queue)
|
32
|
+
yield if message['args'].first.odd?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'executes client middleware' do
|
37
|
+
Sidekiq.client_middleware.add Stopper
|
38
|
+
begin
|
39
|
+
@retry.schedule (Time.now - 60).to_f, @error_1
|
40
|
+
@retry.schedule (Time.now - 60).to_f, @error_2
|
41
|
+
@scheduled.schedule (Time.now - 60).to_f, @future_2
|
42
|
+
@scheduled.schedule (Time.now - 60).to_f, @future_3
|
43
|
+
|
44
|
+
@poller.poll
|
45
|
+
|
46
|
+
Sidekiq.redis do |conn|
|
47
|
+
assert_equal 0, conn.llen("queue:queue_1")
|
48
|
+
assert_equal 1, conn.llen("queue:queue_2")
|
49
|
+
assert_equal 0, conn.llen("queue:queue_5")
|
50
|
+
assert_equal 1, conn.llen("queue:queue_6")
|
51
|
+
end
|
52
|
+
ensure
|
53
|
+
Sidekiq.client_middleware.remove Stopper
|
54
|
+
end
|
17
55
|
end
|
18
56
|
|
19
57
|
it 'should empty the retry and scheduled queues up to the current time' do
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
assert_equal
|
58
|
+
enqueued_time = Time.new(2013, 2, 4)
|
59
|
+
|
60
|
+
Time.stub(:now, enqueued_time) do
|
61
|
+
@retry.schedule (Time.now - 60).to_f, @error_1
|
62
|
+
@retry.schedule (Time.now - 50).to_f, @error_2
|
63
|
+
@retry.schedule (Time.now + 60).to_f, @error_3
|
64
|
+
@scheduled.schedule (Time.now - 60).to_f, @future_1
|
65
|
+
@scheduled.schedule (Time.now - 50).to_f, @future_2
|
66
|
+
@scheduled.schedule (Time.now + 60).to_f, @future_3
|
67
|
+
|
68
|
+
@poller.poll
|
69
|
+
|
70
|
+
Sidekiq.redis do |conn|
|
71
|
+
assert_equal 1, conn.llen("queue:queue_1")
|
72
|
+
assert_equal enqueued_time.to_f, Sidekiq.load_json(conn.lrange("queue:queue_1", 0, -1)[0])['enqueued_at']
|
73
|
+
assert_equal 1, conn.llen("queue:queue_2")
|
74
|
+
assert_equal enqueued_time.to_f, Sidekiq.load_json(conn.lrange("queue:queue_2", 0, -1)[0])['enqueued_at']
|
75
|
+
assert_equal 1, conn.llen("queue:queue_4")
|
76
|
+
assert_equal enqueued_time.to_f, Sidekiq.load_json(conn.lrange("queue:queue_4", 0, -1)[0])['enqueued_at']
|
77
|
+
assert_equal 1, conn.llen("queue:queue_5")
|
78
|
+
assert_equal enqueued_time.to_f, Sidekiq.load_json(conn.lrange("queue:queue_5", 0, -1)[0])['enqueued_at']
|
79
|
+
end
|
80
|
+
|
81
|
+
assert_equal 1, @retry.size
|
82
|
+
assert_equal 1, @scheduled.size
|
44
83
|
end
|
45
84
|
end
|
46
85
|
end
|
data/test/test_testing.rb
CHANGED
@@ -119,6 +119,23 @@ class TestTesting < Minitest::Test
|
|
119
119
|
StoredWorker.clear
|
120
120
|
end
|
121
121
|
|
122
|
+
it 'perform_one runs only one job' do
|
123
|
+
DirectWorker.perform_async(1, 2)
|
124
|
+
DirectWorker.perform_async(3, 4)
|
125
|
+
assert_equal 2, DirectWorker.jobs.size
|
126
|
+
|
127
|
+
DirectWorker.perform_one
|
128
|
+
assert_equal 1, DirectWorker.jobs.size
|
129
|
+
|
130
|
+
DirectWorker.clear
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'perform_one raise error upon empty queue' do
|
134
|
+
assert_raises Sidekiq::EmptyQueueError do
|
135
|
+
DirectWorker.perform_one
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
122
139
|
class FirstWorker
|
123
140
|
include Sidekiq::Worker
|
124
141
|
class_attribute :count
|
data/test/test_web.rb
CHANGED
@@ -264,7 +264,6 @@ class TestWeb < Minitest::Test
|
|
264
264
|
score = Time.now.to_f
|
265
265
|
msg = { 'class' => 'HardWorker',
|
266
266
|
'args' => ['bob', 1, Time.now.to_f],
|
267
|
-
'at' => score,
|
268
267
|
'jid' => 'f39af2a05e8f4b24dbc0f1e4' }
|
269
268
|
Sidekiq.redis do |conn|
|
270
269
|
conn.zadd('schedule', score, Sidekiq.dump_json(msg))
|
data/web/locales/en.yml
CHANGED
data/web/locales/pt-br.yml
CHANGED
data/web/views/retry.slim
CHANGED
@@ -19,6 +19,11 @@ table class="retry table table-bordered table-striped"
|
|
19
19
|
th JID
|
20
20
|
td
|
21
21
|
code= @retry.jid
|
22
|
+
- unless retry_extra_items(@retry).empty?
|
23
|
+
tr
|
24
|
+
th = t('Extras')
|
25
|
+
td
|
26
|
+
code= display_args(retry_extra_items(@retry), 1000)
|
22
27
|
- if @retry['retry_count'] > 0
|
23
28
|
tr
|
24
29
|
th = t('RetryCount')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.12.
|
4
|
+
version: 2.12.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
12
|
+
date: 2013-05-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ! '>='
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 0.14.
|
69
|
+
version: 0.14.1
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 0.14.
|
77
|
+
version: 0.14.1
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: json
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|