beetle 3.3.11 → 3.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd1ee5b22d344002924b2b648e036ce98584e270b05af6195115c5bc6aef6438
4
- data.tar.gz: f32ef2c465d81cb73ac8453b677419c9117e1f2ab62126feb62dd2227cc1e924
3
+ metadata.gz: 64be33377e4235036fac944de3c020f03fc53e426a1969b729ca0db016351cae
4
+ data.tar.gz: 7fde625b27bce1814ba5840b92898b7cb365f1d04b743584b59e15e6bb9d7da7
5
5
  SHA512:
6
- metadata.gz: 9521152d635cb12bd96dd87a8153cc20f4d8f9471d9a3d08c2d8d786a53bad2a76b783140ce1e8481b90c2b8dd1f6a391988985380fc4efcc93c30ba01ee013f
7
- data.tar.gz: c29b033bcb301006b22bcbeeb4a9e62b6d72a5bcf54093e01aee405ea2c5a8d0f65c3a0e6a69bce0cbe0047cf52780069ae6c9a7d68c53161fea5de0c8b09b27
6
+ metadata.gz: 990d179e32cad50f9d51ec3f3bf8e4e3d518b8f1925995277917ae5553dfd3fd72dd510558a3f2f5ddbc815b57f5a8719f3854b18b2680a620f76dda1bb411b5
7
+ data.tar.gz: 42e77ac9b05035ec28891cdf43eb8ba0706e835a52d4c1906843a7d9f1cf8a9a211c332c2d031c5b044b2f4cebbf40ca94a8dd20eda99abc0af0c8cf9ce9ce29
@@ -1,5 +1,24 @@
1
1
  = Release Notes
2
2
 
3
+ == Version 3.4.3
4
+ * optimize declaration of queues with many bindings
5
+
6
+ == Version 3.4.2
7
+ * Updated amq-protocol gem to version 2.3.2.
8
+ * Fixed a rare race condition on message handler timeouts.
9
+
10
+ == Version 3.4.1
11
+ * Updated amq-protocol gem to version 2.3.1.
12
+
13
+ == Version 3.4.0
14
+ * Require redis gem version 4.2.1. This version changes the exists to check for the
15
+ existence of multiple keys, return the number of keys in the list that exist. This
16
+ requires at least redis gem version 4.2.0, but 4.2.1 contains a bug fix for said
17
+ command.
18
+
19
+ == Version 3.3.12
20
+ * Support queue level declaration of dead letter queue message TTL.
21
+
3
22
  == Version 3.3.11
4
23
  * Fixed that dead lettering only works correctly with global config option.
5
24
 
@@ -24,9 +24,9 @@ Gem::Specification.new do |s|
24
24
 
25
25
  s.specification_version = 3
26
26
  s.add_runtime_dependency "bunny", "~> 0.7.12"
27
- s.add_runtime_dependency "redis", ">= 2.2.2"
27
+ s.add_runtime_dependency "redis", ">= 4.2.1"
28
28
  s.add_runtime_dependency "hiredis", ">= 0.4.5"
29
- s.add_runtime_dependency "amq-protocol", "= 2.3.0"
29
+ s.add_runtime_dependency "amq-protocol", "= 2.3.2"
30
30
  s.add_runtime_dependency "amqp", "= 1.8.0"
31
31
  s.add_runtime_dependency "activesupport", ">= 2.3.4"
32
32
 
@@ -67,32 +67,35 @@ module Beetle
67
67
  logger.debug("Beetle: binding queue #{name} with internal name #{opts[:amqp_name]} on server #{@server}")
68
68
  queue_name = opts[:amqp_name]
69
69
  creation_options = opts.slice(*QUEUE_CREATION_KEYS)
70
- the_queue = nil
70
+
71
+ the_queue = declare_queue!(queue_name, creation_options)
71
72
  @client.bindings[name].each do |binding_options|
72
73
  exchange_name = binding_options[:exchange]
73
74
  binding_options = binding_options.slice(*QUEUE_BINDING_KEYS)
74
- the_queue = bind_queue!(queue_name, creation_options, exchange_name, binding_options)
75
+ logger.debug("Beetle: binding queue #{queue_name} to #{exchange_name} with opts: #{binding_options.inspect}")
76
+ bind_queue!(the_queue, exchange_name, binding_options)
75
77
  end
76
78
  the_queue
77
79
  end
78
80
  end
79
81
 
80
- def bind_dead_letter_queue!(channel, target_queue, creation_keys = {})
81
- policy_options = @client.queues[target_queue].slice(:dead_lettering, :lazy)
82
+ def bind_dead_letter_queue!(channel, target_queue, creation_options = {})
83
+ policy_options = @client.queues[target_queue].slice(:dead_lettering, :lazy, :dead_lettering_msg_ttl)
84
+ policy_options[:message_ttl] = policy_options.delete(:dead_lettering_msg_ttl)
82
85
  dead_letter_queue_name = "#{target_queue}_dead_letter"
83
86
  if policy_options[:dead_lettering]
84
- logger.debug("Beetle: creating dead letter queue #{dead_letter_queue_name} with opts: #{creation_keys.inspect}")
85
- channel.queue(dead_letter_queue_name, creation_keys)
87
+ logger.debug("Beetle: creating dead letter queue #{dead_letter_queue_name} with opts: #{creation_options.inspect}")
88
+ channel.queue(dead_letter_queue_name, creation_options)
86
89
  end
87
90
  return {
88
91
  :queue_name => target_queue,
89
92
  :bindings => @client.bindings[target_queue],
90
93
  :dead_letter_queue_name => dead_letter_queue_name,
91
- :message_ttl => @client.config.dead_lettering_msg_ttl,
94
+ :message_ttl => policy_options[:message_ttl]
92
95
  }.merge(policy_options)
93
96
  end
94
97
 
95
- # called by <tt>bind_queue!</tt>
98
+ # called by <tt>declare_queue!</tt>
96
99
  def publish_policy_options(options)
97
100
  # avoid endless recursion
98
101
  return if options[:queue_name] == @client.config.beetle_policy_updates_queue_name
@@ -96,7 +96,8 @@ module Beetle
96
96
  raise ConfigurationError.new("queue #{name} already configured") if queues.include?(name)
97
97
  opts = {
98
98
  :exchange => name, :key => name, :auto_delete => false, :amqp_name => name,
99
- :lazy => config.lazy_queues_enabled, :dead_lettering => config.dead_lettering_enabled
99
+ :lazy => config.lazy_queues_enabled, :dead_lettering => config.dead_lettering_enabled,
100
+ :dead_lettering_msg_ttl => config.dead_lettering_msg_ttl
100
101
  }.merge!(options.symbolize_keys)
101
102
  opts.merge! :durable => true, :passive => false, :exclusive => false
102
103
  exchange = opts.delete(:exchange).to_s
@@ -120,7 +120,7 @@ module Beetle
120
120
 
121
121
  # check whether key with given suffix exists for a given <tt>msg_id</tt>.
122
122
  def exists(msg_id, suffix)
123
- with_failover { redis.exists(key(msg_id, suffix)) }
123
+ with_failover { redis.exists?(key(msg_id, suffix)) }
124
124
  end
125
125
 
126
126
  # flush the configured redis database. useful for testing.
@@ -18,6 +18,8 @@ module Beetle
18
18
  # forcefully abort a running handler after this many seconds.
19
19
  # can be overriden when registering a handler.
20
20
  DEFAULT_HANDLER_TIMEOUT = 600.seconds
21
+ # How much extra time on top of the handler timeout we add before considering a handler timed out
22
+ TIMEOUT_GRACE_PERIOD = 10.seconds
21
23
  # how many times we should try to run a handler before giving up
22
24
  DEFAULT_HANDLER_EXECUTION_ATTEMPTS = 1
23
25
  # how many seconds we should wait before retrying handler execution
@@ -167,8 +169,8 @@ module Beetle
167
169
  end
168
170
 
169
171
  # handler timed out?
170
- def timed_out?
171
- (t = @store.get(msg_id, :timeout)) && t.to_i < now
172
+ def timed_out?(t = nil)
173
+ (t ||= @store.get(msg_id, :timeout)) && (t.to_i + TIMEOUT_GRACE_PERIOD) < now
172
174
  end
173
175
 
174
176
  # reset handler timeout in the deduplication store
@@ -187,8 +189,8 @@ module Beetle
187
189
  end
188
190
 
189
191
  # whether we should wait before running the handler
190
- def delayed?
191
- (t = @store.get(msg_id, :delay)) && t.to_i > now
192
+ def delayed?(t = nil)
193
+ (t ||= @store.get(msg_id, :delay)) && t.to_i > now
192
194
  end
193
195
 
194
196
  # store delay value in the deduplication store
@@ -207,8 +209,8 @@ module Beetle
207
209
  end
208
210
 
209
211
  # whether we have already tried running the handler as often as specified when the handler was registered
210
- def attempts_limit_reached?
211
- (limit = @store.get(msg_id, :attempts)) && limit.to_i >= attempts_limit
212
+ def attempts_limit_reached?(attempts = nil)
213
+ (attempts ||= @store.get(msg_id, :attempts)) && attempts.to_i >= attempts_limit
212
214
  end
213
215
 
214
216
  # increment number of exception occurences in the deduplication store
@@ -217,8 +219,8 @@ module Beetle
217
219
  end
218
220
 
219
221
  # whether the number of exceptions has exceeded the limit set when the handler was registered
220
- def exceptions_limit_reached?
221
- @store.get(msg_id, :exceptions).to_i > exceptions_limit
222
+ def exceptions_limit_reached?(exceptions = nil)
223
+ (exceptions ||= @store.get(msg_id, :exceptions)) && exceptions.to_i > exceptions_limit
222
224
  end
223
225
 
224
226
  def exception_accepted?
@@ -306,17 +308,17 @@ module Beetle
306
308
  if status == "completed"
307
309
  ack!
308
310
  RC::OK
309
- elsif delay && delay.to_i > now
311
+ elsif delay && delayed?(delay)
310
312
  logger.warn "Beetle: ignored delayed message (#{msg_id})!"
311
313
  RC::Delayed
312
- elsif !(timeout && timeout.to_i < now)
314
+ elsif !(timeout && timed_out?(timeout))
313
315
  RC::HandlerNotYetTimedOut
314
- elsif attempts.to_i >= attempts_limit
316
+ elsif attempts && attempts_limit_reached?(attempts)
315
317
  completed!
316
318
  ack!
317
319
  logger.warn "Beetle: reached the handler execution attempts limit: #{attempts_limit} on #{msg_id}"
318
320
  RC::AttemptsLimitReached
319
- elsif exceptions.to_i > exceptions_limit
321
+ elsif exceptions && exceptions_limit_reached?(exceptions)
320
322
  completed!
321
323
  ack!
322
324
  logger.warn "Beetle: reached the handler exceptions limit: #{exceptions_limit} on #{msg_id}"
@@ -247,17 +247,19 @@ module Beetle
247
247
  @exchanges_with_bound_queues[exchange_name] = true
248
248
  end
249
249
 
250
- # TODO: Refactor, fetch the keys and stuff itself
251
- def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys)
252
- logger.debug("Beetle: creating queue with opts: #{creation_keys.inspect}")
253
- queue = bunny.queue(queue_name, creation_keys)
254
- logger.debug("Beetle: binding queue #{queue_name} to #{exchange_name} with opts: #{binding_keys.inspect}")
255
- queue.bind(exchange(exchange_name), binding_keys)
256
- policy_options = bind_dead_letter_queue!(bunny, queue_name, creation_keys)
250
+ def declare_queue!(queue_name, creation_options)
251
+ logger.debug("Beetle: creating queue with opts: #{creation_options.inspect}")
252
+ queue = bunny.queue(queue_name, creation_options)
253
+
254
+ policy_options = bind_dead_letter_queue!(bunny, queue_name, creation_options)
257
255
  publish_policy_options(policy_options)
258
256
  queue
259
257
  end
260
258
 
259
+ def bind_queue!(queue, exchange_name, binding_options)
260
+ queue.bind(exchange(exchange_name), binding_options)
261
+ end
262
+
261
263
  def stop!(exception=nil)
262
264
  return unless bunny?
263
265
  timeout = @client.config.publishing_timeout + @client.config.publisher_connect_timeout + 1
@@ -214,18 +214,20 @@ module Beetle
214
214
  channel.__send__(opts[:type], name, opts.slice(*EXCHANGE_CREATION_KEYS))
215
215
  end
216
216
 
217
- def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys)
218
- queue = channel.queue(queue_name, creation_keys)
217
+ def declare_queue!(queue_name, creation_options)
218
+ queue = channel.queue(queue_name, creation_options)
219
219
  unless tracing?
220
220
  # we don't want to create dead-letter queues for tracing
221
- policy_options = bind_dead_letter_queue!(channel, queue_name, creation_keys)
221
+ policy_options = bind_dead_letter_queue!(channel, queue_name, creation_options)
222
222
  publish_policy_options(policy_options)
223
223
  end
224
- exchange = exchange(exchange_name)
225
- queue.bind(exchange, binding_keys)
226
224
  queue
227
225
  end
228
226
 
227
+ def bind_queue!(queue, exchange_name, binding_options)
228
+ queue.bind(exchange(exchange_name), binding_options)
229
+ end
230
+
229
231
  def connection_settings
230
232
  {
231
233
  :host => current_host, :port => current_port, :logging => false,
@@ -1,3 +1,3 @@
1
1
  module Beetle
2
- VERSION = "3.3.11"
2
+ VERSION = "3.4.3"
3
3
  end
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'time'
4
+
5
+ counts = Hash.new(0)
6
+ expiries = Hash.new{|h,k| h[k] = Hash.new(0)}
7
+ t = Time.now.to_i
8
+
9
+ File.open(ARGV[0]).each_line do |l|
10
+ parts = l.split(':')
11
+ queue = parts[1]
12
+ counts[queue] += 1
13
+ expiry = parts[4].to_i
14
+ expires_in = ((expiry - t)/(3600.0)).ceil
15
+ expiries[queue][expires_in] += 1
16
+ end
17
+
18
+ counts.to_a.sort_by{|_,v| -v}.each do |q,v|
19
+ puts "------------------------------------------------------------------"
20
+ puts "#{q}: #{v}"
21
+ puts "------------------------------------------------------------------"
22
+ expiries[q].to_a.sort_by{|k,_| -k}.each do |expiry, count|
23
+ printf "%3dh: %6d\n", expiry, count
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ queue_counts = Hash.new { |h,k| h[k] = 0 }
3
+ File.open(ARGV[0]).each_line do |l|
4
+ next if l == "lastgc" || l == "clients-last-seen"
5
+ a = l.split(':')
6
+ if a[0] == "msgid"
7
+ queue_counts[a[1]] += 1
8
+ else
9
+ queue_counts["none"] += 1
10
+ end
11
+ end
12
+ sorted_queues = queue_counts.to_a.sort_by{|a| -a[1]}
13
+ sorted_queues.each do |q,c|
14
+ puts "#{c}:#{q}"
15
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ require "redis"
3
+
4
+ redis = Redis.new(:host => "beetle-1.redis.ams2.xing.com", :port => 6379, :db => 0)
5
+
6
+ File.open(ARGV[0]).each_line.each_slice(10) do |s|
7
+ redis.pipelined do
8
+ s.each do |l|
9
+ l.chomp!
10
+ next if l =~ /^beetle:.*$/
11
+ redis.expire(l, 600)
12
+ end
13
+ end
14
+ end
@@ -79,7 +79,7 @@ module Beetle
79
79
 
80
80
  test "registering a queue should store it in the configuration with symbolized option keys and force durable=true and passive=false and set the amqp queue name" do
81
81
  @client.register_queue("some_queue", "durable" => false, "exchange" => "some_exchange")
82
- assert_equal({:durable => true, :passive => false, :lazy=>false, :dead_lettering=>false, :auto_delete => false, :exclusive => false, :amqp_name => "some_queue"}, @client.queues["some_queue"])
82
+ assert_equal({:durable => true, :passive => false, :lazy=>false, :dead_lettering=>false, :dead_lettering_msg_ttl=>1000, :auto_delete => false, :exclusive => false, :amqp_name => "some_queue"}, @client.queues["some_queue"])
83
83
  end
84
84
 
85
85
  test "registering a queue should add the queue to the list of queues of the queue's exchange" do
@@ -9,7 +9,7 @@ module Beetle
9
9
  end
10
10
 
11
11
  test "trying to delete a non existent key doesn't throw an error" do
12
- assert !@r.exists("hahahaha")
12
+ assert !@r.exists?("hahahaha")
13
13
  assert_equal 0, @r.del("hahahaha")
14
14
  end
15
15
 
@@ -75,9 +75,9 @@ module Beetle
75
75
  message.expects(:now).returns(1)
76
76
  message.set_timeout!
77
77
  assert_equal "2", @store.get(message.msg_id, :timeout)
78
- message.expects(:now).returns(2)
78
+ message.expects(:now).returns(2 + Message::TIMEOUT_GRACE_PERIOD)
79
79
  assert !message.timed_out?
80
- message.expects(:now).returns(3)
80
+ message.expects(:now).returns(3 + Message::TIMEOUT_GRACE_PERIOD)
81
81
  assert message.timed_out?
82
82
  end
83
83
 
@@ -86,9 +86,9 @@ module Beetle
86
86
  message.expects(:now).returns(0)
87
87
  message.set_timeout!
88
88
  assert_equal "#{Message::DEFAULT_HANDLER_TIMEOUT}", @store.get(message.msg_id, :timeout)
89
- message.expects(:now).returns(message.timeout)
89
+ message.expects(:now).returns(message.timeout + Message::TIMEOUT_GRACE_PERIOD)
90
90
  assert !message.timed_out?
91
- message.expects(:now).returns(Message::DEFAULT_HANDLER_TIMEOUT + 1)
91
+ message.expects(:now).returns(message.timeout + Message::TIMEOUT_GRACE_PERIOD + 1)
92
92
  assert message.timed_out?
93
93
  end
94
94
 
@@ -141,9 +141,7 @@ module Beetle
141
141
 
142
142
  message.process(@null_handler)
143
143
  keys = @store.keys(message.msg_id)
144
- keys.each do |key|
145
- assert !@store.redis.exists(key)
146
- end
144
+ assert_equal 0, @store.redis.exists(*keys)
147
145
  end
148
146
 
149
147
  test "successful processing of a non redundant message should delete all keys from the database (except the status key, which should be set to expire)" do
@@ -159,11 +157,9 @@ module Beetle
159
157
  message.process(@null_handler)
160
158
  keys = @store.keys(message.msg_id)
161
159
  status_key = keys.shift
162
- assert @store.redis.exists(status_key)
160
+ assert @store.redis.exists?(status_key)
163
161
  assert @store.redis.ttl(status_key) <= @config.redis_status_key_expiry_interval
164
- keys.each do |key|
165
- assert !@store.redis.exists(key)
166
- end
162
+ assert_equal 0, @store.redis.exists(*keys)
167
163
  end
168
164
 
169
165
  test "successful processing of a redundant message twice should delete all keys from the database" do
@@ -179,9 +175,7 @@ module Beetle
179
175
  message.process(@null_handler)
180
176
 
181
177
  keys = @store.keys(message.msg_id)
182
- keys.each do |key|
183
- assert !@store.redis.exists(key)
184
- end
178
+ assert_equal 0, @store.redis.exists(*keys)
185
179
  end
186
180
 
187
181
  test "successful processing of a redundant message twice should delete all keys from the database (except the status key, which should be set to expire)" do
@@ -199,11 +193,9 @@ module Beetle
199
193
 
200
194
  keys = @store.keys(message.msg_id)
201
195
  status_key = keys.shift
202
- assert @store.redis.exists(status_key)
196
+ assert @store.redis.exists?(status_key)
203
197
  assert @store.redis.ttl(status_key) <= @config.redis_status_key_expiry_interval
204
- keys.each do |key|
205
- assert !@store.redis.exists(key)
206
- end
198
+ assert_equal 0, @store.redis.exists(*keys)
207
199
  end
208
200
 
209
201
  test "successful processing of a redundant message once should insert all but the delay key and the exception count key into the database" do
@@ -304,7 +304,9 @@ module Beetle
304
304
  @client.register_queue('test_queue_1', :exchange => 'test_exchange')
305
305
  @client.register_queue('test_queue_2', :exchange => 'test_exchange')
306
306
  @client.register_queue('test_queue_3', :exchange => 'test_exchange_2')
307
- @pub.expects(:bind_queue!).returns(1).times(3)
307
+ queue = mock("queue")
308
+ queue.expects(:bind).times(3)
309
+ @pub.expects(:declare_queue!).returns(queue).times(3)
308
310
  @pub.send(:bind_queues_for_exchange, 'test_exchange')
309
311
  @pub.send(:bind_queues_for_exchange, 'test_exchange_2')
310
312
  end
@@ -312,8 +314,19 @@ module Beetle
312
314
  test "should not rebind the defined queues for the used exchanges if they already have been bound" do
313
315
  @client.register_queue('test_queue_1', :exchange => 'test_exchange')
314
316
  @client.register_queue('test_queue_2', :exchange => 'test_exchange')
315
- @pub.expects(:bind_queue!).twice
317
+ queue = mock("queue")
318
+ queue.expects(:bind).twice
319
+ @pub.expects(:declare_queue!).returns(queue).twice
320
+ @pub.send(:bind_queues_for_exchange, 'test_exchange')
316
321
  @pub.send(:bind_queues_for_exchange, 'test_exchange')
322
+ end
323
+
324
+ test "should declare queues only once even with many bindings" do
325
+ @client.register_queue('test_queue', :exchange => 'test_exchange')
326
+ @client.register_binding('test_queue', :exchange => 'test_exchange', :key => 'sir-message-a-lot')
327
+ queue = mock("queue")
328
+ queue.expects(:bind).twice
329
+ @pub.expects(:declare_queue!).returns(queue).once
317
330
  @pub.send(:bind_queues_for_exchange, 'test_exchange')
318
331
  end
319
332
 
@@ -168,6 +168,17 @@ module Beetle
168
168
  @sub.send(:bind_queues, %W(x y))
169
169
  end
170
170
 
171
+ test "binding queues with many bindings should create it only once" do
172
+ @client.register_queue(:x, :exchange => 'test_exchange')
173
+ @client.register_binding(:x, :exchange => 'test_exchange', :key => 'sir-message-a-lot')
174
+ @client.register_handler(%w(x)){}
175
+ @sub.stubs(:exchange)
176
+ queue = mock("queue")
177
+ queue.expects(:bind).twice
178
+ @sub.expects(:declare_queue!).returns(queue).once
179
+ @sub.send(:bind_queues, %W(x))
180
+ end
181
+
171
182
  test "subscribing to queues should subscribe on all queues" do
172
183
  @client.register_queue(:x)
173
184
  @client.register_queue(:y)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beetle
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.11
4
+ version: 3.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Kaes
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2020-06-18 00:00:00.000000000 Z
15
+ date: 2021-01-21 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: bunny
@@ -34,14 +34,14 @@ dependencies:
34
34
  requirements:
35
35
  - - ">="
36
36
  - !ruby/object:Gem::Version
37
- version: 2.2.2
37
+ version: 4.2.1
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  requirements:
42
42
  - - ">="
43
43
  - !ruby/object:Gem::Version
44
- version: 2.2.2
44
+ version: 4.2.1
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: hiredis
47
47
  requirement: !ruby/object:Gem::Requirement
@@ -62,14 +62,14 @@ dependencies:
62
62
  requirements:
63
63
  - - '='
64
64
  - !ruby/object:Gem::Version
65
- version: 2.3.0
65
+ version: 2.3.2
66
66
  type: :runtime
67
67
  prerelease: false
68
68
  version_requirements: !ruby/object:Gem::Requirement
69
69
  requirements:
70
70
  - - '='
71
71
  - !ruby/object:Gem::Version
72
- version: 2.3.0
72
+ version: 2.3.2
73
73
  - !ruby/object:Gem::Dependency
74
74
  name: amqp
75
75
  requirement: !ruby/object:Gem::Requirement
@@ -337,7 +337,10 @@ files:
337
337
  - lib/beetle/redis_ext.rb
338
338
  - lib/beetle/subscriber.rb
339
339
  - lib/beetle/version.rb
340
+ - script/analyze-expiries
341
+ - script/analyze-redis-keys
340
342
  - script/console
343
+ - script/expire-keys
341
344
  - script/start_rabbit
342
345
  - test/beetle/amqp_gem_behavior_test.rb
343
346
  - test/beetle/base_test.rb