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 +4 -4
- data/RELEASE_NOTES.rdoc +4 -2
- data/lib/beetle/configuration.rb +6 -8
- data/lib/beetle/deduplication_store.rb +6 -3
- data/lib/beetle/version.rb +1 -1
- data/test/beetle/message_test.rb +58 -1
- data/test/beetle/publisher_test.rb +22 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e1e8a0378a54fd5b151e8a85fe404d74b06bc0e33458e632676bb5b60b7b38d
|
4
|
+
data.tar.gz: 546a4383cdc3727eb9709ea6ef30647cfc647c803e5be9853b77b50b70c915c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d307e9c99eaafc64463e2fc5b21b3b9b4a04a831b3eb74d0330f86411412dc01f4f3e0a3e059695d5cfbd2b94b527352549fbaf4e5ebd4c8f28acdce79b25dcb
|
7
|
+
data.tar.gz: a285335c8023bda35630fbe01162d5cd5e196fc60576c827f3f05e099d9f5c3e35608d7819d996de849c9f25e3619a33de90a2cca3704fab11636f3ec6645d0f
|
data/RELEASE_NOTES.rdoc
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
= Release Notes
|
2
2
|
|
3
|
-
== Version 3.3.0
|
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
|
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
|
data/lib/beetle/configuration.rb
CHANGED
@@ -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
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
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 =
|
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 =>
|
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,
|
117
|
+
redis.expire(status_key, expiry) if expiry > 0
|
115
118
|
end
|
116
119
|
end
|
117
120
|
|
data/lib/beetle/version.rb
CHANGED
data/test/beetle/message_test.rb
CHANGED
@@ -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
|
-
@
|
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
|
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-
|
15
|
+
date: 2019-07-18 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bunny
|