karafka 2.0.0 → 2.1.0

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 (246) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/FUNDING.yml +1 -0
  4. data/.github/workflows/ci.yml +40 -16
  5. data/.rspec +4 -0
  6. data/.ruby-version +1 -1
  7. data/CHANGELOG.md +459 -796
  8. data/Gemfile +3 -2
  9. data/Gemfile.lock +44 -32
  10. data/LICENSE +1 -1
  11. data/README.md +22 -17
  12. data/bin/integrations +86 -26
  13. data/bin/karafka +1 -13
  14. data/bin/rspecs +6 -0
  15. data/bin/verify_license_integrity +37 -0
  16. data/certs/cert_chain.pem +26 -0
  17. data/config/{errors.yml → locales/errors.yml} +34 -6
  18. data/config/locales/pro_errors.yml +34 -0
  19. data/docker-compose.yml +4 -30
  20. data/karafka.gemspec +17 -10
  21. data/lib/active_job/karafka.rb +3 -7
  22. data/lib/active_job/queue_adapters/karafka_adapter.rb +7 -1
  23. data/lib/karafka/active_job/consumer.rb +29 -6
  24. data/lib/karafka/active_job/current_attributes/loading.rb +36 -0
  25. data/lib/karafka/active_job/current_attributes/persistence.rb +28 -0
  26. data/lib/karafka/active_job/current_attributes.rb +42 -0
  27. data/lib/karafka/active_job/dispatcher.rb +34 -3
  28. data/lib/karafka/active_job/job_options_contract.rb +13 -2
  29. data/lib/karafka/admin.rb +246 -0
  30. data/lib/karafka/app.rb +30 -7
  31. data/lib/karafka/base_consumer.rb +124 -82
  32. data/lib/karafka/cli/base.rb +20 -0
  33. data/lib/karafka/cli/console.rb +13 -8
  34. data/lib/karafka/cli/info.rb +3 -2
  35. data/lib/karafka/cli/server.rb +55 -8
  36. data/lib/karafka/cli/topics.rb +146 -0
  37. data/lib/karafka/connection/client.rb +118 -61
  38. data/lib/karafka/connection/consumer_group_coordinator.rb +48 -0
  39. data/lib/karafka/connection/listener.rb +78 -30
  40. data/lib/karafka/connection/listeners_batch.rb +18 -2
  41. data/lib/karafka/connection/rebalance_manager.rb +3 -0
  42. data/lib/karafka/contracts/config.rb +1 -1
  43. data/lib/karafka/contracts/consumer_group.rb +22 -9
  44. data/lib/karafka/contracts/server_cli_options.rb +71 -11
  45. data/lib/karafka/contracts/topic.rb +65 -0
  46. data/lib/karafka/contracts.rb +1 -1
  47. data/lib/karafka/embedded.rb +36 -0
  48. data/lib/karafka/errors.rb +6 -4
  49. data/lib/karafka/helpers/colorize.rb +6 -0
  50. data/lib/karafka/instrumentation/callbacks/error.rb +3 -4
  51. data/lib/karafka/instrumentation/callbacks/statistics.rb +14 -4
  52. data/lib/karafka/instrumentation/logger_listener.rb +151 -22
  53. data/lib/karafka/instrumentation/notifications.rb +26 -7
  54. data/lib/karafka/instrumentation/proctitle_listener.rb +7 -16
  55. data/lib/karafka/instrumentation/vendors/datadog/dashboard.json +1 -1
  56. data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +153 -0
  57. data/lib/karafka/instrumentation/vendors/datadog/{listener.rb → metrics_listener.rb} +62 -35
  58. data/lib/karafka/instrumentation/vendors/kubernetes/liveness_listener.rb +166 -0
  59. data/lib/karafka/licenser.rb +53 -50
  60. data/lib/karafka/messages/builders/batch_metadata.rb +8 -8
  61. data/lib/karafka/messages/builders/messages.rb +6 -2
  62. data/lib/karafka/messages/message.rb +14 -2
  63. data/lib/karafka/messages/messages.rb +5 -0
  64. data/lib/karafka/messages/parser.rb +14 -0
  65. data/lib/karafka/patches/rdkafka/bindings.rb +132 -0
  66. data/lib/karafka/pro/active_job/consumer.rb +10 -9
  67. data/lib/karafka/pro/active_job/dispatcher.rb +28 -3
  68. data/lib/karafka/pro/active_job/job_options_contract.rb +16 -3
  69. data/lib/karafka/pro/encryption/cipher.rb +58 -0
  70. data/lib/karafka/pro/encryption/contracts/config.rb +79 -0
  71. data/lib/karafka/pro/encryption/errors.rb +24 -0
  72. data/lib/karafka/pro/encryption/messages/middleware.rb +46 -0
  73. data/lib/karafka/pro/encryption/messages/parser.rb +56 -0
  74. data/lib/karafka/pro/encryption/setup/config.rb +48 -0
  75. data/lib/karafka/pro/encryption.rb +47 -0
  76. data/lib/karafka/pro/iterator.rb +253 -0
  77. data/lib/karafka/pro/loader.rb +52 -26
  78. data/lib/karafka/pro/performance_tracker.rb +10 -6
  79. data/lib/karafka/pro/processing/collapser.rb +62 -0
  80. data/lib/karafka/pro/processing/coordinator.rb +92 -16
  81. data/lib/karafka/pro/processing/filters/base.rb +61 -0
  82. data/lib/karafka/pro/processing/filters/delayer.rb +70 -0
  83. data/lib/karafka/pro/processing/filters/expirer.rb +51 -0
  84. data/lib/karafka/pro/processing/filters/throttler.rb +84 -0
  85. data/lib/karafka/pro/processing/filters/virtual_limiter.rb +52 -0
  86. data/lib/karafka/pro/processing/filters_applier.rb +104 -0
  87. data/lib/karafka/pro/processing/jobs/consume_non_blocking.rb +7 -5
  88. data/lib/karafka/pro/processing/jobs/revoked_non_blocking.rb +37 -0
  89. data/lib/karafka/pro/processing/jobs_builder.rb +22 -4
  90. data/lib/karafka/pro/processing/partitioner.rb +33 -24
  91. data/lib/karafka/pro/processing/scheduler.rb +27 -8
  92. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom.rb +68 -0
  93. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom_vp.rb +74 -0
  94. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom.rb +72 -0
  95. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom_vp.rb +76 -0
  96. data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom.rb +64 -0
  97. data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom_vp.rb +68 -0
  98. data/lib/karafka/pro/processing/strategies/aj/dlq_mom.rb +64 -0
  99. data/lib/karafka/pro/processing/strategies/aj/dlq_mom_vp.rb +69 -0
  100. data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom.rb +38 -0
  101. data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom_vp.rb +64 -0
  102. data/lib/karafka/pro/processing/strategies/aj/ftr_mom.rb +38 -0
  103. data/lib/karafka/pro/processing/strategies/aj/ftr_mom_vp.rb +58 -0
  104. data/lib/karafka/pro/processing/strategies/aj/lrj_mom.rb +37 -0
  105. data/lib/karafka/pro/processing/strategies/aj/lrj_mom_vp.rb +79 -0
  106. data/lib/karafka/pro/processing/strategies/aj/mom.rb +36 -0
  107. data/lib/karafka/pro/processing/strategies/aj/mom_vp.rb +52 -0
  108. data/lib/karafka/pro/processing/strategies/base.rb +26 -0
  109. data/lib/karafka/pro/processing/strategies/default.rb +105 -0
  110. data/lib/karafka/pro/processing/strategies/dlq/default.rb +131 -0
  111. data/lib/karafka/pro/processing/strategies/dlq/ftr.rb +61 -0
  112. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj.rb +75 -0
  113. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom.rb +71 -0
  114. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom_vp.rb +43 -0
  115. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_vp.rb +41 -0
  116. data/lib/karafka/pro/processing/strategies/dlq/ftr_mom.rb +69 -0
  117. data/lib/karafka/pro/processing/strategies/dlq/ftr_mom_vp.rb +41 -0
  118. data/lib/karafka/pro/processing/strategies/dlq/ftr_vp.rb +40 -0
  119. data/lib/karafka/pro/processing/strategies/dlq/lrj.rb +63 -0
  120. data/lib/karafka/pro/processing/strategies/dlq/lrj_mom.rb +63 -0
  121. data/lib/karafka/pro/processing/strategies/dlq/lrj_mom_vp.rb +36 -0
  122. data/lib/karafka/pro/processing/strategies/dlq/lrj_vp.rb +39 -0
  123. data/lib/karafka/pro/processing/strategies/dlq/mom.rb +68 -0
  124. data/lib/karafka/pro/processing/strategies/dlq/mom_vp.rb +37 -0
  125. data/lib/karafka/pro/processing/strategies/dlq/vp.rb +40 -0
  126. data/lib/karafka/pro/processing/strategies/ftr/default.rb +104 -0
  127. data/lib/karafka/pro/processing/strategies/ftr/vp.rb +40 -0
  128. data/lib/karafka/pro/processing/strategies/lrj/default.rb +87 -0
  129. data/lib/karafka/pro/processing/strategies/lrj/ftr.rb +69 -0
  130. data/lib/karafka/pro/processing/strategies/lrj/ftr_mom.rb +67 -0
  131. data/lib/karafka/pro/processing/strategies/lrj/ftr_mom_vp.rb +40 -0
  132. data/lib/karafka/pro/processing/strategies/lrj/ftr_vp.rb +39 -0
  133. data/lib/karafka/pro/processing/strategies/lrj/mom.rb +80 -0
  134. data/lib/karafka/pro/processing/strategies/lrj/mom_vp.rb +38 -0
  135. data/lib/karafka/pro/processing/strategies/lrj/vp.rb +36 -0
  136. data/lib/karafka/pro/processing/strategies/mom/default.rb +46 -0
  137. data/lib/karafka/pro/processing/strategies/mom/ftr.rb +53 -0
  138. data/lib/karafka/pro/processing/strategies/mom/ftr_vp.rb +37 -0
  139. data/lib/karafka/pro/processing/strategies/mom/vp.rb +35 -0
  140. data/lib/karafka/pro/processing/strategies/vp/default.rb +104 -0
  141. data/lib/karafka/pro/{contracts/base.rb → processing/strategies.rb} +6 -5
  142. data/lib/karafka/pro/processing/strategy_selector.rb +84 -0
  143. data/lib/karafka/pro/processing/virtual_offset_manager.rb +147 -0
  144. data/lib/karafka/pro/routing/features/base.rb +24 -0
  145. data/lib/karafka/pro/routing/features/dead_letter_queue/contract.rb +50 -0
  146. data/lib/karafka/pro/routing/features/dead_letter_queue.rb +27 -0
  147. data/lib/karafka/pro/routing/{builder_extensions.rb → features/delaying/config.rb} +8 -11
  148. data/lib/karafka/pro/routing/features/delaying/contract.rb +38 -0
  149. data/lib/karafka/pro/routing/features/delaying/topic.rb +59 -0
  150. data/lib/karafka/pro/routing/features/delaying.rb +29 -0
  151. data/lib/karafka/pro/routing/features/expiring/config.rb +27 -0
  152. data/lib/karafka/pro/routing/features/expiring/contract.rb +38 -0
  153. data/lib/karafka/pro/routing/features/expiring/topic.rb +59 -0
  154. data/lib/karafka/pro/routing/features/expiring.rb +27 -0
  155. data/lib/karafka/pro/routing/features/filtering/config.rb +40 -0
  156. data/lib/karafka/pro/routing/features/filtering/contract.rb +41 -0
  157. data/lib/karafka/pro/routing/features/filtering/topic.rb +51 -0
  158. data/lib/karafka/pro/routing/features/filtering.rb +27 -0
  159. data/lib/karafka/pro/routing/features/long_running_job/config.rb +28 -0
  160. data/lib/karafka/pro/routing/features/long_running_job/contract.rb +37 -0
  161. data/lib/karafka/pro/routing/features/long_running_job/topic.rb +42 -0
  162. data/lib/karafka/pro/routing/features/long_running_job.rb +28 -0
  163. data/lib/karafka/pro/routing/features/throttling/config.rb +32 -0
  164. data/lib/karafka/pro/routing/features/throttling/contract.rb +41 -0
  165. data/lib/karafka/pro/routing/features/throttling/topic.rb +69 -0
  166. data/lib/karafka/pro/routing/features/throttling.rb +30 -0
  167. data/lib/karafka/pro/routing/features/virtual_partitions/config.rb +30 -0
  168. data/lib/karafka/pro/routing/features/virtual_partitions/contract.rb +52 -0
  169. data/lib/karafka/pro/routing/features/virtual_partitions/topic.rb +56 -0
  170. data/lib/karafka/pro/routing/features/virtual_partitions.rb +27 -0
  171. data/lib/karafka/process.rb +23 -8
  172. data/lib/karafka/processing/coordinator.rb +102 -23
  173. data/lib/karafka/processing/coordinators_buffer.rb +5 -1
  174. data/lib/karafka/processing/executor.rb +51 -21
  175. data/lib/karafka/processing/executors_buffer.rb +10 -26
  176. data/lib/karafka/processing/jobs/base.rb +6 -2
  177. data/lib/karafka/processing/jobs/consume.rb +8 -5
  178. data/lib/karafka/processing/jobs/idle.rb +24 -0
  179. data/lib/karafka/processing/jobs_builder.rb +2 -3
  180. data/lib/karafka/processing/jobs_queue.rb +14 -8
  181. data/lib/karafka/processing/partitioner.rb +3 -1
  182. data/lib/karafka/processing/result.rb +14 -1
  183. data/lib/karafka/processing/strategies/aj_dlq_mom.rb +44 -0
  184. data/lib/karafka/processing/strategies/aj_mom.rb +21 -0
  185. data/lib/karafka/processing/strategies/base.rb +52 -0
  186. data/lib/karafka/processing/strategies/default.rb +142 -0
  187. data/lib/karafka/processing/strategies/dlq.rb +88 -0
  188. data/lib/karafka/processing/strategies/dlq_mom.rb +49 -0
  189. data/lib/karafka/processing/strategies/mom.rb +29 -0
  190. data/lib/karafka/processing/strategy_selector.rb +47 -0
  191. data/lib/karafka/processing/worker.rb +8 -3
  192. data/lib/karafka/railtie.rb +24 -12
  193. data/lib/karafka/routing/activity_manager.rb +84 -0
  194. data/lib/karafka/routing/builder.rb +20 -0
  195. data/lib/karafka/routing/consumer_group.rb +38 -4
  196. data/lib/karafka/routing/consumer_mapper.rb +0 -10
  197. data/lib/karafka/routing/features/active_job/builder.rb +33 -0
  198. data/lib/karafka/routing/features/active_job/config.rb +15 -0
  199. data/lib/karafka/routing/features/active_job/contract.rb +41 -0
  200. data/lib/karafka/routing/features/active_job/topic.rb +33 -0
  201. data/lib/karafka/routing/features/active_job.rb +13 -0
  202. data/lib/karafka/routing/features/base/expander.rb +53 -0
  203. data/lib/karafka/routing/features/base.rb +34 -0
  204. data/lib/karafka/routing/features/dead_letter_queue/config.rb +19 -0
  205. data/lib/karafka/routing/features/dead_letter_queue/contract.rb +42 -0
  206. data/lib/karafka/routing/features/dead_letter_queue/topic.rb +41 -0
  207. data/lib/karafka/routing/features/dead_letter_queue.rb +16 -0
  208. data/lib/karafka/routing/features/declaratives/config.rb +18 -0
  209. data/lib/karafka/routing/features/declaratives/contract.rb +30 -0
  210. data/lib/karafka/routing/features/declaratives/topic.rb +44 -0
  211. data/lib/karafka/routing/features/declaratives.rb +14 -0
  212. data/lib/karafka/routing/features/manual_offset_management/config.rb +15 -0
  213. data/lib/karafka/routing/features/manual_offset_management/contract.rb +24 -0
  214. data/lib/karafka/routing/features/manual_offset_management/topic.rb +35 -0
  215. data/lib/karafka/routing/features/manual_offset_management.rb +18 -0
  216. data/lib/karafka/routing/proxy.rb +18 -20
  217. data/lib/karafka/routing/router.rb +27 -2
  218. data/lib/karafka/routing/subscription_group.rb +43 -5
  219. data/lib/karafka/routing/subscription_groups_builder.rb +6 -1
  220. data/lib/karafka/routing/topic.rb +17 -5
  221. data/lib/karafka/routing/topics.rb +8 -0
  222. data/lib/karafka/runner.rb +1 -0
  223. data/lib/karafka/serialization/json/deserializer.rb +1 -0
  224. data/lib/karafka/server.rb +58 -28
  225. data/lib/karafka/setup/attributes_map.rb +344 -0
  226. data/lib/karafka/setup/config.rb +48 -19
  227. data/lib/karafka/status.rb +35 -7
  228. data/lib/karafka/templates/karafka.rb.erb +14 -6
  229. data/lib/karafka/time_trackers/base.rb +1 -6
  230. data/lib/karafka/time_trackers/pause.rb +49 -19
  231. data/lib/karafka/time_trackers/poll.rb +7 -3
  232. data/lib/karafka/version.rb +1 -1
  233. data/lib/karafka.rb +56 -3
  234. data/renovate.json +6 -0
  235. data.tar.gz.sig +0 -0
  236. metadata +189 -61
  237. metadata.gz.sig +0 -0
  238. data/bin/wait_for_kafka +0 -20
  239. data/certs/mensfeld.pem +0 -25
  240. data/lib/karafka/active_job/routing/extensions.rb +0 -31
  241. data/lib/karafka/contracts/consumer_group_topic.rb +0 -42
  242. data/lib/karafka/instrumentation.rb +0 -21
  243. data/lib/karafka/pro/base_consumer.rb +0 -82
  244. data/lib/karafka/pro/contracts/consumer_group.rb +0 -34
  245. data/lib/karafka/pro/contracts/consumer_group_topic.rb +0 -33
  246. data/lib/karafka/pro/routing/topic_extensions.rb +0 -38
@@ -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
  #
@@ -16,39 +18,46 @@ module Karafka
16
18
  class Partitioner < ::Karafka::Processing::Partitioner
17
19
  # @param topic [String] topic name
18
20
  # @param messages [Array<Karafka::Messages::Message>] karafka messages
21
+ # @param coordinator [Karafka::Pro::Processing::Coordinator] processing coordinator that
22
+ # will be used with those messages
19
23
  # @yieldparam [Integer] group id
20
24
  # @yieldparam [Array<Karafka::Messages::Message>] karafka messages
21
- def call(topic, messages)
25
+ def call(topic, messages, coordinator)
22
26
  ktopic = @subscription_group.topics.find(topic)
23
27
 
24
- @concurrency ||= ::Karafka::App.config.concurrency
25
-
26
- # We only partition work if we have a virtual partitioner and more than one thread to
27
- # process the data. With one thread it is not worth partitioning the work as the work
28
- # itself will be assigned to one thread (pointless work)
29
- if ktopic.virtual_partitioner? && @concurrency > 1
30
- # We need to reduce it to number of threads, so the group_id is not a direct effect
28
+ # We only partition work if we have:
29
+ # - a virtual partitioner
30
+ # - more than one thread to process the data
31
+ # - collective is not collapsed via coordinator
32
+ #
33
+ # With one thread it is not worth partitioning the work as the work itself will be
34
+ # assigned to one thread (pointless work)
35
+ #
36
+ # We collapse the partitioning on errors because we "regain" full ordering on a batch
37
+ # that potentially contains the data that caused the error.
38
+ #
39
+ # This is great because it allows us to run things without the parallelization that adds
40
+ # a bit of uncertainty and allows us to use DLQ and safely skip messages if needed.
41
+ if ktopic.virtual_partitions? &&
42
+ ktopic.virtual_partitions.max_partitions > 1 &&
43
+ !coordinator.collapsed?
44
+ # We need to reduce it to the max concurrency, so the group_id is not a direct effect
31
45
  # of the end user action. Otherwise the persistence layer for consumers would cache
32
46
  # it forever and it would cause memory leaks
33
- groupings = messages
34
- .group_by { |msg| ktopic.virtual_partitioner.call(msg) }
35
- .values
36
-
37
- # Reduce the max concurrency to a size that matches the concurrency
38
- # As mentioned above we cannot use the partitioning keys directly as it could cause
39
- # memory leaks
40
47
  #
41
- # The algorithm here is simple, we assume that the most costly in terms of processing,
42
- # will be processing of the biggest group and we reduce the smallest once to have
43
- # max of groups equal to concurrency
44
- while groupings.size > @concurrency
45
- groupings.sort_by! { |grouping| -grouping.size }
48
+ # This also needs to be consistent because the aggregation here needs to warrant, that
49
+ # the same partitioned message will always be assigned to the same virtual partition.
50
+ # Otherwise in case of a window aggregation with VP spanning across several polls, the
51
+ # data could not be complete.
52
+ groupings = messages.group_by do |msg|
53
+ key = ktopic.virtual_partitions.partitioner.call(msg).to_s.sum
46
54
 
47
- # Offset order needs to be maintained for virtual partitions
48
- groupings << (groupings.pop + groupings.pop).sort_by!(&:offset)
55
+ key % ktopic.virtual_partitions.max_partitions
49
56
  end
50
57
 
51
- groupings.each_with_index { |messages_group, index| yield(index, messages_group) }
58
+ groupings.each do |key, messages_group|
59
+ yield(key, messages_group)
60
+ end
52
61
  else
53
62
  # When no virtual partitioner, works as regular one
54
63
  yield(0, messages)
@@ -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
  #
@@ -29,17 +31,15 @@ module Karafka
29
31
  # @param jobs_array [Array<Karafka::Processing::Jobs::Base>] jobs we want to schedule
30
32
  #
31
33
  def schedule_consumption(queue, jobs_array)
32
- pt = PerformanceTracker.instance
34
+ perf_tracker = PerformanceTracker.instance
33
35
 
34
36
  ordered = []
35
37
 
36
38
  jobs_array.each do |job|
37
- messages = job.messages
38
- message = messages.first
39
-
40
- cost = pt.processing_time_p95(message.topic, message.partition) * messages.size
41
-
42
- ordered << [job, cost]
39
+ ordered << [
40
+ job,
41
+ processing_cost(perf_tracker, job)
42
+ ]
43
43
  end
44
44
 
45
45
  ordered.sort_by!(&:last)
@@ -50,6 +50,25 @@ module Karafka
50
50
  queue << job
51
51
  end
52
52
  end
53
+
54
+ private
55
+
56
+ # @param perf_tracker [PerformanceTracker]
57
+ # @param job [Karafka::Processing::Jobs::Base] job we will be processing
58
+ # @return [Numeric] estimated cost of processing this job
59
+ def processing_cost(perf_tracker, job)
60
+ if job.is_a?(::Karafka::Processing::Jobs::Consume)
61
+ messages = job.messages
62
+ message = messages.first
63
+
64
+ perf_tracker.processing_time_p95(message.topic, message.partition) * messages.size
65
+ else
66
+ # LJF will set first the most expensive, but we want to run the zero cost jobs
67
+ # related to the lifecycle always first. That is why we "emulate" that they
68
+ # the longest possible jobs that anyone can run
69
+ Float::INFINITY
70
+ end
71
+ end
53
72
  end
54
73
  end
55
74
  end
@@ -0,0 +1,68 @@
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
+ module Aj
19
+ # ActiveJob enabled
20
+ # DLQ enabled
21
+ # Filtering enabled
22
+ # Long-Running Job enabled
23
+ # Manual offset management enabled
24
+ module DlqFtrLrjMom
25
+ include Strategies::Aj::FtrMom
26
+ include Strategies::Aj::DlqMom
27
+ include Strategies::Aj::LrjMom
28
+
29
+ # Features for this strategy
30
+ FEATURES = %i[
31
+ active_job
32
+ dead_letter_queue
33
+ filtering
34
+ long_running_job
35
+ manual_offset_management
36
+ ].freeze
37
+
38
+ # This strategy assumes we do not early break on shutdown as it has VP
39
+ def handle_after_consume
40
+ coordinator.on_finished do
41
+ if coordinator.success?
42
+ coordinator.pause_tracker.reset
43
+
44
+ if coordinator.filtered? && !revoked?
45
+ handle_post_filtering
46
+ elsif !revoked?
47
+ seek(coordinator.seek_offset)
48
+ resume
49
+ else
50
+ resume
51
+ end
52
+ elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
53
+ retry_after_pause
54
+ else
55
+ coordinator.pause_tracker.reset
56
+ skippable_message, = find_skippable_message
57
+ dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
58
+ mark_as_consumed(skippable_message)
59
+ pause(coordinator.seek_offset, nil, false)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,74 @@
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
+ module Aj
19
+ # ActiveJob enabled
20
+ # DLQ enabled
21
+ # Filtering enabled
22
+ # Long-Running Job enabled
23
+ # Manual offset management enabled
24
+ # Virtual Partitions enabled
25
+ module DlqFtrLrjMomVp
26
+ include Strategies::Aj::FtrMom
27
+ include Strategies::Aj::DlqMomVp
28
+ include Strategies::Aj::LrjMom
29
+
30
+ # Features for this strategy
31
+ FEATURES = %i[
32
+ active_job
33
+ dead_letter_queue
34
+ filtering
35
+ long_running_job
36
+ manual_offset_management
37
+ virtual_partitions
38
+ ].freeze
39
+
40
+ # This strategy assumes we do not early break on shutdown as it has VP
41
+ def handle_after_consume
42
+ coordinator.on_finished do |last_group_message|
43
+ if coordinator.success?
44
+ coordinator.pause_tracker.reset
45
+
46
+ # Since we have VP here we do not commit intermediate offsets and need to commit
47
+ # them here. We do commit in collapsed mode but this is generalized.
48
+ mark_as_consumed(last_group_message) unless revoked?
49
+
50
+ if coordinator.filtered? && !revoked?
51
+ handle_post_filtering
52
+ elsif !revoked?
53
+ seek(coordinator.seek_offset)
54
+ resume
55
+ else
56
+ resume
57
+ end
58
+ elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
59
+ retry_after_pause
60
+ else
61
+ coordinator.pause_tracker.reset
62
+ skippable_message, = find_skippable_message
63
+ dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
64
+ mark_as_consumed(skippable_message)
65
+ pause(coordinator.seek_offset, nil, false)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,72 @@
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
+ module Aj
19
+ # - Aj
20
+ # - Dlq
21
+ # - Ftr
22
+ # - Mom
23
+ module DlqFtrMom
24
+ include Strategies::Dlq::FtrMom
25
+
26
+ # Features for this strategy
27
+ FEATURES = %i[
28
+ active_job
29
+ dead_letter_queue
30
+ filtering
31
+ manual_offset_management
32
+ ].freeze
33
+
34
+ # We write our own custom handler for after consume here, because we mark as consumed
35
+ # per each job in the AJ consumer itself (for this strategy). This means, that for DLQ
36
+ # dispatch, we can mark this message as consumed as well.
37
+ def handle_after_consume
38
+ coordinator.on_finished do
39
+ return if revoked?
40
+
41
+ if coordinator.success?
42
+ coordinator.pause_tracker.reset
43
+
44
+ return if coordinator.manual_pause?
45
+
46
+ handle_post_filtering
47
+ elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
48
+ retry_after_pause
49
+ # If we've reached number of retries that we could, we need to skip the first
50
+ # message that was not marked as consumed, pause and continue, while also moving
51
+ # this message to the dead topic.
52
+ #
53
+ # For a Mom setup, this means, that user has to manage the checkpointing by
54
+ # himself. If no checkpointing is ever done, we end up with an endless loop.
55
+ else
56
+ coordinator.pause_tracker.reset
57
+ skippable_message, = find_skippable_message
58
+ dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
59
+ # We can commit the offset here because we know that we skip it "forever" and
60
+ # since AJ consumer commits the offset after each job, we also know that the
61
+ # previous job was successful
62
+ mark_as_consumed(skippable_message)
63
+ pause(coordinator.seek_offset, nil, false)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,76 @@
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
+ module Aj
19
+ # - Aj
20
+ # - Dlq
21
+ # - Ftr
22
+ # - Mom
23
+ # - VP
24
+ module DlqFtrMomVp
25
+ include Strategies::Aj::DlqMomVp
26
+ include Strategies::Aj::DlqFtrMom
27
+
28
+ # Features for this strategy
29
+ FEATURES = %i[
30
+ active_job
31
+ dead_letter_queue
32
+ filtering
33
+ manual_offset_management
34
+ virtual_partitions
35
+ ].freeze
36
+
37
+ # AJ VP does not early stop on shutdown, hence here we can mark as consumed at the
38
+ # end of all VPs
39
+ def handle_after_consume
40
+ coordinator.on_finished do |last_group_message|
41
+ return if revoked?
42
+
43
+ if coordinator.success?
44
+ coordinator.pause_tracker.reset
45
+
46
+ return if coordinator.manual_pause?
47
+
48
+ mark_as_consumed(last_group_message)
49
+
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
+ else
60
+ coordinator.pause_tracker.reset
61
+ skippable_message, = find_skippable_message
62
+ dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
63
+ # We can commit the offset here because we know that we skip it "forever" and
64
+ # since AJ consumer commits the offset after each job, we also know that the
65
+ # previous job was successful
66
+ mark_as_consumed(skippable_message)
67
+ pause(coordinator.seek_offset, nil, false)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ 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
+ module Aj
19
+ # ActiveJob enabled
20
+ # DLQ enabled
21
+ # Long-Running Job enabled
22
+ # Manual offset management enabled
23
+ #
24
+ # This case is a bit of special. Please see the `AjDlqMom` for explanation on how the
25
+ # offset management works in this case.
26
+ module DlqLrjMom
27
+ include Strategies::Default
28
+ include Strategies::Dlq::Default
29
+ include Strategies::Aj::LrjMom
30
+
31
+ # Features for this strategy
32
+ FEATURES = %i[
33
+ active_job
34
+ dead_letter_queue
35
+ long_running_job
36
+ manual_offset_management
37
+ ].freeze
38
+
39
+ # We cannot use a VP version of this, because non-VP can early stop on shutdown
40
+ def handle_after_consume
41
+ coordinator.on_finished do
42
+ if coordinator.success?
43
+ coordinator.pause_tracker.reset
44
+
45
+ seek(coordinator.seek_offset) unless revoked?
46
+
47
+ resume
48
+ elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
49
+ retry_after_pause
50
+ else
51
+ coordinator.pause_tracker.reset
52
+ skippable_message, = find_skippable_message
53
+ dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
54
+ mark_as_consumed(skippable_message)
55
+ pause(coordinator.seek_offset, nil, false)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,68 @@
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
+ module Aj
19
+ # ActiveJob enabled
20
+ # DLQ enabled
21
+ # Long-Running Job enabled
22
+ # Manual offset management enabled
23
+ # Virtual Partitions enabled
24
+ #
25
+ # This case is a bit of special. Please see the `Aj::DlqMom` for explanation on how the
26
+ # offset management works in this case.
27
+ module DlqLrjMomVp
28
+ include Strategies::Aj::DlqMomVp
29
+ include Strategies::Aj::LrjMom
30
+
31
+ # Features for this strategy
32
+ FEATURES = %i[
33
+ active_job
34
+ dead_letter_queue
35
+ long_running_job
36
+ manual_offset_management
37
+ virtual_partitions
38
+ ].freeze
39
+
40
+ # This strategy assumes we do not early break on shutdown as it has VP
41
+ def handle_after_consume
42
+ coordinator.on_finished do |last_group_message|
43
+ if coordinator.success?
44
+ coordinator.pause_tracker.reset
45
+
46
+ # Since we have VP here we do not commit intermediate offsets and need to commit
47
+ # them here. We do commit in collapsed mode but this is generalized.
48
+ mark_as_consumed(last_group_message) unless revoked?
49
+ seek(coordinator.seek_offset) unless revoked?
50
+
51
+ resume
52
+ elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
53
+ retry_after_pause
54
+ else
55
+ coordinator.pause_tracker.reset
56
+ skippable_message, = find_skippable_message
57
+ dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
58
+ mark_as_consumed(skippable_message)
59
+ pause(coordinator.seek_offset, nil, false)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ 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
+ module Aj
19
+ # ActiveJob enabled
20
+ # DLQ enabled
21
+ # Manual offset management enabled
22
+ #
23
+ # AJ has manual offset management on by default and the offset management is delegated to
24
+ # the AJ consumer. This means, we cannot mark as consumed always. We can only mark as
25
+ # consumed when we skip given job upon errors. In all the other scenarios marking as
26
+ # consumed needs to happen in the AJ consumer on a per job basis.
27
+ module DlqMom
28
+ include Strategies::Dlq::Mom
29
+
30
+ # Features for this strategy
31
+ FEATURES = %i[
32
+ active_job
33
+ dead_letter_queue
34
+ manual_offset_management
35
+ ].freeze
36
+
37
+ # How should we post-finalize consumption.
38
+ def handle_after_consume
39
+ coordinator.on_finished do
40
+ return if revoked?
41
+
42
+ if coordinator.success?
43
+ # Do NOT commit offsets, they are comitted after each job in the AJ consumer.
44
+ coordinator.pause_tracker.reset
45
+ elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
46
+ retry_after_pause
47
+ else
48
+ coordinator.pause_tracker.reset
49
+ skippable_message, = find_skippable_message
50
+ dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
51
+ # We can commit the offset here because we know that we skip it "forever" and
52
+ # since AJ consumer commits the offset after each job, we also know that the
53
+ # previous job was successful
54
+ mark_as_consumed(skippable_message)
55
+ pause(coordinator.seek_offset, nil, false)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end