beetle 2.0.2 → 2.1.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 -0
- data/examples/attempts_with_dead_letter_and_exponential_backoff.rb +72 -0
- data/examples/attempts_with_exponential_backoff.rb +72 -0
- data/lib/beetle/message.rb +13 -1
- data/lib/beetle/version.rb +1 -1
- data/test/beetle/message/settings_test.rb +174 -0
- data/test/beetle/message_test.rb +0 -153
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f35943d8dbccaf27c203a95f97bd0c07eac095e
|
4
|
+
data.tar.gz: 457e47a4c51befed13d5c79a9b9d30a7e34f565b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bd412cffe960ec193ce073fcefece2e7656ed4b136246ea4edf46ea57b45245736b6a00266a2f5edf8413f132790a74b6c86dfcf8c6f613b1a289cd6e284bc5
|
7
|
+
data.tar.gz: a88e2fbe08e0c0a2730b524e58c2a56a9f711b2bfd449bc9b9c895219a69b5f8af82a9d8715550bbe144a026e16ea45c7b569055517f8208dd2322f66c4951c5
|
data/RELEASE_NOTES.rdoc
CHANGED
@@ -0,0 +1,72 @@
|
|
1
|
+
# attempts_with_dead_letter_and_exponential_backoff.rb
|
2
|
+
# ! check the examples/README.rdoc for information on starting your redis/rabbit !
|
3
|
+
#
|
4
|
+
# start it with ruby attempts_with_dead_letter_and_exponential_backoff.rb
|
5
|
+
|
6
|
+
require "rubygems"
|
7
|
+
require File.expand_path("../lib/beetle", File.dirname(__FILE__))
|
8
|
+
|
9
|
+
# set Beetle log level to info, less noisy than debug
|
10
|
+
Beetle.config.logger.level = Logger::INFO
|
11
|
+
|
12
|
+
# setup client with dead lettering enabled
|
13
|
+
config = Beetle::Configuration.new
|
14
|
+
config.dead_lettering_enabled = true
|
15
|
+
config.dead_lettering_msg_ttl = 1000 # millis
|
16
|
+
client = Beetle::Client.new(config)
|
17
|
+
client.register_queue(:test)
|
18
|
+
client.register_message(:test)
|
19
|
+
|
20
|
+
# purge the test queue
|
21
|
+
client.purge(:test)
|
22
|
+
|
23
|
+
# empty the dedup store
|
24
|
+
client.deduplication_store.flushdb
|
25
|
+
|
26
|
+
# setup our counter
|
27
|
+
$completed = 0
|
28
|
+
$exceptions_limit = 4
|
29
|
+
|
30
|
+
# store the start time
|
31
|
+
$start_time = Time.now.to_f
|
32
|
+
|
33
|
+
# declare a handler class for message processing
|
34
|
+
# handler fails on the first execution attempt, then succeeds
|
35
|
+
class Handler < Beetle::Handler
|
36
|
+
# called when the handler receives the message, fails on first two attempts
|
37
|
+
# succeeds on the next and counts up our counter
|
38
|
+
def process
|
39
|
+
logger.info "Attempts: #{message.attempts}, Base Delay: #{message.delay}, Processed at: #{Time.now.to_f - $start_time}"
|
40
|
+
raise "attempt #{message.attempts} for message #{message.data}" if message.attempts < $exceptions_limit
|
41
|
+
logger.info "processing of message #{message.data} succeeded on attempt #{message.attempts}. completed: #{$completed += 1}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# called when handler process raised an exception
|
45
|
+
def error(exception)
|
46
|
+
logger.info "execution failed: #{exception}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# register our handler to the message, configure it to our max_attempts limit, we configure a (base) delay of 0.5
|
51
|
+
client.register_handler(:test, Handler, exceptions: $exceptions_limit, delay: 1, max_delay: 10)
|
52
|
+
# publish test messages
|
53
|
+
client.publish(:test, 1) # publish returns the number of servers the message has been sent to
|
54
|
+
puts "published 1 test message"
|
55
|
+
|
56
|
+
# start the listening loop
|
57
|
+
client.listen do
|
58
|
+
# catch INT-signal and stop listening
|
59
|
+
trap("INT") { client.stop_listening }
|
60
|
+
# we're adding a periodic timer to check whether all 10 messages have been processed without exceptions
|
61
|
+
timer = EM.add_periodic_timer(1) do
|
62
|
+
if $completed == 1
|
63
|
+
timer.cancel
|
64
|
+
client.stop_listening
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
puts "Handled #{$completed} messages"
|
70
|
+
if $completed != 1
|
71
|
+
raise "Did not handle the correct number of messages"
|
72
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# attempts_with_exponential_backoff.rb
|
2
|
+
# ! check the examples/README.rdoc for information on starting your redis/rabbit !
|
3
|
+
#
|
4
|
+
# start it with ruby attempts_with_exponential_backoff.rb
|
5
|
+
|
6
|
+
require "rubygems"
|
7
|
+
require File.expand_path("../lib/beetle", File.dirname(__FILE__))
|
8
|
+
|
9
|
+
# set Beetle log level to info, less noisy than debug
|
10
|
+
Beetle.config.logger.level = Logger::INFO
|
11
|
+
|
12
|
+
# setup client
|
13
|
+
client = Beetle::Client.new
|
14
|
+
client.register_queue(:test)
|
15
|
+
client.register_message(:test)
|
16
|
+
|
17
|
+
# purge the test queue
|
18
|
+
client.purge(:test)
|
19
|
+
|
20
|
+
# empty the dedup store
|
21
|
+
client.deduplication_store.flushdb
|
22
|
+
|
23
|
+
# setup our counter
|
24
|
+
$completed = 0
|
25
|
+
$exceptions_limit = 4
|
26
|
+
|
27
|
+
# store the start time
|
28
|
+
$start_time = Time.now.to_f
|
29
|
+
|
30
|
+
# declare a handler class for message processing
|
31
|
+
# handler fails on the first $exceptions_limit-1 execution attempts, then succeeds
|
32
|
+
class Handler < Beetle::Handler
|
33
|
+
|
34
|
+
# called when the handler receives the message
|
35
|
+
# succeeds on the next and counts up our counter
|
36
|
+
def process
|
37
|
+
logger.info "Attempts: #{message.attempts}, Base Delay: #{message.delay}, Processed at: #{Time.now.to_f - $start_time}"
|
38
|
+
raise "Attempt #{message.attempts} for message #{message.data}" if message.attempts < $exceptions_limit
|
39
|
+
logger.info "Processing of message #{message.data} succeeded on attempt #{message.attempts}. completed: #{$completed += 1}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# called when handler process raised an exception
|
43
|
+
def error(exception)
|
44
|
+
logger.info "Execution failed: #{exception}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# register our handler to the message, configure it to our max_attempts limit, we configure a (base) delay of 1
|
49
|
+
client.register_handler(:test, Handler, exceptions: $exceptions_limit, delay: 1, max_delay: 10)
|
50
|
+
|
51
|
+
# publish test messages
|
52
|
+
client.publish(:test, 1) # publish returns the number of servers the message has been sent to
|
53
|
+
puts "Published 1 test message"
|
54
|
+
|
55
|
+
# start the listening loop
|
56
|
+
client.listen do
|
57
|
+
# catch INT-signal and stop listening
|
58
|
+
trap("INT") { client.stop_listening }
|
59
|
+
# we're adding a periodic timer to check whether all messages have been processed without exceptions
|
60
|
+
timer = EM.add_periodic_timer(1) do
|
61
|
+
if $completed == 1
|
62
|
+
timer.cancel
|
63
|
+
client.stop_listening
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
puts "Handled #{$completed} messages"
|
69
|
+
if $completed != 1
|
70
|
+
raise "Did not handle the correct number of messages"
|
71
|
+
end
|
72
|
+
|
data/lib/beetle/message.rb
CHANGED
@@ -46,6 +46,8 @@ module Beetle
|
|
46
46
|
attr_reader :timeout
|
47
47
|
# how long to wait before retrying the message handler
|
48
48
|
attr_reader :delay
|
49
|
+
# maximum wait time for message handler retries (uses exponential backoff)
|
50
|
+
attr_reader :max_delay
|
49
51
|
# how many times we should try to run the handler
|
50
52
|
attr_reader :attempts_limit
|
51
53
|
# how many exceptions we should tolerate before giving up
|
@@ -71,6 +73,8 @@ module Beetle
|
|
71
73
|
@exceptions_limit = opts[:exceptions] || DEFAULT_EXCEPTION_LIMIT
|
72
74
|
@attempts_limit = @exceptions_limit + 1 if @attempts_limit <= @exceptions_limit
|
73
75
|
@store = opts[:store]
|
76
|
+
max_delay = opts[:max_delay] || @delay
|
77
|
+
@max_delay = max_delay if max_delay >= 2*@delay
|
74
78
|
end
|
75
79
|
|
76
80
|
# extracts various values from the AMQP header properties
|
@@ -186,7 +190,7 @@ module Beetle
|
|
186
190
|
|
187
191
|
# store delay value in the deduplication store
|
188
192
|
def set_delay!
|
189
|
-
@store.set(msg_id, :delay, now +
|
193
|
+
@store.set(msg_id, :delay, now + next_delay(attempts))
|
190
194
|
end
|
191
195
|
|
192
196
|
# how many times we already tried running the handler
|
@@ -362,5 +366,13 @@ module Beetle
|
|
362
366
|
@store.del_keys(msg_id)
|
363
367
|
end
|
364
368
|
end
|
369
|
+
|
370
|
+
def next_delay(n)
|
371
|
+
if max_delay
|
372
|
+
[delay * (2**n), max_delay].min
|
373
|
+
else
|
374
|
+
delay
|
375
|
+
end
|
376
|
+
end
|
365
377
|
end
|
366
378
|
end
|
data/lib/beetle/version.rb
CHANGED
@@ -0,0 +1,174 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
|
2
|
+
|
3
|
+
module Beetle
|
4
|
+
class SettingsTest < Minitest::Test
|
5
|
+
def setup
|
6
|
+
@store = DeduplicationStore.new
|
7
|
+
@store.flushdb
|
8
|
+
end
|
9
|
+
|
10
|
+
test "completed! should store the status 'complete' in the database" do
|
11
|
+
message = Message.new("somequeue", header_with_params, 'foo', :store => @store)
|
12
|
+
assert !message.completed?
|
13
|
+
message.completed!
|
14
|
+
assert message.completed?
|
15
|
+
assert_equal "completed", @store.get(message.msg_id, :status)
|
16
|
+
end
|
17
|
+
|
18
|
+
test "set_delay! should store the current time plus the delay offset in the database" do
|
19
|
+
message = Message.new("somequeue", header_with_params, 'foo', :delay => 2, :store => @store)
|
20
|
+
message.expects(:now).returns(9)
|
21
|
+
message.set_delay!
|
22
|
+
assert_equal "11", @store.get(message.msg_id, :delay)
|
23
|
+
message.expects(:now).returns(12)
|
24
|
+
assert !message.delayed?
|
25
|
+
message.expects(:now).returns(10)
|
26
|
+
assert message.delayed?
|
27
|
+
end
|
28
|
+
|
29
|
+
test "set_delay! should store the current time plus the exponential delay offset in the database" do
|
30
|
+
message = Message.new("somequeue", header_with_params, 'foo', :delay => 3, :max_delay => 30, :store => @store)
|
31
|
+
message.stubs(:now).returns(1)
|
32
|
+
|
33
|
+
[4, 7, 13, 25].each do |exp_delay|
|
34
|
+
message.set_delay!
|
35
|
+
assert_equal exp_delay, @store.get(message.msg_id, :delay).to_i
|
36
|
+
message.increment_execution_attempts!
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
test "set_delay! should store the current time plus the exponential delay offset in the database up to given max value" do
|
41
|
+
message = Message.new("somequeue", header_with_params, 'foo', :delay => 3, :max_delay => 10, :store => @store)
|
42
|
+
message.stubs(:now).returns(1)
|
43
|
+
|
44
|
+
[4, 7, 11, 11].each do |exp_delay|
|
45
|
+
message.set_delay!
|
46
|
+
assert_equal exp_delay, @store.get(message.msg_id, :delay).to_i
|
47
|
+
message.increment_execution_attempts!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
test "set_delay! should store the current time plus the linear delay offset in the database" do
|
52
|
+
delay = 32
|
53
|
+
message = Message.new("somequeue", header_with_params, 'foo', :delay => delay, :store => @store)
|
54
|
+
[3, 5, 6].each do |now_offset|
|
55
|
+
message.stubs(:now).returns(now_offset)
|
56
|
+
message.set_delay!
|
57
|
+
assert_equal @store.get(message.msg_id, :delay).to_i, now_offset + delay
|
58
|
+
message.increment_execution_attempts!
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
test "set_delay! should use the default delay if the delay hasn't been set on the message instance" do
|
63
|
+
message = Message.new("somequeue", header_with_params, 'foo', :store => @store)
|
64
|
+
message.expects(:now).returns(0)
|
65
|
+
message.set_delay!
|
66
|
+
assert_equal "#{Message::DEFAULT_HANDLER_EXECUTION_ATTEMPTS_DELAY}", @store.get(message.msg_id, :delay)
|
67
|
+
message.expects(:now).returns(message.delay)
|
68
|
+
assert !message.delayed?
|
69
|
+
message.expects(:now).returns(0)
|
70
|
+
assert message.delayed?
|
71
|
+
end
|
72
|
+
|
73
|
+
test "set_timeout! should store the current time plus the number of timeout seconds in the database" do
|
74
|
+
message = Message.new("somequeue", header_with_params, 'foo', :timeout => 1, :store => @store)
|
75
|
+
message.expects(:now).returns(1)
|
76
|
+
message.set_timeout!
|
77
|
+
assert_equal "2", @store.get(message.msg_id, :timeout)
|
78
|
+
message.expects(:now).returns(2)
|
79
|
+
assert !message.timed_out?
|
80
|
+
message.expects(:now).returns(3)
|
81
|
+
assert message.timed_out?
|
82
|
+
end
|
83
|
+
|
84
|
+
test "set_timeout! should use the default timeout if the timeout hasn't been set on the message instance" do
|
85
|
+
message = Message.new("somequeue", header_with_params, 'foo', :store => @store)
|
86
|
+
message.expects(:now).returns(0)
|
87
|
+
message.set_timeout!
|
88
|
+
assert_equal "#{Message::DEFAULT_HANDLER_TIMEOUT}", @store.get(message.msg_id, :timeout)
|
89
|
+
message.expects(:now).returns(message.timeout)
|
90
|
+
assert !message.timed_out?
|
91
|
+
message.expects(:now).returns(Message::DEFAULT_HANDLER_TIMEOUT + 1)
|
92
|
+
assert message.timed_out?
|
93
|
+
end
|
94
|
+
|
95
|
+
test "incrementing execution attempts should increment by 1" do
|
96
|
+
message = Message.new("somequeue", header_with_params, 'foo', :store => @store)
|
97
|
+
assert_equal 1, message.increment_execution_attempts!
|
98
|
+
assert_equal 2, message.increment_execution_attempts!
|
99
|
+
assert_equal 3, message.increment_execution_attempts!
|
100
|
+
end
|
101
|
+
|
102
|
+
test "accessing execution attempts should return the number of execution attempts made so far" do
|
103
|
+
message = Message.new("somequeue", header_with_params, 'foo', :store => @store)
|
104
|
+
assert_equal 0, message.attempts
|
105
|
+
message.increment_execution_attempts!
|
106
|
+
assert_equal 1, message.attempts
|
107
|
+
message.increment_execution_attempts!
|
108
|
+
assert_equal 2, message.attempts
|
109
|
+
message.increment_execution_attempts!
|
110
|
+
assert_equal 3, message.attempts
|
111
|
+
end
|
112
|
+
|
113
|
+
test "accessing execution attempts should return 0 if none were made" do
|
114
|
+
message = Message.new("somequeue", header_with_params, 'foo', :store => @store)
|
115
|
+
assert_equal 0, message.attempts
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
test "attempts limit should be set exception limit + 1 iff the configured attempts limit is equal to or smaller than the exceptions limit" do
|
120
|
+
message = Message.new("somequeue", header_with_params, 'foo', :exceptions => 1, :store => @store)
|
121
|
+
assert_equal 2, message.attempts_limit
|
122
|
+
assert_equal 1, message.exceptions_limit
|
123
|
+
message = Message.new("somequeue", header_with_params, 'foo', :exceptions => 2, :store => @store)
|
124
|
+
assert_equal 3, message.attempts_limit
|
125
|
+
assert_equal 2, message.exceptions_limit
|
126
|
+
message = Message.new("somequeue", header_with_params, 'foo', :attempts => 5, :exceptions => 2, :store => @store)
|
127
|
+
assert_equal 5, message.attempts_limit
|
128
|
+
assert_equal 2, message.exceptions_limit
|
129
|
+
end
|
130
|
+
|
131
|
+
test "attempts limit should be reached after incrementing the attempt limit counter 'attempts limit' times" do
|
132
|
+
message = Message.new("somequeue", header_with_params, 'foo', :attempts =>2, :store => @store)
|
133
|
+
assert !message.attempts_limit_reached?
|
134
|
+
message.increment_execution_attempts!
|
135
|
+
assert !message.attempts_limit_reached?
|
136
|
+
message.increment_execution_attempts!
|
137
|
+
assert message.attempts_limit_reached?
|
138
|
+
message.increment_execution_attempts!
|
139
|
+
assert message.attempts_limit_reached?
|
140
|
+
end
|
141
|
+
|
142
|
+
test "incrementing exception counts should increment by 1" do
|
143
|
+
message = Message.new("somequeue", header_with_params, 'foo', :store => @store)
|
144
|
+
assert_equal 1, message.increment_exception_count!
|
145
|
+
assert_equal 2, message.increment_exception_count!
|
146
|
+
assert_equal 3, message.increment_exception_count!
|
147
|
+
end
|
148
|
+
|
149
|
+
test "default exceptions limit should be reached after incrementing the attempt limit counter 1 time" do
|
150
|
+
message = Message.new("somequeue", header_with_params, 'foo', :store => @store)
|
151
|
+
assert !message.exceptions_limit_reached?
|
152
|
+
message.increment_exception_count!
|
153
|
+
assert message.exceptions_limit_reached?
|
154
|
+
end
|
155
|
+
|
156
|
+
test "exceptions limit should be reached after incrementing the attempt limit counter 'exceptions limit + 1' times" do
|
157
|
+
message = Message.new("somequeue", header_with_params, 'foo', :exceptions => 1, :store => @store)
|
158
|
+
assert !message.exceptions_limit_reached?
|
159
|
+
message.increment_exception_count!
|
160
|
+
assert !message.exceptions_limit_reached?
|
161
|
+
message.increment_exception_count!
|
162
|
+
assert message.exceptions_limit_reached?
|
163
|
+
message.increment_exception_count!
|
164
|
+
assert message.exceptions_limit_reached?
|
165
|
+
end
|
166
|
+
|
167
|
+
test "failure to aquire a mutex should delete it from the database" do
|
168
|
+
message = Message.new("somequeue", header_with_params, 'foo', :store => @store)
|
169
|
+
assert message.aquire_mutex!
|
170
|
+
assert !message.aquire_mutex!
|
171
|
+
assert !@store.exists(message.msg_id, :mutex)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
data/test/beetle/message_test.rb
CHANGED
@@ -677,159 +677,6 @@ module Beetle
|
|
677
677
|
end
|
678
678
|
end
|
679
679
|
|
680
|
-
class SettingsTest < Minitest::Test
|
681
|
-
def setup
|
682
|
-
@store = DeduplicationStore.new
|
683
|
-
@store.flushdb
|
684
|
-
end
|
685
|
-
|
686
|
-
test "completed! should store the status 'complete' in the database" do
|
687
|
-
header = header_with_params({})
|
688
|
-
message = Message.new("somequeue", header, 'foo', :store => @store)
|
689
|
-
assert !message.completed?
|
690
|
-
message.completed!
|
691
|
-
assert message.completed?
|
692
|
-
assert_equal "completed", @store.get(message.msg_id, :status)
|
693
|
-
end
|
694
|
-
|
695
|
-
test "set_delay! should store the current time plus the number of delayed seconds in the database" do
|
696
|
-
header = header_with_params({})
|
697
|
-
message = Message.new("somequeue", header, 'foo', :delay => 1, :store => @store)
|
698
|
-
message.expects(:now).returns(1)
|
699
|
-
message.set_delay!
|
700
|
-
assert_equal "2", @store.get(message.msg_id, :delay)
|
701
|
-
message.expects(:now).returns(2)
|
702
|
-
assert !message.delayed?
|
703
|
-
message.expects(:now).returns(0)
|
704
|
-
assert message.delayed?
|
705
|
-
end
|
706
|
-
|
707
|
-
test "set_delay! should use the default delay if the delay hasn't been set on the message instance" do
|
708
|
-
header = header_with_params({})
|
709
|
-
message = Message.new("somequeue", header, 'foo', :store => @store)
|
710
|
-
message.expects(:now).returns(0)
|
711
|
-
message.set_delay!
|
712
|
-
assert_equal "#{Message::DEFAULT_HANDLER_EXECUTION_ATTEMPTS_DELAY}", @store.get(message.msg_id, :delay)
|
713
|
-
message.expects(:now).returns(message.delay)
|
714
|
-
assert !message.delayed?
|
715
|
-
message.expects(:now).returns(0)
|
716
|
-
assert message.delayed?
|
717
|
-
end
|
718
|
-
|
719
|
-
test "set_timeout! should store the current time plus the number of timeout seconds in the database" do
|
720
|
-
header = header_with_params({})
|
721
|
-
message = Message.new("somequeue", header, 'foo', :timeout => 1, :store => @store)
|
722
|
-
message.expects(:now).returns(1)
|
723
|
-
message.set_timeout!
|
724
|
-
assert_equal "2", @store.get(message.msg_id, :timeout)
|
725
|
-
message.expects(:now).returns(2)
|
726
|
-
assert !message.timed_out?
|
727
|
-
message.expects(:now).returns(3)
|
728
|
-
assert message.timed_out?
|
729
|
-
end
|
730
|
-
|
731
|
-
test "set_timeout! should use the default timeout if the timeout hasn't been set on the message instance" do
|
732
|
-
header = header_with_params({})
|
733
|
-
message = Message.new("somequeue", header, 'foo', :store => @store)
|
734
|
-
message.expects(:now).returns(0)
|
735
|
-
message.set_timeout!
|
736
|
-
assert_equal "#{Message::DEFAULT_HANDLER_TIMEOUT}", @store.get(message.msg_id, :timeout)
|
737
|
-
message.expects(:now).returns(message.timeout)
|
738
|
-
assert !message.timed_out?
|
739
|
-
message.expects(:now).returns(Message::DEFAULT_HANDLER_TIMEOUT+1)
|
740
|
-
assert message.timed_out?
|
741
|
-
end
|
742
|
-
|
743
|
-
test "incrementing execution attempts should increment by 1" do
|
744
|
-
header = header_with_params({})
|
745
|
-
message = Message.new("somequeue", header, 'foo', :store => @store)
|
746
|
-
assert_equal 1, message.increment_execution_attempts!
|
747
|
-
assert_equal 2, message.increment_execution_attempts!
|
748
|
-
assert_equal 3, message.increment_execution_attempts!
|
749
|
-
end
|
750
|
-
|
751
|
-
test "accessing execution attempts should return the number of execution attempts made so far" do
|
752
|
-
header = header_with_params({})
|
753
|
-
message = Message.new("somequeue", header, 'foo', :store => @store)
|
754
|
-
assert_equal 0, message.attempts
|
755
|
-
message.increment_execution_attempts!
|
756
|
-
assert_equal 1, message.attempts
|
757
|
-
message.increment_execution_attempts!
|
758
|
-
assert_equal 2, message.attempts
|
759
|
-
message.increment_execution_attempts!
|
760
|
-
assert_equal 3, message.attempts
|
761
|
-
end
|
762
|
-
|
763
|
-
test "accessing execution attempts should return 0 if none were made" do
|
764
|
-
header = header_with_params({})
|
765
|
-
message = Message.new("somequeue", header, 'foo', :store => @store)
|
766
|
-
assert_equal 0, message.attempts
|
767
|
-
end
|
768
|
-
|
769
|
-
|
770
|
-
test "attempts limit should be set exception limit + 1 iff the configured attempts limit is equal to or smaller than the exceptions limit" do
|
771
|
-
header = header_with_params({})
|
772
|
-
message = Message.new("somequeue", header, 'foo', :exceptions => 1, :store => @store)
|
773
|
-
assert_equal 2, message.attempts_limit
|
774
|
-
assert_equal 1, message.exceptions_limit
|
775
|
-
message = Message.new("somequeue", header, 'foo', :exceptions => 2, :store => @store)
|
776
|
-
assert_equal 3, message.attempts_limit
|
777
|
-
assert_equal 2, message.exceptions_limit
|
778
|
-
message = Message.new("somequeue", header, 'foo', :attempts => 5, :exceptions => 2, :store => @store)
|
779
|
-
assert_equal 5, message.attempts_limit
|
780
|
-
assert_equal 2, message.exceptions_limit
|
781
|
-
end
|
782
|
-
|
783
|
-
test "attempts limit should be reached after incrementing the attempt limit counter 'attempts limit' times" do
|
784
|
-
header = header_with_params({})
|
785
|
-
message = Message.new("somequeue", header, 'foo', :attempts =>2, :store => @store)
|
786
|
-
assert !message.attempts_limit_reached?
|
787
|
-
message.increment_execution_attempts!
|
788
|
-
assert !message.attempts_limit_reached?
|
789
|
-
message.increment_execution_attempts!
|
790
|
-
assert message.attempts_limit_reached?
|
791
|
-
message.increment_execution_attempts!
|
792
|
-
assert message.attempts_limit_reached?
|
793
|
-
end
|
794
|
-
|
795
|
-
test "incrementing exception counts should increment by 1" do
|
796
|
-
header = header_with_params({})
|
797
|
-
message = Message.new("somequeue", header, 'foo', :store => @store)
|
798
|
-
assert_equal 1, message.increment_exception_count!
|
799
|
-
assert_equal 2, message.increment_exception_count!
|
800
|
-
assert_equal 3, message.increment_exception_count!
|
801
|
-
end
|
802
|
-
|
803
|
-
test "default exceptions limit should be reached after incrementing the attempt limit counter 1 time" do
|
804
|
-
header = header_with_params({})
|
805
|
-
message = Message.new("somequeue", header, 'foo', :store => @store)
|
806
|
-
assert !message.exceptions_limit_reached?
|
807
|
-
message.increment_exception_count!
|
808
|
-
assert message.exceptions_limit_reached?
|
809
|
-
end
|
810
|
-
|
811
|
-
test "exceptions limit should be reached after incrementing the attempt limit counter 'exceptions limit + 1' times" do
|
812
|
-
header = header_with_params({})
|
813
|
-
message = Message.new("somequeue", header, 'foo', :exceptions => 1, :store => @store)
|
814
|
-
assert !message.exceptions_limit_reached?
|
815
|
-
message.increment_exception_count!
|
816
|
-
assert !message.exceptions_limit_reached?
|
817
|
-
message.increment_exception_count!
|
818
|
-
assert message.exceptions_limit_reached?
|
819
|
-
message.increment_exception_count!
|
820
|
-
assert message.exceptions_limit_reached?
|
821
|
-
end
|
822
|
-
|
823
|
-
test "failure to aquire a mutex should delete it from the database" do
|
824
|
-
header = header_with_params({})
|
825
|
-
message = Message.new("somequeue", header, 'foo', :store => @store)
|
826
|
-
assert message.aquire_mutex!
|
827
|
-
assert !message.aquire_mutex!
|
828
|
-
assert !@store.exists(message.msg_id, :mutex)
|
829
|
-
end
|
830
|
-
end
|
831
|
-
|
832
|
-
|
833
680
|
class RoutingKeyTest < Minitest::Test
|
834
681
|
test "returns the routing key" do
|
835
682
|
header = header_with_params({})
|
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: 2.0
|
4
|
+
version: 2.1.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: 2017-
|
15
|
+
date: 2017-12-01 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: uuid4r
|
@@ -314,6 +314,8 @@ files:
|
|
314
314
|
- beetle.gemspec
|
315
315
|
- examples/README.rdoc
|
316
316
|
- examples/attempts.rb
|
317
|
+
- examples/attempts_with_dead_letter_and_exponential_backoff.rb
|
318
|
+
- examples/attempts_with_exponential_backoff.rb
|
317
319
|
- examples/consume_many_messages_and_shutdown_randomly.rb
|
318
320
|
- examples/handler_class.rb
|
319
321
|
- examples/handling_exceptions.rb
|
@@ -361,6 +363,7 @@ files:
|
|
361
363
|
- test/beetle/dead_lettering_test.rb
|
362
364
|
- test/beetle/deduplication_store_test.rb
|
363
365
|
- test/beetle/handler_test.rb
|
366
|
+
- test/beetle/message/settings_test.rb
|
364
367
|
- test/beetle/message_test.rb
|
365
368
|
- test/beetle/publisher_test.rb
|
366
369
|
- test/beetle/r_c_test.rb
|
@@ -389,7 +392,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
389
392
|
version: 1.3.7
|
390
393
|
requirements: []
|
391
394
|
rubyforge_project:
|
392
|
-
rubygems_version: 2.6.
|
395
|
+
rubygems_version: 2.6.14
|
393
396
|
signing_key:
|
394
397
|
specification_version: 3
|
395
398
|
summary: High Availability AMQP Messaging with Redundant Queues
|
@@ -402,6 +405,7 @@ test_files:
|
|
402
405
|
- test/beetle/dead_lettering_test.rb
|
403
406
|
- test/beetle/deduplication_store_test.rb
|
404
407
|
- test/beetle/handler_test.rb
|
408
|
+
- test/beetle/message/settings_test.rb
|
405
409
|
- test/beetle/message_test.rb
|
406
410
|
- test/beetle/publisher_test.rb
|
407
411
|
- test/beetle/r_c_test.rb
|