changed exponential backoff interface
MODIFY
examples/attempts_with_dead_letter_and_exponential_backoff.rb
examples/attempts_with_dead_letter_and_exponential_backoff.rb
@@ -48,7 +48,7 @@ class Handler < Beetle::Handler
end
# register our handler to the message, configure it to our max_attempts limit, we configure a (base) delay of 0.5
-client.register_handler(:test, Handler, exceptions: $exceptions_limit, delay: 1, exponential_back_off: true)
+client.register_handler(:test, Handler, exceptions: $exceptions_limit, delay: 1, max_delay: 10)
# publish test messages
client.publish(:test, 1) # publish returns the number of servers the message has been sent to
puts "published 1 test message"

MODIFY
examples/attempts_with_exponential_backoff.rb
examples/attempts_with_exponential_backoff.rb
@@ -46,7 +46,7 @@ class Handler < Beetle::Handler
end
# register our handler to the message, configure it to our max_attempts limit, we configure a (base) delay of 1
-client.register_handler(:test, Handler, exceptions: $exceptions_limit, delay: 1, exponential_back_off: true)
+client.register_handler(:test, Handler, exceptions: $exceptions_limit, delay: 1, max_delay: 10)
# publish test messages
client.publish(:test, 1) # publish returns the number of servers the message has been sent to

MODIFY
lib/beetle/message.rb
lib/beetle/message.rb
@@ -16,11 +16,11 @@ module Beetle
DEFAULT_TTL = 1.day
# forcefully abort a running handler after this many seconds.
# can be overriden when registering a handler.
- DEFAULT_HANDLER_TIMEOUT = 600
+ DEFAULT_HANDLER_TIMEOUT = 600.seconds
# how many times we should try to run a handler before giving up
DEFAULT_HANDLER_EXECUTION_ATTEMPTS = 1
# how many seconds we should wait before retrying handler execution
- DEFAULT_HANDLER_EXECUTION_ATTEMPTS_DELAY = 10
+ DEFAULT_HANDLER_EXECUTION_ATTEMPTS_DELAY = 10.seconds
# how many exceptions should be tolerated before giving up
DEFAULT_EXCEPTION_LIMIT = 0
@@ -46,6 +46,8 @@ module Beetle
attr_reader :timeout
# how long to wait before retrying the message handler
attr_reader :delay
+ # maximum wait time for message handler retries (uses exponential backoff)
+ attr_reader :max_delay
# how many times we should try to run the handler
attr_reader :attempts_limit
# how many exceptions we should tolerate before giving up
@@ -67,11 +69,12 @@ module Beetle
@server = opts[:server]
@timeout = opts[:timeout] || DEFAULT_HANDLER_TIMEOUT
@delay = opts[:delay] || DEFAULT_HANDLER_EXECUTION_ATTEMPTS_DELAY
- @max_exp_bo = opts[:exponential_back_off]&.to_i
@attempts_limit = opts[:attempts] || DEFAULT_HANDLER_EXECUTION_ATTEMPTS
@exceptions_limit = opts[:exceptions] || DEFAULT_EXCEPTION_LIMIT
@attempts_limit = @exceptions_limit + 1 if @attempts_limit <= @exceptions_limit
@store = opts[:store]
+ max_delay = opts[:max_delay] || @delay
+ @max_delay = max_delay if max_delay >= 2*@delay
end
# extracts various values from the AMQP header properties
@@ -187,8 +190,7 @@ module Beetle
# store delay value in the deduplication store
def set_delay!
- next_delay = calculate_next_delay(attempts, delay)
- @store.set(msg_id, :delay, now + next_delay)
+ @store.set(msg_id, :delay, now + next_delay(attempts))
end
# how many times we already tried running the handler
@@ -365,19 +367,11 @@ module Beetle
end
end
- def exponential_back_off?
- @max_exp_bo.present?
- end
-
- def max_exp_bo_delay
- @max_exp_bo
- end
-
- def calculate_next_delay(n, base_delay)
- unless exponential_back_off?
- base_delay
+ def next_delay(n)
+ if max_delay
+ [delay * (2**n), max_delay].min
else
- [base_delay * (2**n), max_exp_bo_delay].min
+ delay
end
end
end

MODIFY
test/beetle/message/settings_test.rb
test/beetle/message/settings_test.rb
@@ -27,7 +27,7 @@ module Beetle
end
test "set_delay! should store the current time plus the exponential delay offset in the database" do
- message = Message.new("somequeue", header_with_params, 'foo', :delay => 3, :exponential_back_off => 30, :store => @store)
+ message = Message.new("somequeue", header_with_params, 'foo', :delay => 3, :max_delay => 30, :store => @store)
message.stubs(:now).returns(1)
[4, 7, 13, 25].each do |exp_delay|
@@ -38,7 +38,7 @@ module Beetle
end
test "set_delay! should store the current time plus the exponential delay offset in the database up to given max value" do
- message = Message.new("somequeue", header_with_params, 'foo', :delay => 3, :exponential_back_off => 10, :store => @store)
+ message = Message.new("somequeue", header_with_params, 'foo', :delay => 3, :max_delay => 10, :store => @store)
message.stubs(:now).returns(1)
[4, 7, 11, 11].each do |exp_delay|
@@ -50,7 +50,7 @@ module Beetle
test "set_delay! should store the current time plus the linear delay offset in the database" do
delay = 32
- message = Message.new("somequeue", header_with_params, 'foo', :delay => delay, :exponential_back_off => nil, :store => @store)
+ message = Message.new("somequeue", header_with_params, 'foo', :delay => delay, :store => @store)
[3, 5, 6].each do |now_offset|
message.stubs(:now).returns(now_offset)
message.set_delay!

changed exponential backoff interface