-
Notifications
You must be signed in to change notification settings - Fork 47
Retry pushing message 5 times, then reject the message #1545
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -93,6 +93,13 @@ module LavinMQ | |
| end | ||
| end | ||
|
|
||
| def reject(delivery_tag) | ||
| if ch = @ch | ||
| return if ch.closed? | ||
| ch.basic_reject(delivery_tag, requeue: true) | ||
| end | ||
| end | ||
|
|
||
| def started? : Bool | ||
| [email protected]? && [email protected] &.closed? | ||
| end | ||
|
|
@@ -183,7 +190,7 @@ module LavinMQ | |
|
|
||
| abstract def stop | ||
|
|
||
| abstract def push(msg, source) | ||
| abstract def push(msg, source) : Bool | ||
|
|
||
| abstract def started? : Bool | ||
| end | ||
|
|
@@ -207,8 +214,12 @@ module LavinMQ | |
| @current_dest = nil | ||
| end | ||
|
|
||
| def push(msg, source) | ||
| @current_dest.try &.push(msg, source) | ||
| def push(msg, source) : Bool | ||
| if dest = @current_dest | ||
| dest.push(msg, source) | ||
| else | ||
| false | ||
| end | ||
| end | ||
|
|
||
| def started? : Bool | ||
|
|
@@ -272,21 +283,26 @@ module LavinMQ | |
| [email protected]? && [email protected] &.closed? | ||
| end | ||
|
|
||
| def push(msg, source) | ||
| def push(msg, source) : Bool | ||
| raise "Not started" unless started? | ||
| ch = @ch.not_nil! | ||
| ex = @exchange || msg.exchange | ||
| rk = @exchange_key || msg.routing_key | ||
| case @ack_mode | ||
| in AckMode::OnConfirm | ||
| ch.basic_publish(msg.body_io, ex, rk, props: msg.properties) do | ||
| if ch.basic_publish_confirm(msg.body_io, ex, rk, props: msg.properties) | ||
| source.ack(msg.delivery_tag) | ||
| true | ||
| else | ||
| false | ||
| end | ||
| in AckMode::OnPublish | ||
| ch.basic_publish(msg.body_io, ex, rk, props: msg.properties) | ||
| source.ack(msg.delivery_tag) | ||
| true | ||
| in AckMode::NoAck | ||
| ch.basic_publish(msg.body_io, ex, rk, props: msg.properties) | ||
| true | ||
| end | ||
| end | ||
| end | ||
|
|
@@ -314,7 +330,7 @@ module LavinMQ | |
| [email protected]? | ||
| end | ||
|
|
||
| def push(msg, source) | ||
| def push(msg, source) : Bool | ||
| raise "Not started" unless started? | ||
| c = @client.not_nil! | ||
| headers = ::HTTP::Headers{"User-Agent" => "LavinMQ"} | ||
|
|
@@ -341,6 +357,7 @@ module LavinMQ | |
| source.ack(msg.delivery_tag) | ||
| in AckMode::NoAck | ||
| end | ||
| true | ||
| end | ||
| end | ||
|
|
||
|
|
@@ -368,7 +385,7 @@ module LavinMQ | |
| @state | ||
| end | ||
|
|
||
| def run | ||
| def run # ameba:disable Metrics/CyclomaticComplexity | ||
| Log.context.set(name: @name, vhost: @vhost.name) | ||
| loop do | ||
| break if should_stop_loop? | ||
|
|
@@ -382,7 +399,15 @@ module LavinMQ | |
| @retries = 0 | ||
| @source.each do |msg| | ||
| @message_count += 1 | ||
| @destination.push(msg, @source) | ||
| push_retries = 0 | ||
| until @destination.push(msg, @source) | ||
| if push_retries >= 5 | ||
| @source.reject(msg.delivery_tag) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wasn't the message rejected with requeue? that means the message will be retried soon again?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea is to try 5 times and then put the message back in the queue so it could be removed or consumed by another consumer. |
||
| break | ||
| end | ||
| push_retries += 1 | ||
| sleep 500.milliseconds | ||
| end | ||
| end | ||
| break if should_stop_loop? # Don't delete shovel if paused/terminated | ||
| @vhost.delete_parameter("shovel", @name) if @source.delete_after.queue_length? | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fyi, the block to
basic_publishtakes a boolean too, the result from the confirm (ack/nack).The upside/downside with this approach is that this fiber is blocked until an ack/nack is recievied from the server, hampering the throughput, but also limits the number of messages not confirmed (to 1)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could reject in the block instead, with requeue if the
x-delivery-countis less than 5, and without requeue if > 5. Or even use thedelivery-limitqueue argument/policy somehow, instead of this hardcoded one.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of using deliver limit. But then again, the message will be removed from the queue and "disappear" if there is no DLX configured.
What I wanted to achieve with this PR is that the shovel basically just waits until the destination is available again, as a default behavior.