我正在尝试制作一个执行以下操作的程序:
我已经成功实现了回调、错误处理和重试逻辑,但是我的实现中有一些问题,因为将回调与重试逻辑结合起来会破坏错误处理。
这个节目:
def print_attempt_number(proc_id:, &callback)
random = [true, false].sample
if random
message = "Attempt for ID: #{proc_id}"
callback.call(proc_id, message) if callback
# puts "PUTS: #{message}"
else
raise StandardError, "This is my error message"
end
end
def handle_error(proc_id:, retries:, max_retries:, &callback)
retries += 1
retry_msg = "Retry #{retries} / #{max_retries}"
# puts "PUTS: #{retry_msg}"
callback.call(proc_id, retry_msg)
return retries
end
def with_retries(max_retries:, proc_id:, &callback)
retries = 0
begin
yield
rescue StandardError => e
retries = handle_error(proc_id: proc_id, retries: retries, max_retries: max_retries, &callback)
sleep 1.0
retry if retries < max_retries
end
end
def process_item(proc_id:, &callback)
init_msg = "Starting with #{proc_id}"
callback.call(proc_id, init_msg)
with_retries(max_retries: 3, proc_id:) do
print_attempt_number(proc_id: proc_id, &callback)
end
end
callback = Proc.new do |proc_id, message|
puts "CALLBACK: #{proc_id}\t#{message}"
end
for id in 1..5 do
process_item(proc_id: id, &callback)
sleep 1.0
end
产生这个结果:
CALLBACK: 1 Starting with 1
CALLBACK: 1 Attempt for ID: 1
CALLBACK: 2 Starting with 2
CALLBACK: 2 Attempt for ID: 2
callback_test.rb:8:in `print_attempt_number': This is my error message (StandardError)
from callback_test.rb:38:in `block in process_item'
from callback_test.rb:16:in `handle_error'
from callback_test.rb:25:in `rescue in with_retries'
from callback_test.rb:22:in `with_retries'
from callback_test.rb:37:in `process_item'
from callback_test.rb:49:in `block in <main>'
from callback_test.rb:48:in `each'
from callback_test.rb:48:in `<main>'
callback_test.rb:8:in `print_attempt_number': This is my error message (StandardError)
from callback_test.rb:38:in `block in process_item'
from callback_test.rb:23:in `with_retries'
from callback_test.rb:37:in `process_item'
from callback_test.rb:49:in `block in <main>'
from callback_test.rb:48:in `each'
from callback_test.rb:48:in `<main>'
但是,从
callback
直接切换到 puts
会产生预期的结果:
def print_attempt_number(proc_id:, &callback)
random = [true, false].sample
if random
message = "Attempt for ID: #{proc_id}"
# callback.call(proc_id, message) if callback
puts "PUTS: #{message}"
else
raise StandardError, "This is my error message"
end
end
def handle_error(proc_id:, retries:, max_retries:, &callback)
retries += 1
retry_msg = "Retry #{retries} / #{max_retries}"
puts "PUTS: #{retry_msg}"
# callback.call(proc_id, retry_msg)
return retries
end
def with_retries(max_retries:, proc_id:, &callback)
retries = 0
begin
yield
rescue StandardError => e
retries = handle_error(proc_id: proc_id, retries: retries, max_retries: max_retries, &callback)
sleep 1.0
retry if retries < max_retries
end
end
def process_item(proc_id:, &callback)
init_msg = "Starting with #{proc_id}"
callback.call(proc_id, init_msg)
with_retries(max_retries: 3, proc_id:) do
print_attempt_number(proc_id: proc_id, &callback)
end
end
callback = Proc.new do |proc_id, message|
puts "CALLBACK: #{proc_id}\t#{message}"
end
for id in 1..5 do
process_item(proc_id: id, &callback)
sleep 1.0
end
产生:
CALLBACK: 1 Starting with 1
PUTS: Attempt for ID: 1
CALLBACK: 2 Starting with 2
PUTS: Retry 1 / 3
PUTS: Attempt for ID: 2
CALLBACK: 3 Starting with 3
PUTS: Retry 1 / 3
PUTS: Attempt for ID: 3
CALLBACK: 4 Starting with 4
PUTS: Retry 1 / 3
PUTS: Retry 2 / 3
PUTS: Retry 3 / 3
CALLBACK: 5 Starting with 5
PUTS: Attempt for ID: 5
我不明白为什么会发生这种情况;如何使用打印消息的回调来实现所需的打印?
显然,不将其作为块传递(没有
&
)解决了我的用例:
def print_attempt_number(proc_id, callback)
random = [true, false].sample
if random
message = "Attempt for ID: #{proc_id}"
callback.call(proc_id, message) # Use callback without block syntax
else
raise StandardError, "This is my error message"
end
end
def handle_error(proc_id, retries, max_retries, callback)
retries += 1
retry_msg = "Retry #{retries} / #{max_retries}"
callback.call(proc_id, retry_msg) # Use callback without block syntax
retries
end
def with_retries(max_retries, proc_id, callback)
retries = 0
begin
yield # Execute the block provided to with_retries
rescue StandardError => e
retries = handle_error(proc_id, retries, max_retries, callback)
sleep 1.0
retry if retries < max_retries
end
end
def process_item(proc_id, callback)
init_msg = "Starting with #{proc_id}"
callback.call(proc_id, init_msg) # Call the callback with init message
with_retries(3, proc_id, callback) do
print_attempt_number(proc_id, callback) # Pass callback without using & syntax
end
end
callback = Proc.new do |proc_id, message|
puts "CALLBACK: #{proc_id}\t#{message}"
end
for id in 1..5 do
process_item(id, callback)
sleep 1.0
end