beetle 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|