karafka 2.0.15 → 2.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/ci.yml +1 -1
  4. data/.rspec +2 -0
  5. data/CHANGELOG.md +78 -0
  6. data/Gemfile.lock +14 -14
  7. data/LICENSE +1 -1
  8. data/README.md +2 -1
  9. data/bin/integrations +3 -2
  10. data/bin/rspecs +4 -0
  11. data/config/errors.yml +10 -4
  12. data/lib/active_job/karafka.rb +0 -6
  13. data/lib/karafka/active_job/consumer.rb +1 -0
  14. data/lib/karafka/admin.rb +2 -2
  15. data/lib/karafka/base_consumer.rb +31 -21
  16. data/lib/karafka/connection/listener.rb +6 -4
  17. data/lib/karafka/contracts/consumer_group.rb +0 -14
  18. data/lib/karafka/contracts/{consumer_group_topic.rb → topic.rb} +2 -3
  19. data/lib/karafka/errors.rb +6 -4
  20. data/lib/karafka/instrumentation/logger_listener.rb +25 -11
  21. data/lib/karafka/instrumentation/notifications.rb +2 -0
  22. data/lib/karafka/instrumentation/vendors/datadog/dashboard.json +1 -1
  23. data/lib/karafka/instrumentation/vendors/datadog/listener.rb +37 -32
  24. data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +153 -0
  25. data/lib/karafka/pro/active_job/consumer.rb +3 -1
  26. data/lib/karafka/pro/active_job/dispatcher.rb +3 -1
  27. data/lib/karafka/pro/active_job/job_options_contract.rb +3 -1
  28. data/lib/karafka/pro/base_consumer.rb +3 -85
  29. data/lib/karafka/pro/loader.rb +31 -24
  30. data/lib/karafka/pro/performance_tracker.rb +3 -1
  31. data/lib/karafka/pro/processing/coordinator.rb +16 -1
  32. data/lib/karafka/pro/processing/jobs/consume_non_blocking.rb +3 -1
  33. data/lib/karafka/pro/processing/jobs_builder.rb +3 -1
  34. data/lib/karafka/pro/processing/partitioner.rb +3 -1
  35. data/lib/karafka/pro/processing/scheduler.rb +3 -1
  36. data/lib/karafka/pro/processing/strategies/aj_dlq_lrj_mom.rb +40 -0
  37. data/lib/karafka/pro/processing/strategies/aj_dlq_mom.rb +62 -0
  38. data/lib/karafka/pro/processing/strategies/aj_lrj_mom.rb +35 -0
  39. data/lib/karafka/pro/processing/strategies/aj_lrj_mom_vp.rb +69 -0
  40. data/lib/karafka/pro/processing/strategies/aj_mom.rb +33 -0
  41. data/lib/karafka/pro/processing/strategies/aj_mom_vp.rb +58 -0
  42. data/lib/karafka/pro/processing/strategies/base.rb +26 -0
  43. data/lib/karafka/pro/processing/strategies/default.rb +69 -0
  44. data/lib/karafka/pro/processing/strategies/dlq.rb +88 -0
  45. data/lib/karafka/pro/processing/strategies/dlq_lrj.rb +64 -0
  46. data/lib/karafka/pro/processing/strategies/dlq_lrj_mom.rb +60 -0
  47. data/lib/karafka/pro/processing/strategies/dlq_mom.rb +58 -0
  48. data/lib/karafka/pro/processing/strategies/lrj.rb +76 -0
  49. data/lib/karafka/pro/processing/strategies/lrj_mom.rb +68 -0
  50. data/lib/karafka/pro/processing/strategies/lrj_vp.rb +33 -0
  51. data/lib/karafka/pro/processing/strategies/mom.rb +43 -0
  52. data/lib/karafka/pro/processing/strategies/vp.rb +32 -0
  53. data/lib/karafka/pro/processing/strategy_selector.rb +58 -0
  54. data/lib/karafka/pro/{contracts → routing/features}/base.rb +8 -5
  55. data/lib/karafka/pro/routing/features/dead_letter_queue/contract.rb +49 -0
  56. data/lib/karafka/pro/routing/{builder_extensions.rb → features/dead_letter_queue.rb} +9 -12
  57. data/lib/karafka/pro/routing/features/long_running_job/config.rb +28 -0
  58. data/lib/karafka/pro/routing/features/long_running_job/contract.rb +37 -0
  59. data/lib/karafka/pro/routing/features/long_running_job/topic.rb +42 -0
  60. data/lib/karafka/pro/routing/features/long_running_job.rb +28 -0
  61. data/lib/karafka/pro/routing/features/virtual_partitions/config.rb +30 -0
  62. data/lib/karafka/pro/routing/features/virtual_partitions/contract.rb +69 -0
  63. data/lib/karafka/pro/routing/features/virtual_partitions/topic.rb +56 -0
  64. data/lib/karafka/pro/routing/features/virtual_partitions.rb +27 -0
  65. data/lib/karafka/processing/coordinator.rb +1 -1
  66. data/lib/karafka/processing/executor.rb +6 -0
  67. data/lib/karafka/processing/strategies/aj_dlq_mom.rb +44 -0
  68. data/lib/karafka/processing/strategies/aj_mom.rb +21 -0
  69. data/lib/karafka/processing/strategies/base.rb +37 -0
  70. data/lib/karafka/processing/strategies/default.rb +52 -0
  71. data/lib/karafka/processing/strategies/dlq.rb +77 -0
  72. data/lib/karafka/processing/strategies/dlq_mom.rb +42 -0
  73. data/lib/karafka/processing/strategies/mom.rb +29 -0
  74. data/lib/karafka/processing/strategy_selector.rb +30 -0
  75. data/lib/karafka/railtie.rb +9 -8
  76. data/lib/karafka/routing/builder.rb +6 -0
  77. data/lib/karafka/routing/features/active_job/builder.rb +33 -0
  78. data/lib/karafka/routing/features/active_job/config.rb +15 -0
  79. data/lib/karafka/routing/features/active_job/contract.rb +41 -0
  80. data/lib/karafka/routing/features/active_job/topic.rb +33 -0
  81. data/lib/karafka/routing/features/active_job.rb +13 -0
  82. data/lib/karafka/routing/features/base/expander.rb +53 -0
  83. data/lib/karafka/routing/features/base.rb +34 -0
  84. data/lib/karafka/routing/features/dead_letter_queue/config.rb +19 -0
  85. data/lib/karafka/routing/features/dead_letter_queue/contract.rb +40 -0
  86. data/lib/karafka/routing/features/dead_letter_queue/topic.rb +40 -0
  87. data/lib/karafka/routing/features/dead_letter_queue.rb +16 -0
  88. data/lib/karafka/routing/features/manual_offset_management/config.rb +15 -0
  89. data/lib/karafka/routing/features/manual_offset_management/contract.rb +24 -0
  90. data/lib/karafka/routing/features/manual_offset_management/topic.rb +35 -0
  91. data/lib/karafka/routing/features/manual_offset_management.rb +18 -0
  92. data/lib/karafka/routing/topic.rb +2 -10
  93. data/lib/karafka/server.rb +4 -2
  94. data/lib/karafka/setup/attributes_map.rb +5 -0
  95. data/lib/karafka/setup/config.rb +4 -4
  96. data/lib/karafka/time_trackers/pause.rb +21 -12
  97. data/lib/karafka/version.rb +1 -1
  98. data/lib/karafka.rb +7 -11
  99. data.tar.gz.sig +0 -0
  100. metadata +57 -9
  101. metadata.gz.sig +0 -0
  102. data/lib/karafka/active_job/routing/extensions.rb +0 -33
  103. data/lib/karafka/pro/contracts/consumer_group.rb +0 -34
  104. data/lib/karafka/pro/contracts/consumer_group_topic.rb +0 -69
  105. data/lib/karafka/pro/routing/topic_extensions.rb +0 -74
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This Karafka component is a Pro component.
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
4
6
  # All of the commercial components are present in the lib/karafka/pro directory of this
5
7
  # repository and their usage requires commercial license agreement.
6
8
  #
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This Karafka component is a Pro component.
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
4
6
  # All of the commercial components are present in the lib/karafka/pro directory of this
5
7
  # repository and their usage requires commercial license agreement.
6
8
  #
@@ -21,6 +23,7 @@ module Karafka
21
23
  @on_enqueued_invoked = false
22
24
  @on_started_invoked = false
23
25
  @on_finished_invoked = false
26
+ @on_revoked_invoked = false
24
27
  @flow_lock = Mutex.new
25
28
  end
26
29
 
@@ -79,6 +82,18 @@ module Karafka
79
82
  yield(@last_message)
80
83
  end
81
84
  end
85
+
86
+ # Runs once when a partition is revoked
87
+ def on_revoked
88
+ @flow_lock.synchronize do
89
+ return unless finished?
90
+ return if @on_revoked_invoked
91
+
92
+ @on_revoked_invoked = true
93
+
94
+ yield(@last_message)
95
+ end
96
+ end
82
97
  end
83
98
  end
84
99
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This Karafka component is a Pro component.
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
4
6
  # All of the commercial components are present in the lib/karafka/pro directory of this
5
7
  # repository and their usage requires commercial license agreement.
6
8
  #
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This Karafka component is a Pro component.
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
4
6
  # All of the commercial components are present in the lib/karafka/pro directory of this
5
7
  # repository and their usage requires commercial license agreement.
6
8
  #
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This Karafka component is a Pro component.
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
4
6
  # All of the commercial components are present in the lib/karafka/pro directory of this
5
7
  # repository and their usage requires commercial license agreement.
6
8
  #
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This Karafka component is a Pro component.
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
4
6
  # All of the commercial components are present in the lib/karafka/pro directory of this
5
7
  # repository and their usage requires commercial license agreement.
6
8
  #
@@ -0,0 +1,40 @@
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 Processing
17
+ module Strategies
18
+ # ActiveJob enabled
19
+ # DLQ enabled
20
+ # Long-Running Job enabled
21
+ # Manual offset management enabled
22
+ #
23
+ # This case is a bit of special. Please see the `AjDlqMom` for explanation on how the
24
+ # offset management works in this case.
25
+ module AjDlqLrjMom
26
+ include AjLrjMom
27
+ include AjDlqMom
28
+
29
+ # Features for this strategy
30
+ FEATURES = %i[
31
+ active_job
32
+ long_running_job
33
+ manual_offset_management
34
+ dead_letter_queue
35
+ ].freeze
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,62 @@
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 Processing
17
+ module Strategies
18
+ # ActiveJob enabled
19
+ # DLQ enabled
20
+ # Manual offset management enabled
21
+ #
22
+ # AJ has manual offset management on by default and the offset management is delegated to
23
+ # the AJ consumer. This means, we cannot mark as consumed always. We can only mark as
24
+ # consumed when we skip given job upon errors. In all the other scenarions marking as
25
+ # consumed needs to happen in the AJ consumer on a per job basis.
26
+ module AjDlqMom
27
+ include DlqMom
28
+
29
+ # Features for this strategy
30
+ FEATURES = %i[
31
+ active_job
32
+ dead_letter_queue
33
+ manual_offset_management
34
+ ].freeze
35
+
36
+ # How should we post-finalize consumption.
37
+ def handle_after_consume
38
+ coordinator.on_finished do
39
+ return if revoked?
40
+
41
+ if coordinator.success?
42
+ # Do NOT commit offsets, they are comitted after each job in the AJ consumer.
43
+ coordinator.pause_tracker.reset
44
+ elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
45
+ pause(coordinator.seek_offset)
46
+ else
47
+ coordinator.pause_tracker.reset
48
+ skippable_message = find_skippable_message
49
+ dispatch_to_dlq(skippable_message)
50
+ # We can commit the offset here because we know that we skip it "forever" and
51
+ # since AJ consumer commits the offset after each job, we also know that the
52
+ # previous job was successful
53
+ mark_as_consumed(skippable_message)
54
+ pause(coordinator.seek_offset)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,35 @@
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 Processing
17
+ module Strategies
18
+ # ActiveJob enabled
19
+ # Long-Running Job enabled
20
+ # Manual offset management enabled
21
+ module AjLrjMom
22
+ # Same behaviour as LrjMom
23
+ include LrjMom
24
+
25
+ # Features for this strategy
26
+ FEATURES = %i[
27
+ active_job
28
+ long_running_job
29
+ manual_offset_management
30
+ ].freeze
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,69 @@
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 Processing
17
+ module Strategies
18
+ # ActiveJob enabled
19
+ # Long-Running Job enabled
20
+ # Manual offset management enabled
21
+ # Virtual Partitions enabled
22
+ module AjLrjMomVp
23
+ include Default
24
+
25
+ # Features for this strategy
26
+ FEATURES = %i[
27
+ active_job
28
+ long_running_job
29
+ manual_offset_management
30
+ virtual_partitions
31
+ ].freeze
32
+
33
+ # No actions needed for the standard flow here
34
+ def handle_before_enqueue
35
+ coordinator.on_enqueued do
36
+ pause(coordinator.seek_offset, Lrj::MAX_PAUSE_TIME)
37
+ end
38
+ end
39
+
40
+ # Standard flow without any features
41
+ def handle_after_consume
42
+ coordinator.on_finished do |last_group_message|
43
+ if coordinator.success?
44
+ coordinator.pause_tracker.reset
45
+
46
+ mark_as_consumed(last_group_message) unless revoked? || Karafka::App.stopping?
47
+ seek(coordinator.seek_offset) unless revoked?
48
+
49
+ resume
50
+ else
51
+ # If processing failed, we need to pause
52
+ # For long running job this will overwrite the default never-ending pause and will
53
+ # cause the processing to keep going after the error backoff
54
+ pause(coordinator.seek_offset)
55
+ end
56
+ end
57
+ end
58
+
59
+ # LRJ cannot resume here. Only in handling the after consumption
60
+ def handle_revoked
61
+ coordinator.on_revoked do
62
+ coordinator.revoke
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,33 @@
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 Processing
17
+ module Strategies
18
+ # ActiveJob enabled
19
+ # Manual Offset management enabled
20
+ module AjMom
21
+ # Standard ActiveJob strategy is the same one we use for Mom
22
+ include Mom
23
+
24
+ # Features for this strategy
25
+ FEATURES = %i[
26
+ active_job
27
+ manual_offset_management
28
+ ].freeze
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,58 @@
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 Processing
17
+ module Strategies
18
+ # ActiveJob enabled
19
+ # Manual offset management enabled
20
+ # Virtual Partitions enabled
21
+ module AjMomVp
22
+ include Default
23
+
24
+ # Features for this strategy
25
+ FEATURES = %i[
26
+ active_job
27
+ manual_offset_management
28
+ virtual_partitions
29
+ ].freeze
30
+
31
+ # Standard flow without any features
32
+ def handle_after_consume
33
+ coordinator.on_finished do |last_group_message|
34
+ if coordinator.success?
35
+ coordinator.pause_tracker.reset
36
+
37
+ # When this is an ActiveJob running via Pro with virtual partitions, we cannot mark
38
+ # intermediate jobs as processed not to mess up with the ordering.
39
+ # Only when all the jobs are processed and we did not loose the partition
40
+ # assignment and we are not stopping (Pro ActiveJob has an early break) we can
41
+ # commit offsets on this as only then we can be sure, that all the jobs were
42
+ # processed.
43
+ # For a non virtual partitions case, the flow is regular and state is marked after
44
+ # each successfully processed job
45
+ return if revoked?
46
+ return if Karafka::App.stopping?
47
+
48
+ mark_as_consumed(last_group_message)
49
+ else
50
+ pause(coordinator.seek_offset)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,26 @@
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 Processing
17
+ # Pro processing strategies namespace
18
+ module Strategies
19
+ # Base strategy for Pro
20
+ module Base
21
+ include ::Karafka::Processing::Strategies::Base
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,69 @@
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 Processing
17
+ module Strategies
18
+ # No features enabled.
19
+ # No manual offset management
20
+ # No long running jobs
21
+ # No virtual partitions
22
+ # Nothing. Just standard, automatic flow
23
+ module Default
24
+ include Base
25
+
26
+ # Apply strategy for a non-feature based flow
27
+ FEATURES = %i[].freeze
28
+
29
+ # No actions needed for the standard flow here
30
+ def handle_before_enqueue
31
+ nil
32
+ end
33
+
34
+ # Increment number of attempts per one "full" job. For all VP on a single topic partition
35
+ # this also should run once.
36
+ def handle_before_consume
37
+ coordinator.on_started do
38
+ coordinator.pause_tracker.increment
39
+ end
40
+ end
41
+
42
+ # Standard flow without any features
43
+ def handle_after_consume
44
+ coordinator.on_finished do |last_group_message|
45
+ return if revoked?
46
+
47
+ if coordinator.success?
48
+ coordinator.pause_tracker.reset
49
+
50
+ mark_as_consumed(last_group_message)
51
+ else
52
+ pause(coordinator.seek_offset)
53
+ end
54
+ end
55
+ end
56
+
57
+ # Standard
58
+ def handle_revoked
59
+ coordinator.on_revoked do
60
+ resume
61
+
62
+ coordinator.revoke
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,88 @@
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 Processing
17
+ module Strategies
18
+ # Only dead letter queue enabled
19
+ module Dlq
20
+ include Default
21
+
22
+ # Features for this strategy
23
+ FEATURES = %i[
24
+ dead_letter_queue
25
+ ].freeze
26
+
27
+ # When we encounter non-recoverable message, we skip it and go on with our lives
28
+ def handle_after_consume
29
+ coordinator.on_finished do
30
+ return if revoked?
31
+
32
+ if coordinator.success?
33
+ coordinator.pause_tracker.reset
34
+
35
+ mark_as_consumed(messages.last)
36
+ elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
37
+ pause(coordinator.seek_offset)
38
+ # If we've reached number of retries that we could, we need to skip the first message
39
+ # that was not marked as consumed, pause and continue, while also moving this message
40
+ # to the dead topic
41
+ else
42
+ # We reset the pause to indicate we will now consider it as "ok".
43
+ coordinator.pause_tracker.reset
44
+ skippable_message = find_skippable_message
45
+ dispatch_to_dlq(skippable_message)
46
+ mark_as_consumed(skippable_message)
47
+ pause(coordinator.seek_offset)
48
+ end
49
+ end
50
+ end
51
+
52
+ # Finds the message may want to skip (all, starting from first)
53
+ # @private
54
+ # @return [Karafka::Messages::Message] message we may want to skip
55
+ def find_skippable_message
56
+ skippable_message = messages.find { |msg| msg.offset == coordinator.seek_offset }
57
+ skippable_message || raise(Errors::SkipMessageNotFoundError, topic.name)
58
+ end
59
+
60
+ # Moves the broken message into a separate queue defined via the settings
61
+ #
62
+ # @private
63
+ # @param skippable_message [Array<Karafka::Messages::Message>] message we want to
64
+ # dispatch to DLQ
65
+ def dispatch_to_dlq(skippable_message)
66
+ producer.produce_async(
67
+ topic: topic.dead_letter_queue.topic,
68
+ payload: skippable_message.raw_payload,
69
+ key: skippable_message.partition.to_s,
70
+ headers: skippable_message.headers.merge(
71
+ 'original-topic' => topic.name,
72
+ 'original-partition' => skippable_message.partition.to_s,
73
+ 'original-offset' => skippable_message.offset.to_s
74
+ )
75
+ )
76
+
77
+ # Notify about dispatch on the events bus
78
+ Karafka.monitor.instrument(
79
+ 'dead_letter_queue.dispatched',
80
+ caller: self,
81
+ message: skippable_message
82
+ )
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,64 @@
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 Processing
17
+ module Strategies
18
+ # DLQ enabled
19
+ # Long-Running Job enabled
20
+ module DlqLrj
21
+ # Order here matters, lrj needs to be second
22
+ include Dlq
23
+ include Lrj
24
+
25
+ # Features for this strategy
26
+ FEATURES = %i[
27
+ dead_letter_queue
28
+ long_running_job
29
+ ].freeze
30
+
31
+ # LRJ standard flow after consumption with DLQ dispatch
32
+ def handle_after_consume
33
+ coordinator.on_finished do |last_group_message|
34
+ if coordinator.success?
35
+ coordinator.pause_tracker.reset
36
+
37
+ mark_as_consumed(last_group_message) unless revoked?
38
+ seek(coordinator.seek_offset) unless revoked?
39
+
40
+ resume
41
+ elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
42
+ pause(coordinator.seek_offset)
43
+ else
44
+ coordinator.pause_tracker.reset
45
+
46
+ skippable_message = find_skippable_message
47
+
48
+ unless revoked?
49
+ dispatch_to_dlq(skippable_message)
50
+ mark_as_consumed(skippable_message)
51
+ end
52
+
53
+ # This revoke might have changed state due to marking, hence checked again
54
+ seek(coordinator.seek_offset) unless revoked?
55
+
56
+ resume
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end