karafka 2.3.1 → 2.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +6 -6
- data/bin/integrations +2 -1
- data/bin/rspecs +6 -2
- data/config/locales/errors.yml +30 -8
- data/config/locales/pro_errors.yml +2 -0
- data/docker-compose.yml +1 -1
- data/lib/karafka/app.rb +14 -0
- data/lib/karafka/cli/base.rb +19 -0
- data/lib/karafka/cli/server.rb +62 -76
- data/lib/karafka/cli/swarm.rb +30 -0
- data/lib/karafka/constraints.rb +3 -3
- data/lib/karafka/contracts/config.rb +19 -0
- data/lib/karafka/errors.rb +12 -0
- data/lib/karafka/helpers/config_importer.rb +30 -0
- data/lib/karafka/instrumentation/logger_listener.rb +31 -0
- data/lib/karafka/instrumentation/notifications.rb +9 -0
- data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +2 -0
- data/lib/karafka/instrumentation/vendors/kubernetes/base_listener.rb +72 -0
- data/lib/karafka/instrumentation/vendors/kubernetes/liveness_listener.rb +11 -40
- data/lib/karafka/instrumentation/vendors/kubernetes/swarm_liveness_listener.rb +54 -0
- data/lib/karafka/pro/active_job/job_options_contract.rb +1 -1
- data/lib/karafka/pro/base_consumer.rb +16 -0
- data/lib/karafka/pro/connection/manager.rb +6 -1
- data/lib/karafka/pro/processing/coordinator.rb +13 -3
- data/lib/karafka/pro/processing/coordinators/errors_tracker.rb +74 -0
- data/lib/karafka/pro/processing/coordinators/filters_applier.rb +107 -0
- data/lib/karafka/pro/processing/coordinators/virtual_offset_manager.rb +180 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom.rb +5 -7
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom_vp.rb +5 -7
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom.rb +8 -10
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom_vp.rb +8 -16
- data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom.rb +5 -7
- data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom_vp.rb +5 -7
- data/lib/karafka/pro/processing/strategies/aj/dlq_mom.rb +8 -10
- data/lib/karafka/pro/processing/strategies/aj/dlq_mom_vp.rb +7 -9
- data/lib/karafka/pro/processing/strategies/dlq/default.rb +36 -10
- data/lib/karafka/pro/processing/strategies/dlq/ftr.rb +3 -7
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj.rb +4 -8
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom.rb +6 -9
- data/lib/karafka/pro/processing/strategies/dlq/ftr_mom.rb +5 -15
- data/lib/karafka/pro/processing/strategies/dlq/lrj.rb +4 -8
- data/lib/karafka/pro/processing/strategies/dlq/lrj_mom.rb +6 -9
- data/lib/karafka/pro/processing/strategies/dlq/mom.rb +10 -20
- data/lib/karafka/pro/processing/strategies/vp/default.rb +7 -0
- data/lib/karafka/pro/routing/features/dead_letter_queue/contracts/topic.rb +6 -0
- data/lib/karafka/pro/routing/features/dead_letter_queue/topic.rb +39 -0
- data/lib/karafka/pro/swarm/liveness_listener.rb +171 -0
- data/lib/karafka/process.rb +27 -1
- data/lib/karafka/routing/features/dead_letter_queue/config.rb +2 -0
- data/lib/karafka/routing/subscription_group.rb +31 -9
- data/lib/karafka/server.rb +11 -13
- data/lib/karafka/setup/config.rb +41 -2
- data/lib/karafka/status.rb +4 -2
- data/lib/karafka/swarm/liveness_listener.rb +55 -0
- data/lib/karafka/swarm/manager.rb +217 -0
- data/lib/karafka/swarm/node.rb +179 -0
- data/lib/karafka/swarm/pidfd.rb +131 -0
- data/lib/karafka/swarm/supervisor.rb +184 -0
- data/lib/karafka/swarm.rb +27 -0
- data/lib/karafka/version.rb +1 -1
- data/lib/karafka.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +17 -4
- metadata.gz.sig +0 -0
- data/lib/karafka/pro/processing/filters_applier.rb +0 -105
- data/lib/karafka/pro/processing/virtual_offset_manager.rb +0 -177
@@ -51,14 +51,12 @@ module Karafka
|
|
51
51
|
else
|
52
52
|
resume
|
53
53
|
end
|
54
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
55
|
-
retry_after_pause
|
56
54
|
else
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
apply_dlq_flow do
|
56
|
+
skippable_message, = find_skippable_message
|
57
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
58
|
+
mark_as_consumed(skippable_message)
|
59
|
+
end
|
62
60
|
end
|
63
61
|
end
|
64
62
|
end
|
@@ -57,14 +57,12 @@ module Karafka
|
|
57
57
|
else
|
58
58
|
resume
|
59
59
|
end
|
60
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
61
|
-
retry_after_pause
|
62
60
|
else
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
61
|
+
apply_dlq_flow do
|
62
|
+
skippable_message, = find_skippable_message
|
63
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
64
|
+
mark_as_consumed(skippable_message)
|
65
|
+
end
|
68
66
|
end
|
69
67
|
end
|
70
68
|
end
|
@@ -44,8 +44,6 @@ module Karafka
|
|
44
44
|
return if coordinator.manual_pause?
|
45
45
|
|
46
46
|
handle_post_filtering
|
47
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
48
|
-
retry_after_pause
|
49
47
|
# If we've reached number of retries that we could, we need to skip the first
|
50
48
|
# message that was not marked as consumed, pause and continue, while also moving
|
51
49
|
# this message to the dead topic.
|
@@ -53,14 +51,14 @@ module Karafka
|
|
53
51
|
# For a Mom setup, this means, that user has to manage the checkpointing by
|
54
52
|
# himself. If no checkpointing is ever done, we end up with an endless loop.
|
55
53
|
else
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
54
|
+
apply_dlq_flow do
|
55
|
+
skippable_message, = find_skippable_message
|
56
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
57
|
+
# We can commit the offset here because we know that we skip it "forever" and
|
58
|
+
# since AJ consumer commits the offset after each job, we also know that the
|
59
|
+
# previous job was successful
|
60
|
+
mark_as_consumed(skippable_message)
|
61
|
+
end
|
64
62
|
end
|
65
63
|
end
|
66
64
|
end
|
@@ -48,23 +48,15 @@ module Karafka
|
|
48
48
|
mark_as_consumed(last_group_message)
|
49
49
|
|
50
50
|
handle_post_filtering
|
51
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
52
|
-
retry_after_pause
|
53
|
-
# If we've reached number of retries that we could, we need to skip the first
|
54
|
-
# message that was not marked as consumed, pause and continue, while also moving
|
55
|
-
# this message to the dead topic.
|
56
|
-
#
|
57
|
-
# For a Mom setup, this means, that user has to manage the checkpointing by
|
58
|
-
# himself. If no checkpointing is ever done, we end up with an endless loop.
|
59
51
|
else
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
52
|
+
apply_dlq_flow do
|
53
|
+
skippable_message, = find_skippable_message
|
54
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
55
|
+
# We can commit the offset here because we know that we skip it "forever" and
|
56
|
+
# since AJ consumer commits the offset after each job, we also know that the
|
57
|
+
# previous job was successful
|
58
|
+
mark_as_consumed(skippable_message)
|
59
|
+
end
|
68
60
|
end
|
69
61
|
end
|
70
62
|
end
|
@@ -47,14 +47,12 @@ module Karafka
|
|
47
47
|
seek(coordinator.seek_offset, false) unless revoked?
|
48
48
|
|
49
49
|
resume
|
50
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
51
|
-
retry_after_pause
|
52
50
|
else
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
51
|
+
apply_dlq_flow do
|
52
|
+
skippable_message, = find_skippable_message
|
53
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
54
|
+
mark_as_consumed(skippable_message)
|
55
|
+
end
|
58
56
|
end
|
59
57
|
end
|
60
58
|
end
|
@@ -51,14 +51,12 @@ module Karafka
|
|
51
51
|
seek(coordinator.seek_offset, false) unless revoked?
|
52
52
|
|
53
53
|
resume
|
54
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
55
|
-
retry_after_pause
|
56
54
|
else
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
apply_dlq_flow do
|
56
|
+
skippable_message, = find_skippable_message
|
57
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
58
|
+
mark_as_consumed(skippable_message)
|
59
|
+
end
|
62
60
|
end
|
63
61
|
end
|
64
62
|
end
|
@@ -42,17 +42,15 @@ module Karafka
|
|
42
42
|
if coordinator.success?
|
43
43
|
# Do NOT commit offsets, they are comitted after each job in the AJ consumer.
|
44
44
|
coordinator.pause_tracker.reset
|
45
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
46
|
-
retry_after_pause
|
47
45
|
else
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
46
|
+
apply_dlq_flow do
|
47
|
+
skippable_message, = find_skippable_message
|
48
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
49
|
+
# We can commit the offset here because we know that we skip it "forever" and
|
50
|
+
# since AJ consumer commits the offset after each job, we also know that the
|
51
|
+
# previous job was successful
|
52
|
+
mark_as_consumed(skippable_message)
|
53
|
+
end
|
56
54
|
end
|
57
55
|
end
|
58
56
|
end
|
@@ -48,16 +48,14 @@ module Karafka
|
|
48
48
|
return if revoked?
|
49
49
|
|
50
50
|
mark_as_consumed(last_group_message)
|
51
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
52
|
-
retry_after_pause
|
53
51
|
else
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
52
|
+
apply_dlq_flow do
|
53
|
+
# Here we are in a collapsed state, hence we can apply the same logic as
|
54
|
+
# Aj::DlqMom
|
55
|
+
skippable_message, = find_skippable_message
|
56
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
57
|
+
mark_as_consumed(skippable_message)
|
58
|
+
end
|
61
59
|
end
|
62
60
|
end
|
63
61
|
end
|
@@ -76,16 +76,10 @@ module Karafka
|
|
76
76
|
return if coordinator.manual_pause?
|
77
77
|
|
78
78
|
mark_as_consumed(last_group_message)
|
79
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
80
|
-
retry_after_pause
|
81
|
-
# If we've reached number of retries that we could, we need to skip the first
|
82
|
-
# message that was not marked as consumed, pause and continue, while also moving
|
83
|
-
# this message to the dead topic
|
84
79
|
else
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
pause(coordinator.seek_offset, nil, false)
|
80
|
+
apply_dlq_flow do
|
81
|
+
dispatch_if_needed_and_mark_as_consumed
|
82
|
+
end
|
89
83
|
end
|
90
84
|
end
|
91
85
|
end
|
@@ -183,7 +177,10 @@ module Karafka
|
|
183
177
|
# topic is set to false, we will skip the dispatch, effectively ignoring the broken
|
184
178
|
# message without taking any action.
|
185
179
|
def dispatch_to_dlq?
|
186
|
-
topic.dead_letter_queue.topic
|
180
|
+
return false unless topic.dead_letter_queue.topic
|
181
|
+
return false unless @_dispatch_to_dlq
|
182
|
+
|
183
|
+
true
|
187
184
|
end
|
188
185
|
|
189
186
|
# @return [Boolean] should we use a transaction to move the data to the DLQ.
|
@@ -192,6 +189,35 @@ module Karafka
|
|
192
189
|
def dispatch_in_a_transaction?
|
193
190
|
producer.transactional? && topic.dead_letter_queue.transactional?
|
194
191
|
end
|
192
|
+
|
193
|
+
# Runs the DLQ strategy and based on it it performs certain operations
|
194
|
+
#
|
195
|
+
# In case of `:skip` and `:dispatch` will run the exact flow provided in a block
|
196
|
+
# In case of `:retry` always `#retry_after_pause` is applied
|
197
|
+
def apply_dlq_flow
|
198
|
+
flow = topic.dead_letter_queue.strategy.call(errors_tracker, attempt)
|
199
|
+
|
200
|
+
case flow
|
201
|
+
when :retry
|
202
|
+
retry_after_pause
|
203
|
+
|
204
|
+
return
|
205
|
+
when :skip
|
206
|
+
@_dispatch_to_dlq = false
|
207
|
+
when :dispatch
|
208
|
+
@_dispatch_to_dlq = true
|
209
|
+
else
|
210
|
+
raise Karafka::UnsupportedCaseError, flow
|
211
|
+
end
|
212
|
+
|
213
|
+
# We reset the pause to indicate we will now consider it as "ok".
|
214
|
+
coordinator.pause_tracker.reset
|
215
|
+
|
216
|
+
yield
|
217
|
+
|
218
|
+
# Always backoff after DLQ dispatch even on skip to prevent overloads on errors
|
219
|
+
pause(coordinator.seek_offset, nil, false)
|
220
|
+
end
|
195
221
|
end
|
196
222
|
end
|
197
223
|
end
|
@@ -42,14 +42,10 @@ module Karafka
|
|
42
42
|
mark_as_consumed(last_group_message)
|
43
43
|
|
44
44
|
handle_post_filtering
|
45
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
46
|
-
retry_after_pause
|
47
45
|
else
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
pause(coordinator.seek_offset, nil, false)
|
46
|
+
apply_dlq_flow do
|
47
|
+
dispatch_if_needed_and_mark_as_consumed
|
48
|
+
end
|
53
49
|
end
|
54
50
|
end
|
55
51
|
end
|
@@ -53,16 +53,12 @@ module Karafka
|
|
53
53
|
else
|
54
54
|
resume
|
55
55
|
end
|
56
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
57
|
-
retry_after_pause
|
58
56
|
else
|
59
|
-
|
60
|
-
|
61
|
-
return resume if revoked?
|
57
|
+
apply_dlq_flow do
|
58
|
+
return resume if revoked?
|
62
59
|
|
63
|
-
|
64
|
-
|
65
|
-
pause(coordinator.seek_offset, nil, false)
|
60
|
+
dispatch_if_needed_and_mark_as_consumed
|
61
|
+
end
|
66
62
|
end
|
67
63
|
end
|
68
64
|
end
|
@@ -48,18 +48,15 @@ module Karafka
|
|
48
48
|
else
|
49
49
|
resume
|
50
50
|
end
|
51
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
52
|
-
retry_after_pause
|
53
51
|
else
|
54
|
-
|
55
|
-
|
56
|
-
return resume if revoked?
|
52
|
+
apply_dlq_flow do
|
53
|
+
return resume if revoked?
|
57
54
|
|
58
|
-
|
59
|
-
|
55
|
+
skippable_message, _marked = find_skippable_message
|
56
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
60
57
|
|
61
|
-
|
62
|
-
|
58
|
+
coordinator.seek_offset = skippable_message.offset + 1
|
59
|
+
end
|
63
60
|
end
|
64
61
|
end
|
65
62
|
end
|
@@ -41,23 +41,13 @@ module Karafka
|
|
41
41
|
return if coordinator.manual_pause?
|
42
42
|
|
43
43
|
handle_post_filtering
|
44
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
45
|
-
retry_after_pause
|
46
|
-
# If we've reached number of retries that we could, we need to skip the first
|
47
|
-
# message that was not marked as consumed, pause and continue, while also moving
|
48
|
-
# this message to the dead topic.
|
49
|
-
#
|
50
|
-
# For a Mom setup, this means, that user has to manage the checkpointing by
|
51
|
-
# himself. If no checkpointing is ever done, we end up with an endless loop.
|
52
44
|
else
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
skippable_message, _marked = find_skippable_message
|
57
|
-
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
45
|
+
apply_dlq_flow do
|
46
|
+
skippable_message, _marked = find_skippable_message
|
47
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
58
48
|
|
59
|
-
|
60
|
-
|
49
|
+
coordinator.seek_offset = skippable_message.offset + 1
|
50
|
+
end
|
61
51
|
end
|
62
52
|
end
|
63
53
|
end
|
@@ -42,16 +42,12 @@ module Karafka
|
|
42
42
|
seek(coordinator.seek_offset, false) unless revoked? || coordinator.manual_seek?
|
43
43
|
|
44
44
|
resume
|
45
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
46
|
-
retry_after_pause
|
47
45
|
else
|
48
|
-
|
49
|
-
|
50
|
-
return resume if revoked?
|
51
|
-
|
52
|
-
dispatch_if_needed_and_mark_as_consumed
|
46
|
+
apply_dlq_flow do
|
47
|
+
return resume if revoked?
|
53
48
|
|
54
|
-
|
49
|
+
dispatch_if_needed_and_mark_as_consumed
|
50
|
+
end
|
55
51
|
end
|
56
52
|
end
|
57
53
|
end
|
@@ -42,18 +42,15 @@ module Karafka
|
|
42
42
|
end
|
43
43
|
|
44
44
|
resume
|
45
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
46
|
-
retry_after_pause
|
47
45
|
else
|
48
|
-
|
49
|
-
|
50
|
-
return resume if revoked?
|
46
|
+
apply_dlq_flow do
|
47
|
+
return resume if revoked?
|
51
48
|
|
52
|
-
|
53
|
-
|
49
|
+
skippable_message, _marked = find_skippable_message
|
50
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
54
51
|
|
55
|
-
|
56
|
-
|
52
|
+
coordinator.seek_offset = skippable_message.offset + 1
|
53
|
+
end
|
57
54
|
end
|
58
55
|
end
|
59
56
|
end
|
@@ -35,28 +35,18 @@ module Karafka
|
|
35
35
|
|
36
36
|
if coordinator.success?
|
37
37
|
coordinator.pause_tracker.reset
|
38
|
-
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
39
|
-
retry_after_pause
|
40
|
-
# If we've reached number of retries that we could, we need to skip the first
|
41
|
-
# message that was not marked as consumed, pause and continue, while also moving
|
42
|
-
# this message to the dead topic.
|
43
|
-
#
|
44
|
-
# For a Mom setup, this means, that user has to manage the checkpointing by
|
45
|
-
# himself. If no checkpointing is ever done, we end up with an endless loop.
|
46
38
|
else
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
skippable_message, = find_skippable_message
|
51
|
-
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
39
|
+
apply_dlq_flow do
|
40
|
+
skippable_message, = find_skippable_message
|
41
|
+
dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
|
52
42
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
43
|
+
# Save the next offset we want to go with after moving given message to DLQ
|
44
|
+
# Without this, we would not be able to move forward and we would end up
|
45
|
+
# in an infinite loop trying to un-pause from the message we've already
|
46
|
+
# processed. Of course, since it's a MoM a rebalance or kill, will move it back
|
47
|
+
# as no offsets are being committed
|
48
|
+
coordinator.seek_offset = skippable_message.offset + 1
|
49
|
+
end
|
60
50
|
end
|
61
51
|
end
|
62
52
|
end
|
@@ -155,6 +155,13 @@ module Karafka
|
|
155
155
|
def handle_before_schedule_consume
|
156
156
|
super
|
157
157
|
|
158
|
+
# We should not register offsets in virtual manager when in collapse as virtual
|
159
|
+
# manager is not used then for offsets materialization.
|
160
|
+
#
|
161
|
+
# If we would do so, it would cause increased storage in cases of endless errors
|
162
|
+
# that are being retried in collapse without a DLQ.
|
163
|
+
return if collapsed?
|
164
|
+
|
158
165
|
coordinator.virtual_offset_manager.register(
|
159
166
|
messages.map(&:offset)
|
160
167
|
)
|
@@ -28,6 +28,12 @@ module Karafka
|
|
28
28
|
).fetch('en').fetch('validations').fetch('topic')
|
29
29
|
end
|
30
30
|
|
31
|
+
nested(:dead_letter_queue) do
|
32
|
+
# We use strategy based DLQ for every case in Pro
|
33
|
+
# For default (when no strategy) a default `max_retries` based strategy is used
|
34
|
+
required(:strategy) { |val| val.respond_to?(:call) }
|
35
|
+
end
|
36
|
+
|
31
37
|
# Make sure that when we use virtual partitions with DLQ, at least one retry is set
|
32
38
|
# We cannot use VP with DLQ without retries as we in order to provide ordering
|
33
39
|
# warranties on errors with VP, we need to collapse the VPs concurrency and retry
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Pro
|
16
|
+
module Routing
|
17
|
+
module Features
|
18
|
+
class DeadLetterQueue < Base
|
19
|
+
# Expansions to the topic API in DLQ
|
20
|
+
module Topic
|
21
|
+
# @param strategy [#call, nil] Strategy we want to use or nil if a default strategy
|
22
|
+
# (same as in OSS) should be applied
|
23
|
+
# @param args [Hash] OSS DLQ arguments
|
24
|
+
def dead_letter_queue(strategy: nil, **args)
|
25
|
+
return @dead_letter_queue if @dead_letter_queue
|
26
|
+
|
27
|
+
super(**args).tap do |config|
|
28
|
+
# If explicit strategy is not provided, use the default approach from OSS
|
29
|
+
config.strategy = strategy || lambda do |_errors_tracker, attempt|
|
30
|
+
attempt > config.max_retries ? :dispatch : :retry
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|