beetle 3.3.0.rc1 → 3.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df35415e0cf7a4d4915a56aa594fe4aa1e63be2d536eab5589a5b80c349fdb96
4
- data.tar.gz: 6f621ab1501f71cdc7ee84d8989dd446ebd17676d53f9e23ba9d8278206908ed
3
+ metadata.gz: 3e1e8a0378a54fd5b151e8a85fe404d74b06bc0e33458e632676bb5b60b7b38d
4
+ data.tar.gz: 546a4383cdc3727eb9709ea6ef30647cfc647c803e5be9853b77b50b70c915c0
5
5
  SHA512:
6
- metadata.gz: 51e61e992d734f636b5a86b176ab1150530c8e7c18dbbaf8c4f8e685eaf48b2531133bb0770b9b8f50bea45e95588cad6b892866a6cd6644dc8d5a3e67e71b7d
7
- data.tar.gz: 4ef44c5608cfe93adc0bf9fefea0cfdfda59f358323b5ed93158fb57e0122241c45a4deff76a8a098664a4e027ff1394e135541857a4682286ab135481c012a9
6
+ metadata.gz: d307e9c99eaafc64463e2fc5b21b3b9b4a04a831b3eb74d0330f86411412dc01f4f3e0a3e059695d5cfbd2b94b527352549fbaf4e5ebd4c8f28acdce79b25dcb
7
+ data.tar.gz: a285335c8023bda35630fbe01162d5cd5e196fc60576c827f3f05e099d9f5c3e35608d7819d996de849c9f25e3619a33de90a2cca3704fab11636f3ec6645d0f
@@ -1,12 +1,14 @@
1
1
  = Release Notes
2
2
 
3
- == Version 3.3.0.rc1
3
+ == Version 3.3.0
4
4
  * protect against duplicate handler execution by keeping the status of
5
5
  handler exectution for both redundant and non-redundant messages in
6
6
  the dedup store for a configurable time window. The config option
7
7
  is named redis_status_key_expiry_interval. Note that this will
8
8
  significantly increase the cpu load and memory usage of the Redis
9
- server for applications using a large number of non-redundant messages.
9
+ server for applications using a large number of non-redundant
10
+ messages. This feature is turned off by default, but we will
11
+ activate it with the next major release (4.0.0).
10
12
 
11
13
  == Version 3.2.0
12
14
  * added currently processed message to the handler pre-processing step
@@ -37,13 +37,11 @@ module Beetle
37
37
  # handler timeout.
38
38
  attr_accessor :redis_failover_timeout
39
39
 
40
- # how long we want status keys to survive after we have seen the second message of a
41
- # redundant message pair. Defaults to 5 minutes. Setting this to a high value (hours)
42
- # will reduce the likelihood of executing handler logic more than once, but can cause
43
- # a higher redis database size with all associated problems. A handler can be
44
- # executed more than once if the ack to the RabbitMQ server gets lost between the consumer
45
- # and the RabbitMQ instance. This happens extremely seldom in our environment, but we cannot
46
- # rule it out and we also don't quite understand (yet) why it happens.
40
+ # how long we want status keys to survive after we have seen the second message of a redundant
41
+ # message pair. Defaults to 0 seconds, but will be set to something non-zero with the next
42
+ # major beetle release. A recommended value would be 5 minutes (300 seconds). Setting this to a
43
+ # high value (hours) will reduce the likelihood of executing handler logic more than once, but
44
+ # can cause a higher redis database size with all associated problems.
47
45
  attr_accessor :redis_status_key_expiry_interval
48
46
 
49
47
  # how often heartbeat messages are exchanged between failover
@@ -151,7 +149,7 @@ module Beetle
151
149
  self.redis_servers = ""
152
150
  self.redis_db = 4
153
151
  self.redis_failover_timeout = 180.seconds
154
- self.redis_status_key_expiry_interval = 5.minutes
152
+ self.redis_status_key_expiry_interval = 0.seconds
155
153
  self.redis_failover_client_heartbeat_interval = 10.seconds
156
154
  self.redis_failover_client_dead_interval = 60.seconds
157
155
 
@@ -62,12 +62,14 @@ module Beetle
62
62
  # store completion status for given <tt>msg_id</tt> if it doesn't exist yet. Returns whether the
63
63
  # operation was successful.
64
64
  def setnx_completed!(msg_id)
65
+ expiry = @config.redis_status_key_expiry_interval
66
+ return true if expiry == 0
65
67
  with_failover do
66
68
  redis.set(
67
69
  key(msg_id, :status),
68
70
  "completed",
69
71
  :nx => true,
70
- :ex => @config.redis_status_key_expiry_interval,
72
+ :ex => expiry,
71
73
  )
72
74
  end
73
75
  end
@@ -107,11 +109,12 @@ module Beetle
107
109
 
108
110
  # delete all keys associated with the given <tt>msg_id</tt>.
109
111
  def del_keys(msg_id)
112
+ expiry = @config.redis_status_key_expiry_interval
110
113
  keys = keys(msg_id)
111
- status_key = keys.shift
114
+ status_key = keys.shift if expiry > 0
112
115
  with_failover do
113
116
  redis.del(*keys)
114
- redis.expire(status_key, @config.redis_status_key_expiry_interval)
117
+ redis.expire(status_key, expiry) if expiry > 0
115
118
  end
116
119
  end
117
120
 
@@ -1,3 +1,3 @@
1
1
  module Beetle
2
- VERSION = "3.3.0.rc1"
2
+ VERSION = "3.3.0"
3
3
  end
@@ -129,7 +129,24 @@ module Beetle
129
129
  end
130
130
  end
131
131
 
132
+ test "successful processing of a non redundant message should delete all keys from the database" do
133
+ header = header_with_params({})
134
+ header.expects(:ack)
135
+ message = Message.new("somequeue", header, 'foo', :store => @store)
136
+ message.stubs(:simple?).returns(false)
137
+
138
+ assert !message.expired?
139
+ assert !message.redundant?
140
+
141
+ message.process(@null_handler)
142
+ keys = @store.keys(message.msg_id)
143
+ keys.each do |key|
144
+ assert !@store.redis.exists(key)
145
+ end
146
+ end
147
+
132
148
  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
149
+ @config.redis_status_key_expiry_interval = 1.minutes
133
150
  header = header_with_params({})
134
151
  header.expects(:ack)
135
152
  message = Message.new("somequeue", header, 'foo', :store => @store)
@@ -148,7 +165,26 @@ module Beetle
148
165
  end
149
166
  end
150
167
 
168
+ test "successful processing of a redundant message twice should delete all keys from the database" do
169
+ header = header_with_params({:redundant => true})
170
+ header.expects(:ack).twice
171
+ message = Message.new("somequeue", header, 'foo', :store => @store)
172
+
173
+ assert !message.expired?
174
+ assert message.redundant?
175
+ assert !message.simple?
176
+
177
+ message.process(@null_handler)
178
+ message.process(@null_handler)
179
+
180
+ keys = @store.keys(message.msg_id)
181
+ keys.each do |key|
182
+ assert !@store.redis.exists(key)
183
+ end
184
+ end
185
+
151
186
  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
187
+ @config.redis_status_key_expiry_interval = 1.minutes
152
188
  header = header_with_params({:redundant => true})
153
189
  header.expects(:ack).twice
154
190
  message = Message.new("somequeue", header, 'foo', :store => @store)
@@ -302,7 +338,8 @@ module Beetle
302
338
 
303
339
  class SimpleMessageTest < Minitest::Test
304
340
  def setup
305
- @store = DeduplicationStore.new
341
+ @config = Configuration.new
342
+ @store = DeduplicationStore.new(@config)
306
343
  @store.flushdb
307
344
  end
308
345
 
@@ -333,6 +370,26 @@ module Beetle
333
370
  assert_equal RC::AttemptsLimitReached, message.process(handler)
334
371
  end
335
372
 
373
+ test "when processing a simple message, the handler should be executed only once if status keys are used" do
374
+ @config.redis_status_key_expiry_interval = 1.minute
375
+ header = header_with_params({})
376
+ message = Message.new("somequeue", header, 'foo', :attempts => 1, :store => @store)
377
+
378
+ handler = mock("handler")
379
+ s = sequence("s")
380
+ handler.expects(:pre_process).with(message).in_sequence(s)
381
+ header.expects(:ack).in_sequence(s)
382
+ handler.expects(:call).in_sequence(s)
383
+ assert_equal RC::OK, message.process(handler)
384
+
385
+ handler2 = mock("handler")
386
+ s2 = sequence("s2")
387
+ handler2.expects(:pre_process).with(message).in_sequence(s2)
388
+ header.expects(:ack).in_sequence(s2)
389
+ handler2.expects(:call).in_sequence(s2).never
390
+ assert_equal RC::OK, message.process(handler2)
391
+ end
392
+
336
393
  end
337
394
 
338
395
  class HandlerCrashTest < Minitest::Test
@@ -53,6 +53,17 @@ module Beetle
53
53
  assert_nil @pub.instance_variable_get(:@bunnies)[@pub.server]
54
54
  end
55
55
 
56
+ test "stop!(exception) should close the bunny socket if an exception is not nil" do
57
+ b = mock("bunny")
58
+ b.expects(:close_socket)
59
+ @pub.expects(:bunny?).returns(true)
60
+ @pub.expects(:bunny).returns(b)
61
+ @pub.send(:stop!, Exception.new)
62
+ assert_equal({}, @pub.send(:exchanges))
63
+ assert_equal({}, @pub.send(:queues))
64
+ assert_nil @pub.instance_variable_get(:@bunnies)[@pub.server]
65
+ end
66
+
56
67
  test "stop! should not create a new bunny " do
57
68
  @pub.expects(:bunny?).returns(false)
58
69
  @pub.expects(:bunny).never
@@ -392,6 +403,17 @@ module Beetle
392
403
  assert @pub.throttled?
393
404
  end
394
405
 
406
+ test "refresh_throttling! logs a warning if an exception is raised during throttling" do
407
+ assert !@pub.throttled?
408
+ @pub.instance_variable_set :@next_throttle_refresh, Time.now - 1
409
+ options = { "test" => 100 }
410
+ @pub.throttle(options)
411
+ @pub.expects(:each_server).raises(StandardError.new("foo"))
412
+ @pub.logger.expects(:warn)
413
+ @pub.__send__ :refresh_throttling!
414
+ assert !@pub.throttled?
415
+ end
416
+
395
417
  end
396
418
 
397
419
  class PublisherExchangeManagementTest < Minitest::Test
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.0.rc1
4
+ version: 3.3.0
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: 2019-07-17 00:00:00.000000000 Z
15
+ date: 2019-07-18 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: bunny