karafka 2.5.9 → 2.6.0.beta1

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 (471) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/certs/expired.txt +83 -0
  4. data/config/locales/errors.yml +17 -7
  5. data/karafka.gemspec +3 -3
  6. data/lib/active_job/queue_adapters/karafka_adapter.rb +1 -2
  7. data/lib/karafka/active_job/job_extensions.rb +1 -2
  8. data/lib/karafka/admin/configs/resource.rb +1 -2
  9. data/lib/karafka/admin/consumer_groups.rb +109 -98
  10. data/lib/karafka/admin/isolation_levels.rb +22 -0
  11. data/lib/karafka/admin/topics.rb +103 -8
  12. data/lib/karafka/admin.rb +59 -31
  13. data/lib/karafka/app.rb +16 -5
  14. data/lib/karafka/base_consumer.rb +2 -2
  15. data/lib/karafka/cli/contracts/server.rb +4 -4
  16. data/lib/karafka/cli/info.rb +1 -1
  17. data/lib/karafka/cli/topics/base.rb +10 -18
  18. data/lib/karafka/cli/topics/repartition.rb +1 -1
  19. data/lib/karafka/connection/client.rb +40 -9
  20. data/lib/karafka/connection/consumer_groups/rebalance_manager.rb +120 -0
  21. data/lib/karafka/connection/listener.rb +8 -7
  22. data/lib/karafka/connection/listeners_batch.rb +1 -1
  23. data/lib/karafka/connection/mode.rb +1 -2
  24. data/lib/karafka/connection/raw_messages_buffer.rb +0 -5
  25. data/lib/karafka/declaratives/builder.rb +65 -0
  26. data/lib/karafka/declaratives/contracts/topic.rb +28 -0
  27. data/lib/karafka/declaratives/repository.rb +52 -0
  28. data/lib/karafka/declaratives/topic.rb +100 -0
  29. data/lib/karafka/declaratives.rb +9 -0
  30. data/lib/karafka/helpers/interval_runner.rb +2 -2
  31. data/lib/karafka/instrumentation/assignments_tracker.rb +65 -2
  32. data/lib/karafka/instrumentation/callbacks/consumer_groups/error.rb +56 -0
  33. data/lib/karafka/instrumentation/callbacks/consumer_groups/rebalance.rb +93 -0
  34. data/lib/karafka/instrumentation/callbacks/consumer_groups/statistics.rb +59 -0
  35. data/lib/karafka/instrumentation/logger_listener.rb +27 -9
  36. data/lib/karafka/instrumentation/notifications.rb +2 -0
  37. data/lib/karafka/instrumentation/vendors/appsignal/metrics_listener.rb +14 -17
  38. data/lib/karafka/instrumentation/vendors/datadog/metrics_listener.rb +8 -9
  39. data/lib/karafka/instrumentation/vendors/kubernetes/base_listener.rb +7 -3
  40. data/lib/karafka/instrumentation/vendors/kubernetes/liveness_listener.rb +13 -10
  41. data/lib/karafka/licenser.rb +16 -3
  42. data/lib/karafka/pro/active_job/consumer.rb +1 -2
  43. data/lib/karafka/pro/active_job/dispatcher.rb +1 -2
  44. data/lib/karafka/pro/admin/recovery.rb +19 -19
  45. data/lib/karafka/pro/base_consumer.rb +3 -3
  46. data/lib/karafka/pro/cli/contracts/server.rb +5 -5
  47. data/lib/karafka/pro/cli/parallel_segments/base.rb +7 -7
  48. data/lib/karafka/pro/cli/parallel_segments/collapse.rb +4 -4
  49. data/lib/karafka/pro/cli/parallel_segments/distribute.rb +6 -6
  50. data/lib/karafka/pro/iterator/tpl_builder.rb +38 -18
  51. data/lib/karafka/pro/loader.rb +15 -12
  52. data/lib/karafka/pro/processing/consumer_groups/adaptive_iterator/consumer.rb +84 -0
  53. data/lib/karafka/pro/processing/consumer_groups/adaptive_iterator/tracker.rb +97 -0
  54. data/lib/karafka/pro/processing/consumer_groups/collapser.rb +84 -0
  55. data/lib/karafka/pro/processing/consumer_groups/coordinator.rb +202 -0
  56. data/lib/karafka/pro/processing/consumer_groups/coordinators/errors_tracker.rb +124 -0
  57. data/lib/karafka/pro/processing/consumer_groups/coordinators/filters_applier.rb +157 -0
  58. data/lib/karafka/pro/processing/consumer_groups/coordinators/virtual_offset_manager.rb +212 -0
  59. data/lib/karafka/pro/processing/{filters/expirer.rb → consumer_groups/executor.rb} +17 -31
  60. data/lib/karafka/pro/processing/{jobs/periodic.rb → consumer_groups/expansions_selector.rb} +18 -21
  61. data/lib/karafka/pro/processing/consumer_groups/filters/base.rb +103 -0
  62. data/lib/karafka/pro/processing/consumer_groups/filters/delayer.rb +92 -0
  63. data/lib/karafka/pro/processing/consumer_groups/filters/expirer.rb +78 -0
  64. data/lib/karafka/pro/processing/consumer_groups/filters/inline_insights_delayer.rb +99 -0
  65. data/lib/karafka/pro/processing/consumer_groups/filters/throttler.rb +106 -0
  66. data/lib/karafka/pro/processing/consumer_groups/filters/virtual_limiter.rb +79 -0
  67. data/lib/karafka/pro/processing/{jobs → consumer_groups/jobs}/consume_non_blocking.rb +21 -17
  68. data/lib/karafka/pro/processing/{virtual_partitions/distributors/consistent.rb → consumer_groups/jobs/eofed_non_blocking.rb} +16 -14
  69. data/lib/karafka/pro/processing/consumer_groups/jobs/periodic.rb +64 -0
  70. data/lib/karafka/pro/processing/{jobs → consumer_groups/jobs}/periodic_non_blocking.rb +16 -11
  71. data/lib/karafka/pro/processing/{jobs → consumer_groups/jobs}/revoked_non_blocking.rb +19 -15
  72. data/lib/karafka/pro/processing/consumer_groups/jobs_builder.rb +95 -0
  73. data/lib/karafka/pro/processing/consumer_groups/offset_metadata/consumer.rb +66 -0
  74. data/lib/karafka/pro/processing/consumer_groups/offset_metadata/fetcher.rb +154 -0
  75. data/lib/karafka/pro/processing/consumer_groups/offset_metadata/listener.rb +68 -0
  76. data/lib/karafka/pro/processing/consumer_groups/parallel_segments/filters/base.rb +102 -0
  77. data/lib/karafka/pro/processing/consumer_groups/parallel_segments/filters/default.rb +115 -0
  78. data/lib/karafka/pro/processing/consumer_groups/parallel_segments/filters/mom.rb +96 -0
  79. data/lib/karafka/pro/processing/consumer_groups/partitioner.rb +98 -0
  80. data/lib/karafka/pro/processing/consumer_groups/periodic_job/consumer.rb +90 -0
  81. data/lib/karafka/pro/processing/consumer_groups/piping/consumer.rb +154 -0
  82. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_ftr_lrj_mom.rb +93 -0
  83. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_ftr_lrj_mom_vp.rb +99 -0
  84. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_ftr_mom.rb +92 -0
  85. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_ftr_mom_vp.rb +90 -0
  86. data/lib/karafka/pro/processing/{strategies/aj/dlq_ftr_lrj_mom.rb → consumer_groups/strategies/aj/dlq_lrj_mom.rb} +37 -39
  87. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_lrj_mom_vp.rb +90 -0
  88. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_mom.rb +84 -0
  89. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_mom_vp.rb +89 -0
  90. data/lib/karafka/pro/processing/{strategies → consumer_groups/strategies}/aj/ftr_lrj_mom.rb +20 -15
  91. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/ftr_lrj_mom_vp.rb +91 -0
  92. data/lib/karafka/pro/processing/{strategies → consumer_groups/strategies}/aj/ftr_mom.rb +20 -15
  93. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/ftr_mom_vp.rb +80 -0
  94. data/lib/karafka/pro/processing/{strategies/mom/default.rb → consumer_groups/strategies/aj/lrj_mom.rb} +18 -22
  95. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/lrj_mom_vp.rb +106 -0
  96. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/mom.rb +58 -0
  97. data/lib/karafka/pro/processing/consumer_groups/strategies/aj/mom_vp.rb +74 -0
  98. data/lib/karafka/pro/processing/{strategies/lrj/vp.rb → consumer_groups/strategies/base.rb} +9 -14
  99. data/lib/karafka/pro/processing/consumer_groups/strategies/default.rb +421 -0
  100. data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/default.rb +285 -0
  101. data/lib/karafka/pro/processing/{strategies/dlq/lrj.rb → consumer_groups/strategies/dlq/ftr.rb} +30 -29
  102. data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_lrj.rb +95 -0
  103. data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_lrj_mom.rb +97 -0
  104. data/lib/karafka/pro/processing/{executor.rb → consumer_groups/strategies/dlq/ftr_lrj_mom_vp.rb} +26 -15
  105. data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_lrj_vp.rb +63 -0
  106. data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_mom.rb +97 -0
  107. data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_mom_vp.rb +63 -0
  108. data/lib/karafka/pro/{routing/features/patterns/patterns.rb → processing/consumer_groups/strategies/dlq/ftr_vp.rb} +22 -12
  109. data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/lrj.rb +83 -0
  110. data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/lrj_mom.rb +100 -0
  111. data/lib/karafka/pro/processing/{strategies → consumer_groups/strategies}/dlq/lrj_mom_vp.rb +18 -13
  112. data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/lrj_vp.rb +61 -0
  113. data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/mom.rb +96 -0
  114. data/lib/karafka/pro/processing/{strategies/lrj → consumer_groups/strategies/dlq}/mom_vp.rb +19 -15
  115. data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/vp.rb +62 -0
  116. data/lib/karafka/pro/processing/consumer_groups/strategies/ftr/default.rb +146 -0
  117. data/lib/karafka/pro/processing/{strategies/mom/ftr.rb → consumer_groups/strategies/ftr/vp.rb} +20 -28
  118. data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/default.rb +119 -0
  119. data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/ftr.rb +94 -0
  120. data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/ftr_mom.rb +92 -0
  121. data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/ftr_mom_vp.rb +62 -0
  122. data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/ftr_vp.rb +61 -0
  123. data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/mom.rb +101 -0
  124. data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/mom_vp.rb +60 -0
  125. data/lib/karafka/pro/processing/{strategies/mom → consumer_groups/strategies/lrj}/vp.rb +18 -12
  126. data/lib/karafka/pro/processing/{strategies/aj/mom_vp.rb → consumer_groups/strategies/mom/default.rb} +22 -23
  127. data/lib/karafka/pro/processing/{strategies/aj/ftr_mom_vp.rb → consumer_groups/strategies/mom/ftr.rb} +28 -28
  128. data/lib/karafka/pro/processing/{virtual_partitions/distributors/base.rb → consumer_groups/strategies/mom/ftr_vp.rb} +19 -14
  129. data/lib/karafka/pro/processing/{strategies/aj/mom.rb → consumer_groups/strategies/mom/vp.rb} +16 -12
  130. data/lib/karafka/pro/processing/consumer_groups/strategies/vp/default.rb +197 -0
  131. data/lib/karafka/pro/processing/consumer_groups/strategy_selector.rb +106 -0
  132. data/lib/karafka/pro/processing/consumer_groups/subscription_groups_coordinator.rb +73 -0
  133. data/lib/karafka/pro/processing/consumer_groups/virtual_partitions/distributors/balanced.rb +82 -0
  134. data/lib/karafka/pro/processing/consumer_groups/virtual_partitions/distributors/base.rb +59 -0
  135. data/lib/karafka/pro/processing/{strategies/dlq/ftr.rb → consumer_groups/virtual_partitions/distributors/consistent.rb} +18 -33
  136. data/lib/karafka/pro/processing/filters/base.rb +3 -61
  137. data/lib/karafka/pro/processing/partitioner.rb +2 -57
  138. data/lib/karafka/pro/processing/schedulers/base.rb +10 -6
  139. data/lib/karafka/pro/processing/schedulers/default.rb +6 -5
  140. data/lib/karafka/pro/recurring_tasks/executor.rb +1 -2
  141. data/lib/karafka/pro/routing/features/{active_job → consumer_groups/active_job}/builder.rb +20 -18
  142. data/lib/karafka/pro/routing/features/{inline_insights/config.rb → consumer_groups/active_job.rb} +5 -9
  143. data/lib/karafka/pro/routing/features/consumer_groups/adaptive_iterator/config.rb +53 -0
  144. data/lib/karafka/pro/routing/features/consumer_groups/adaptive_iterator/contracts/topic.rb +91 -0
  145. data/lib/karafka/pro/routing/features/consumer_groups/adaptive_iterator/topic.rb +90 -0
  146. data/lib/karafka/pro/routing/features/consumer_groups/adaptive_iterator.rb +50 -0
  147. data/lib/karafka/pro/routing/features/{patterns/contracts/consumer_group.rb → consumer_groups/dead_letter_queue/contracts/topic.rb} +25 -30
  148. data/lib/karafka/pro/routing/features/consumer_groups/dead_letter_queue/topic.rb +70 -0
  149. data/lib/karafka/pro/routing/features/consumer_groups/dead_letter_queue.rb +46 -0
  150. data/lib/karafka/pro/routing/features/{direct_assignments → consumer_groups/delaying}/config.rb +6 -4
  151. data/lib/karafka/pro/routing/features/{patterns/contracts/pattern.rb → consumer_groups/delaying/contracts/topic.rb} +13 -16
  152. data/lib/karafka/pro/routing/features/consumer_groups/delaying/topic.rb +85 -0
  153. data/lib/karafka/pro/routing/features/{adaptive_iterator/config.rb → consumer_groups/delaying.rb} +8 -11
  154. data/lib/karafka/pro/routing/features/consumer_groups/direct_assignments/config.rb +46 -0
  155. data/lib/karafka/pro/routing/features/consumer_groups/direct_assignments/contracts/consumer_group.rb +68 -0
  156. data/lib/karafka/pro/routing/features/consumer_groups/direct_assignments/contracts/topic.rb +125 -0
  157. data/lib/karafka/pro/routing/features/consumer_groups/direct_assignments/subscription_group.rb +97 -0
  158. data/lib/karafka/pro/routing/features/consumer_groups/direct_assignments/topic.rb +97 -0
  159. data/lib/karafka/pro/routing/features/consumer_groups/direct_assignments.rb +44 -0
  160. data/lib/karafka/pro/routing/features/consumer_groups/inline_insights/config.rb +51 -0
  161. data/lib/karafka/pro/routing/features/consumer_groups/inline_insights/contracts/topic.rb +58 -0
  162. data/lib/karafka/pro/routing/features/consumer_groups/inline_insights/topic.rb +80 -0
  163. data/lib/karafka/pro/routing/features/consumer_groups/inline_insights.rb +45 -0
  164. data/lib/karafka/pro/routing/features/consumer_groups/long_running_job/config.rb +47 -0
  165. data/lib/karafka/pro/routing/features/{multiplexing/patches/contracts/consumer_group.rb → consumer_groups/long_running_job/contracts/topic.rb} +13 -15
  166. data/lib/karafka/pro/routing/features/consumer_groups/long_running_job/topic.rb +72 -0
  167. data/lib/karafka/pro/routing/features/{long_running_job.rb → consumer_groups/long_running_job.rb} +6 -4
  168. data/lib/karafka/pro/routing/features/consumer_groups/multiplexing/config.rb +58 -0
  169. data/lib/karafka/pro/routing/features/consumer_groups/multiplexing/contracts/routing.rb +83 -0
  170. data/lib/karafka/pro/routing/features/consumer_groups/multiplexing/contracts/topic.rb +148 -0
  171. data/lib/karafka/pro/routing/features/{delaying/contracts/topic.rb → consumer_groups/multiplexing/patches/contracts/consumer_group.rb} +19 -14
  172. data/lib/karafka/pro/routing/features/{multiplexing/subscription_group.rb → consumer_groups/multiplexing/proxy.rb} +17 -23
  173. data/lib/karafka/pro/routing/features/consumer_groups/multiplexing/subscription_group.rb +68 -0
  174. data/lib/karafka/pro/routing/features/{multiplexing → consumer_groups/multiplexing}/subscription_groups_builder.rb +16 -14
  175. data/lib/karafka/pro/routing/features/consumer_groups/multiplexing.rb +85 -0
  176. data/lib/karafka/pro/routing/features/consumer_groups/non_blocking_job/topic.rb +51 -0
  177. data/lib/karafka/pro/routing/features/{non_blocking_job.rb → consumer_groups/non_blocking_job.rb} +15 -13
  178. data/lib/karafka/pro/routing/features/consumer_groups/offset_metadata/config.rb +52 -0
  179. data/lib/karafka/pro/routing/features/consumer_groups/offset_metadata/contracts/topic.rb +59 -0
  180. data/lib/karafka/pro/routing/features/consumer_groups/offset_metadata/topic.rb +93 -0
  181. data/lib/karafka/pro/routing/features/{offset_metadata.rb → consumer_groups/offset_metadata.rb} +16 -14
  182. data/lib/karafka/pro/routing/features/consumer_groups/parallel_segments/builder.rb +74 -0
  183. data/lib/karafka/pro/routing/features/{multiplexing → consumer_groups/parallel_segments}/config.rb +13 -15
  184. data/lib/karafka/pro/routing/features/consumer_groups/parallel_segments/consumer_group.rb +110 -0
  185. data/lib/karafka/pro/routing/features/consumer_groups/parallel_segments/contracts/consumer_group.rb +74 -0
  186. data/lib/karafka/pro/routing/features/{parallel_segments → consumer_groups/parallel_segments}/topic.rb +24 -22
  187. data/lib/karafka/pro/routing/features/consumer_groups/parallel_segments.rb +51 -0
  188. data/lib/karafka/pro/routing/features/{patterns → consumer_groups/patterns}/builder.rb +15 -13
  189. data/lib/karafka/pro/routing/features/{offset_metadata/contracts/topic.rb → consumer_groups/patterns/config.rb} +28 -13
  190. data/lib/karafka/pro/routing/features/consumer_groups/patterns/consumer_group.rb +91 -0
  191. data/lib/karafka/pro/routing/features/consumer_groups/patterns/contracts/consumer_group.rb +83 -0
  192. data/lib/karafka/pro/routing/features/{parallel_segments.rb → consumer_groups/patterns/contracts/pattern.rb} +24 -10
  193. data/lib/karafka/pro/routing/features/consumer_groups/patterns/contracts/topic.rb +58 -0
  194. data/lib/karafka/pro/routing/features/consumer_groups/patterns/detector.rb +98 -0
  195. data/lib/karafka/pro/routing/features/consumer_groups/patterns/pattern.rb +114 -0
  196. data/lib/karafka/pro/routing/features/{recurring_tasks/contracts/topic.rb → consumer_groups/patterns/patterns.rb} +12 -13
  197. data/lib/karafka/pro/routing/features/consumer_groups/patterns/topic.rb +78 -0
  198. data/lib/karafka/pro/routing/features/consumer_groups/patterns/topics.rb +72 -0
  199. data/lib/karafka/pro/routing/features/consumer_groups/patterns.rb +52 -0
  200. data/lib/karafka/pro/routing/features/consumer_groups/periodic_job/config.rb +56 -0
  201. data/lib/karafka/pro/routing/features/{direct_assignments/contracts/consumer_group.rb → consumer_groups/periodic_job/contracts/topic.rb} +17 -22
  202. data/lib/karafka/pro/routing/features/consumer_groups/periodic_job/topic.rb +122 -0
  203. data/lib/karafka/pro/routing/features/consumer_groups/periodic_job.rb +46 -0
  204. data/lib/karafka/pro/routing/features/consumer_groups/recurring_tasks/builder.rb +150 -0
  205. data/lib/karafka/pro/routing/features/{swarm → consumer_groups/recurring_tasks}/config.rb +7 -8
  206. data/lib/karafka/pro/routing/features/{inline_insights → consumer_groups/recurring_tasks}/contracts/topic.rb +14 -13
  207. data/lib/karafka/pro/routing/features/{scheduled_messages → consumer_groups/recurring_tasks}/proxy.rb +6 -4
  208. data/lib/karafka/pro/routing/features/consumer_groups/recurring_tasks/topic.rb +72 -0
  209. data/lib/karafka/pro/routing/features/consumer_groups/recurring_tasks.rb +44 -0
  210. data/lib/karafka/pro/routing/features/consumer_groups/scheduled_messages/builder.rb +154 -0
  211. data/lib/karafka/pro/routing/features/consumer_groups/scheduled_messages/config.rb +47 -0
  212. data/lib/karafka/pro/routing/features/{long_running_job → consumer_groups/scheduled_messages}/contracts/topic.rb +14 -12
  213. data/lib/karafka/pro/routing/features/{delaying/config.rb → consumer_groups/scheduled_messages/proxy.rb} +6 -4
  214. data/lib/karafka/pro/routing/features/consumer_groups/scheduled_messages/topic.rb +72 -0
  215. data/lib/karafka/pro/routing/features/{recurring_tasks/proxy.rb → consumer_groups/scheduled_messages.rb} +3 -4
  216. data/lib/karafka/pro/routing/features/{non_blocking_job/topic.rb → consumer_groups/swarm/config.rb} +9 -8
  217. data/lib/karafka/pro/routing/features/consumer_groups/swarm/contracts/routing.rb +94 -0
  218. data/lib/karafka/pro/routing/features/consumer_groups/swarm/contracts/topic.rb +95 -0
  219. data/lib/karafka/pro/routing/features/consumer_groups/swarm/topic.rb +105 -0
  220. data/lib/karafka/pro/routing/features/consumer_groups/swarm.rb +58 -0
  221. data/lib/karafka/pro/routing/features/consumer_groups/virtual_partitions/config.rb +69 -0
  222. data/lib/karafka/pro/routing/features/{parallel_segments/contracts/consumer_group.rb → consumer_groups/virtual_partitions/contracts/topic.rb} +21 -18
  223. data/lib/karafka/pro/routing/features/consumer_groups/virtual_partitions/topic.rb +101 -0
  224. data/lib/karafka/pro/routing/features/consumer_groups/virtual_partitions.rb +46 -0
  225. data/lib/karafka/pro/routing/features/{scheduled_messages.rb → consumer_groups.rb} +3 -2
  226. data/lib/karafka/pro/routing/features/expiring/topic.rb +4 -4
  227. data/lib/karafka/pro/routing/features/filtering/topic.rb +3 -3
  228. data/lib/karafka/pro/routing/features/pausing/topic.rb +3 -3
  229. data/lib/karafka/pro/routing/features/throttling/topic.rb +4 -4
  230. data/lib/karafka/pro/setup/defaults_injector.rb +70 -0
  231. data/lib/karafka/pro/swarm/liveness_listener.rb +22 -10
  232. data/lib/karafka/processing/consumer_groups/coordinator.rb +221 -0
  233. data/lib/karafka/processing/consumer_groups/coordinators_buffer.rb +69 -0
  234. data/lib/karafka/processing/consumer_groups/executor.rb +220 -0
  235. data/lib/karafka/processing/consumer_groups/executors_buffer.rb +94 -0
  236. data/lib/karafka/processing/consumer_groups/expansions_selector.rb +26 -0
  237. data/lib/karafka/processing/consumer_groups/inline_insights/consumer.rb +47 -0
  238. data/lib/karafka/processing/consumer_groups/inline_insights/listener.rb +23 -0
  239. data/lib/karafka/processing/consumer_groups/inline_insights/tracker.rb +132 -0
  240. data/lib/karafka/processing/consumer_groups/jobs/consume.rb +52 -0
  241. data/lib/karafka/processing/consumer_groups/jobs/eofed.rb +34 -0
  242. data/lib/karafka/processing/consumer_groups/jobs/idle.rb +33 -0
  243. data/lib/karafka/processing/consumer_groups/jobs/revoked.rb +34 -0
  244. data/lib/karafka/processing/consumer_groups/jobs/shutdown.rb +32 -0
  245. data/lib/karafka/processing/consumer_groups/jobs_builder.rb +36 -0
  246. data/lib/karafka/processing/consumer_groups/partitioner.rb +28 -0
  247. data/lib/karafka/processing/consumer_groups/strategies/aj_dlq_mom.rb +48 -0
  248. data/lib/karafka/processing/consumer_groups/strategies/aj_mom.rb +25 -0
  249. data/lib/karafka/processing/consumer_groups/strategies/base.rb +65 -0
  250. data/lib/karafka/processing/consumer_groups/strategies/default.rb +218 -0
  251. data/lib/karafka/processing/consumer_groups/strategies/dlq.rb +157 -0
  252. data/lib/karafka/processing/consumer_groups/strategies/dlq_mom.rb +72 -0
  253. data/lib/karafka/processing/consumer_groups/strategies/mom.rb +33 -0
  254. data/lib/karafka/processing/consumer_groups/strategy_selector.rb +53 -0
  255. data/lib/karafka/processing/coordinator.rb +4 -211
  256. data/lib/karafka/processing/coordinators_buffer.rb +4 -59
  257. data/lib/karafka/processing/jobs_queue.rb +12 -4
  258. data/lib/karafka/processing/partitioner.rb +4 -18
  259. data/lib/karafka/processing/schedulers/default.rb +2 -1
  260. data/lib/karafka/processing/strategy_selector.rb +4 -42
  261. data/lib/karafka/processing/worker.rb +8 -4
  262. data/lib/karafka/processing/workers_pool.rb +158 -0
  263. data/lib/karafka/routing/builder.rb +12 -12
  264. data/lib/karafka/routing/contracts/routing.rb +3 -4
  265. data/lib/karafka/routing/features/base/expander.rb +5 -5
  266. data/lib/karafka/routing/features/consumer_groups/active_job/builder.rb +35 -0
  267. data/lib/karafka/routing/features/consumer_groups/active_job/config.rb +17 -0
  268. data/lib/karafka/routing/features/consumer_groups/active_job/contracts/topic.rb +44 -0
  269. data/lib/karafka/routing/features/consumer_groups/active_job/proxy.rb +16 -0
  270. data/lib/karafka/routing/features/consumer_groups/active_job/topic.rb +50 -0
  271. data/lib/karafka/routing/features/consumer_groups/active_job.rb +15 -0
  272. data/lib/karafka/routing/features/consumer_groups/dead_letter_queue/config.rb +39 -0
  273. data/lib/karafka/routing/features/consumer_groups/dead_letter_queue/contracts/topic.rb +58 -0
  274. data/lib/karafka/routing/features/consumer_groups/dead_letter_queue/topic.rb +76 -0
  275. data/lib/karafka/routing/features/consumer_groups/dead_letter_queue.rb +18 -0
  276. data/lib/karafka/routing/features/consumer_groups/eofed/config.rb +17 -0
  277. data/lib/karafka/routing/features/consumer_groups/eofed/contracts/topic.rb +39 -0
  278. data/lib/karafka/routing/features/consumer_groups/eofed/topic.rb +42 -0
  279. data/lib/karafka/routing/features/consumer_groups/eofed.rb +16 -0
  280. data/lib/karafka/routing/features/consumer_groups/inline_insights/config.rb +17 -0
  281. data/lib/karafka/routing/features/consumer_groups/inline_insights/contracts/topic.rb +27 -0
  282. data/lib/karafka/routing/features/consumer_groups/inline_insights/topic.rb +42 -0
  283. data/lib/karafka/routing/features/consumer_groups/inline_insights.rb +42 -0
  284. data/lib/karafka/routing/features/consumer_groups/manual_offset_management/config.rb +17 -0
  285. data/lib/karafka/routing/features/consumer_groups/manual_offset_management/contracts/topic.rb +27 -0
  286. data/lib/karafka/routing/features/consumer_groups/manual_offset_management/topic.rb +46 -0
  287. data/lib/karafka/routing/features/consumer_groups/manual_offset_management.rb +20 -0
  288. data/lib/karafka/routing/features/consumer_groups.rb +12 -0
  289. data/lib/karafka/routing/features/declaratives/contracts/topic.rb +4 -19
  290. data/lib/karafka/routing/features/declaratives/topic.rb +30 -14
  291. data/lib/karafka/routing/features/deserializers/topic.rb +3 -3
  292. data/lib/karafka/routing/router.rb +2 -2
  293. data/lib/karafka/routing/subscription_group.rb +18 -9
  294. data/lib/karafka/routing/topic.rb +25 -11
  295. data/lib/karafka/runner.rb +17 -17
  296. data/lib/karafka/server.rb +28 -6
  297. data/lib/karafka/setup/attributes_map.rb +2 -0
  298. data/lib/karafka/setup/config.rb +64 -15
  299. data/lib/karafka/setup/config_proxy.rb +1 -2
  300. data/lib/karafka/setup/contracts/config.rb +28 -8
  301. data/lib/karafka/setup/defaults_injector.rb +10 -0
  302. data/lib/karafka/status.rb +1 -2
  303. data/lib/karafka/swarm/liveness_listener.rb +7 -0
  304. data/lib/karafka/swarm/manager.rb +7 -7
  305. data/lib/karafka/swarm/node.rb +8 -0
  306. data/lib/karafka/swarm/supervisor.rb +9 -1
  307. data/lib/karafka/templates/karafka.rb.erb +11 -5
  308. data/lib/karafka/version.rb +1 -1
  309. metadata +237 -224
  310. data/lib/karafka/connection/rebalance_manager.rb +0 -116
  311. data/lib/karafka/instrumentation/callbacks/error.rb +0 -52
  312. data/lib/karafka/instrumentation/callbacks/rebalance.rb +0 -84
  313. data/lib/karafka/instrumentation/callbacks/statistics.rb +0 -55
  314. data/lib/karafka/pro/processing/adaptive_iterator/consumer.rb +0 -79
  315. data/lib/karafka/pro/processing/adaptive_iterator/tracker.rb +0 -92
  316. data/lib/karafka/pro/processing/collapser.rb +0 -79
  317. data/lib/karafka/pro/processing/coordinator.rb +0 -197
  318. data/lib/karafka/pro/processing/coordinators/errors_tracker.rb +0 -119
  319. data/lib/karafka/pro/processing/coordinators/filters_applier.rb +0 -152
  320. data/lib/karafka/pro/processing/coordinators/virtual_offset_manager.rb +0 -207
  321. data/lib/karafka/pro/processing/expansions_selector.rb +0 -52
  322. data/lib/karafka/pro/processing/filters/delayer.rb +0 -87
  323. data/lib/karafka/pro/processing/filters/inline_insights_delayer.rb +0 -95
  324. data/lib/karafka/pro/processing/filters/throttler.rb +0 -101
  325. data/lib/karafka/pro/processing/filters/virtual_limiter.rb +0 -74
  326. data/lib/karafka/pro/processing/jobs/eofed_non_blocking.rb +0 -51
  327. data/lib/karafka/pro/processing/jobs_builder.rb +0 -90
  328. data/lib/karafka/pro/processing/offset_metadata/consumer.rb +0 -61
  329. data/lib/karafka/pro/processing/offset_metadata/fetcher.rb +0 -149
  330. data/lib/karafka/pro/processing/offset_metadata/listener.rb +0 -63
  331. data/lib/karafka/pro/processing/parallel_segments/filters/base.rb +0 -98
  332. data/lib/karafka/pro/processing/parallel_segments/filters/default.rb +0 -110
  333. data/lib/karafka/pro/processing/parallel_segments/filters/mom.rb +0 -91
  334. data/lib/karafka/pro/processing/periodic_job/consumer.rb +0 -85
  335. data/lib/karafka/pro/processing/piping/consumer.rb +0 -149
  336. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom_vp.rb +0 -94
  337. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom.rb +0 -87
  338. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom_vp.rb +0 -85
  339. data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom.rb +0 -81
  340. data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom_vp.rb +0 -85
  341. data/lib/karafka/pro/processing/strategies/aj/dlq_mom.rb +0 -79
  342. data/lib/karafka/pro/processing/strategies/aj/dlq_mom_vp.rb +0 -84
  343. data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom_vp.rb +0 -86
  344. data/lib/karafka/pro/processing/strategies/aj/lrj_mom.rb +0 -54
  345. data/lib/karafka/pro/processing/strategies/aj/lrj_mom_vp.rb +0 -101
  346. data/lib/karafka/pro/processing/strategies/base.rb +0 -43
  347. data/lib/karafka/pro/processing/strategies/default.rb +0 -416
  348. data/lib/karafka/pro/processing/strategies/dlq/default.rb +0 -280
  349. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj.rb +0 -90
  350. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom.rb +0 -92
  351. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom_vp.rb +0 -60
  352. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_vp.rb +0 -58
  353. data/lib/karafka/pro/processing/strategies/dlq/ftr_mom.rb +0 -92
  354. data/lib/karafka/pro/processing/strategies/dlq/ftr_mom_vp.rb +0 -58
  355. data/lib/karafka/pro/processing/strategies/dlq/ftr_vp.rb +0 -57
  356. data/lib/karafka/pro/processing/strategies/dlq/lrj_mom.rb +0 -95
  357. data/lib/karafka/pro/processing/strategies/dlq/lrj_vp.rb +0 -56
  358. data/lib/karafka/pro/processing/strategies/dlq/mom.rb +0 -91
  359. data/lib/karafka/pro/processing/strategies/dlq/mom_vp.rb +0 -54
  360. data/lib/karafka/pro/processing/strategies/dlq/vp.rb +0 -57
  361. data/lib/karafka/pro/processing/strategies/ftr/default.rb +0 -141
  362. data/lib/karafka/pro/processing/strategies/ftr/vp.rb +0 -57
  363. data/lib/karafka/pro/processing/strategies/lrj/default.rb +0 -114
  364. data/lib/karafka/pro/processing/strategies/lrj/ftr.rb +0 -89
  365. data/lib/karafka/pro/processing/strategies/lrj/ftr_mom.rb +0 -87
  366. data/lib/karafka/pro/processing/strategies/lrj/ftr_mom_vp.rb +0 -57
  367. data/lib/karafka/pro/processing/strategies/lrj/ftr_vp.rb +0 -56
  368. data/lib/karafka/pro/processing/strategies/lrj/mom.rb +0 -96
  369. data/lib/karafka/pro/processing/strategies/mom/ftr_vp.rb +0 -54
  370. data/lib/karafka/pro/processing/strategies/vp/default.rb +0 -192
  371. data/lib/karafka/pro/processing/strategies.rb +0 -39
  372. data/lib/karafka/pro/processing/strategy_selector.rb +0 -102
  373. data/lib/karafka/pro/processing/subscription_groups_coordinator.rb +0 -68
  374. data/lib/karafka/pro/processing/virtual_partitions/distributors/balanced.rb +0 -77
  375. data/lib/karafka/pro/routing/features/active_job.rb +0 -43
  376. data/lib/karafka/pro/routing/features/adaptive_iterator/contracts/topic.rb +0 -89
  377. data/lib/karafka/pro/routing/features/adaptive_iterator/topic.rb +0 -88
  378. data/lib/karafka/pro/routing/features/adaptive_iterator.rb +0 -48
  379. data/lib/karafka/pro/routing/features/dead_letter_queue/contracts/topic.rb +0 -74
  380. data/lib/karafka/pro/routing/features/dead_letter_queue/topic.rb +0 -68
  381. data/lib/karafka/pro/routing/features/dead_letter_queue.rb +0 -44
  382. data/lib/karafka/pro/routing/features/delaying/topic.rb +0 -83
  383. data/lib/karafka/pro/routing/features/delaying.rb +0 -46
  384. data/lib/karafka/pro/routing/features/direct_assignments/contracts/topic.rb +0 -123
  385. data/lib/karafka/pro/routing/features/direct_assignments/subscription_group.rb +0 -95
  386. data/lib/karafka/pro/routing/features/direct_assignments/topic.rb +0 -95
  387. data/lib/karafka/pro/routing/features/direct_assignments.rb +0 -42
  388. data/lib/karafka/pro/routing/features/inline_insights/topic.rb +0 -78
  389. data/lib/karafka/pro/routing/features/inline_insights.rb +0 -43
  390. data/lib/karafka/pro/routing/features/long_running_job/config.rb +0 -45
  391. data/lib/karafka/pro/routing/features/long_running_job/topic.rb +0 -70
  392. data/lib/karafka/pro/routing/features/multiplexing/contracts/routing.rb +0 -81
  393. data/lib/karafka/pro/routing/features/multiplexing/contracts/topic.rb +0 -146
  394. data/lib/karafka/pro/routing/features/multiplexing/proxy.rb +0 -58
  395. data/lib/karafka/pro/routing/features/multiplexing.rb +0 -83
  396. data/lib/karafka/pro/routing/features/offset_metadata/config.rb +0 -50
  397. data/lib/karafka/pro/routing/features/offset_metadata/topic.rb +0 -91
  398. data/lib/karafka/pro/routing/features/parallel_segments/builder.rb +0 -72
  399. data/lib/karafka/pro/routing/features/parallel_segments/config.rb +0 -52
  400. data/lib/karafka/pro/routing/features/parallel_segments/consumer_group.rb +0 -108
  401. data/lib/karafka/pro/routing/features/patterns/config.rb +0 -71
  402. data/lib/karafka/pro/routing/features/patterns/consumer_group.rb +0 -89
  403. data/lib/karafka/pro/routing/features/patterns/contracts/topic.rb +0 -56
  404. data/lib/karafka/pro/routing/features/patterns/detector.rb +0 -96
  405. data/lib/karafka/pro/routing/features/patterns/pattern.rb +0 -112
  406. data/lib/karafka/pro/routing/features/patterns/topic.rb +0 -76
  407. data/lib/karafka/pro/routing/features/patterns/topics.rb +0 -70
  408. data/lib/karafka/pro/routing/features/patterns.rb +0 -50
  409. data/lib/karafka/pro/routing/features/periodic_job/config.rb +0 -54
  410. data/lib/karafka/pro/routing/features/periodic_job/contracts/topic.rb +0 -59
  411. data/lib/karafka/pro/routing/features/periodic_job/topic.rb +0 -120
  412. data/lib/karafka/pro/routing/features/periodic_job.rb +0 -44
  413. data/lib/karafka/pro/routing/features/recurring_tasks/builder.rb +0 -148
  414. data/lib/karafka/pro/routing/features/recurring_tasks/config.rb +0 -45
  415. data/lib/karafka/pro/routing/features/recurring_tasks/topic.rb +0 -70
  416. data/lib/karafka/pro/routing/features/recurring_tasks.rb +0 -42
  417. data/lib/karafka/pro/routing/features/scheduled_messages/builder.rb +0 -152
  418. data/lib/karafka/pro/routing/features/scheduled_messages/config.rb +0 -45
  419. data/lib/karafka/pro/routing/features/scheduled_messages/contracts/topic.rb +0 -55
  420. data/lib/karafka/pro/routing/features/scheduled_messages/topic.rb +0 -70
  421. data/lib/karafka/pro/routing/features/swarm/contracts/routing.rb +0 -92
  422. data/lib/karafka/pro/routing/features/swarm/contracts/topic.rb +0 -93
  423. data/lib/karafka/pro/routing/features/swarm/topic.rb +0 -103
  424. data/lib/karafka/pro/routing/features/swarm.rb +0 -56
  425. data/lib/karafka/pro/routing/features/virtual_partitions/config.rb +0 -67
  426. data/lib/karafka/pro/routing/features/virtual_partitions/contracts/topic.rb +0 -73
  427. data/lib/karafka/pro/routing/features/virtual_partitions/topic.rb +0 -99
  428. data/lib/karafka/pro/routing/features/virtual_partitions.rb +0 -44
  429. data/lib/karafka/processing/executor.rb +0 -216
  430. data/lib/karafka/processing/executors_buffer.rb +0 -90
  431. data/lib/karafka/processing/expansions_selector.rb +0 -22
  432. data/lib/karafka/processing/inline_insights/consumer.rb +0 -43
  433. data/lib/karafka/processing/inline_insights/listener.rb +0 -19
  434. data/lib/karafka/processing/inline_insights/tracker.rb +0 -129
  435. data/lib/karafka/processing/jobs/consume.rb +0 -47
  436. data/lib/karafka/processing/jobs/eofed.rb +0 -29
  437. data/lib/karafka/processing/jobs/idle.rb +0 -31
  438. data/lib/karafka/processing/jobs/revoked.rb +0 -29
  439. data/lib/karafka/processing/jobs/shutdown.rb +0 -30
  440. data/lib/karafka/processing/jobs_builder.rb +0 -34
  441. data/lib/karafka/processing/strategies/aj_dlq_mom.rb +0 -44
  442. data/lib/karafka/processing/strategies/aj_mom.rb +0 -21
  443. data/lib/karafka/processing/strategies/base.rb +0 -61
  444. data/lib/karafka/processing/strategies/default.rb +0 -214
  445. data/lib/karafka/processing/strategies/dlq.rb +0 -153
  446. data/lib/karafka/processing/strategies/dlq_mom.rb +0 -68
  447. data/lib/karafka/processing/strategies/mom.rb +0 -29
  448. data/lib/karafka/processing/workers_batch.rb +0 -29
  449. data/lib/karafka/routing/features/active_job/builder.rb +0 -33
  450. data/lib/karafka/routing/features/active_job/config.rb +0 -15
  451. data/lib/karafka/routing/features/active_job/contracts/topic.rb +0 -42
  452. data/lib/karafka/routing/features/active_job/proxy.rb +0 -14
  453. data/lib/karafka/routing/features/active_job/topic.rb +0 -48
  454. data/lib/karafka/routing/features/active_job.rb +0 -13
  455. data/lib/karafka/routing/features/dead_letter_queue/config.rb +0 -37
  456. data/lib/karafka/routing/features/dead_letter_queue/contracts/topic.rb +0 -56
  457. data/lib/karafka/routing/features/dead_letter_queue/topic.rb +0 -74
  458. data/lib/karafka/routing/features/dead_letter_queue.rb +0 -16
  459. data/lib/karafka/routing/features/declaratives/config.rb +0 -18
  460. data/lib/karafka/routing/features/eofed/config.rb +0 -15
  461. data/lib/karafka/routing/features/eofed/contracts/topic.rb +0 -37
  462. data/lib/karafka/routing/features/eofed/topic.rb +0 -40
  463. data/lib/karafka/routing/features/eofed.rb +0 -14
  464. data/lib/karafka/routing/features/inline_insights/config.rb +0 -15
  465. data/lib/karafka/routing/features/inline_insights/contracts/topic.rb +0 -25
  466. data/lib/karafka/routing/features/inline_insights/topic.rb +0 -40
  467. data/lib/karafka/routing/features/inline_insights.rb +0 -40
  468. data/lib/karafka/routing/features/manual_offset_management/config.rb +0 -15
  469. data/lib/karafka/routing/features/manual_offset_management/contracts/topic.rb +0 -25
  470. data/lib/karafka/routing/features/manual_offset_management/topic.rb +0 -44
  471. data/lib/karafka/routing/features/manual_offset_management.rb +0 -18
@@ -1,416 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Karafka Pro - Source Available Commercial Software
4
- # Copyright (c) 2017-present Maciej Mensfeld. All rights reserved.
5
- #
6
- # This software is NOT open source. It is source-available commercial software
7
- # requiring a paid license for use. It is NOT covered by LGPL.
8
- #
9
- # The author retains all right, title, and interest in this software,
10
- # including all copyrights, patents, and other intellectual property rights.
11
- # No patent rights are granted under this license.
12
- #
13
- # PROHIBITED:
14
- # - Use without a valid commercial license
15
- # - Redistribution, modification, or derivative works without authorization
16
- # - Reverse engineering, decompilation, or disassembly of this software
17
- # - Use as training data for AI/ML models or inclusion in datasets
18
- # - Scraping, crawling, or automated collection for any purpose
19
- #
20
- # PERMITTED:
21
- # - Reading, referencing, and linking for personal or commercial use
22
- # - Runtime retrieval by AI assistants, coding agents, and RAG systems
23
- # for the purpose of providing contextual help to Karafka users
24
- #
25
- # Receipt, viewing, or possession of this software does not convey or
26
- # imply any license or right beyond those expressly stated above.
27
- #
28
- # License: https://karafka.io/docs/Pro-License-Comm/
29
- # Contact: contact@karafka.io
30
-
31
- module Karafka
32
- module Pro
33
- module Processing
34
- module Strategies
35
- # No features enabled.
36
- # No manual offset management
37
- # No long running jobs
38
- # No virtual partitions
39
- # Nothing. Just standard, automatic flow
40
- module Default
41
- include Base
42
- include Karafka::Processing::Strategies::Default
43
-
44
- # Apply strategy for a non-feature based flow
45
- FEATURES = %i[].freeze
46
-
47
- # Allows to set offset metadata that will be used with the upcoming marking as consumed
48
- # as long as a different offset metadata was not used. After it was used either via
49
- # `#mark_as_consumed` or `#mark_as_consumed!` it will be set back to `nil`. It is done
50
- # that way to provide the end user with ability to influence metadata on the non-user
51
- # initiated markings in complex flows.
52
- #
53
- # @param offset_metadata [String, nil] metadata we want to store with the upcoming
54
- # marking as consumed
55
- #
56
- # @note Please be aware, that offset metadata set this way will be passed to any marking
57
- # as consumed even if it was not user initiated. For example in the DLQ flow.
58
- def store_offset_metadata(offset_metadata)
59
- @_current_offset_metadata = offset_metadata
60
- end
61
-
62
- # Marks message as consumed in an async way.
63
- #
64
- # @param message [Messages::Message] last successfully processed message.
65
- # @param offset_metadata [String, nil] offset metadata string or nil if nothing
66
- # @return [Boolean] true if we were able to mark the offset, false otherwise.
67
- # False indicates that we were not able and that we have lost the partition.
68
- #
69
- # @note We keep track of this offset in case we would mark as consumed and got error when
70
- # processing another message. In case like this we do not pause on the message we've
71
- # already processed but rather at the next one. This applies to both sync and async
72
- # versions of this method.
73
- def mark_as_consumed(message, offset_metadata = @_current_offset_metadata)
74
- # If we are inside a transaction than we can just mark as consumed within it
75
- if @_in_transaction
76
- mark_in_transaction(message, offset_metadata, true)
77
- elsif @_in_transaction_marked
78
- mark_in_memory(message)
79
- else
80
- # seek offset can be nil only in case `#seek` was invoked with offset reset request
81
- # In case like this we ignore marking
82
- return true if seek_offset.nil?
83
- # Ignore if it is the same offset as the one that is marked currently
84
- # We ignore second marking because it changes nothing and in case of people using
85
- # metadata storage but with automatic offset marking, this would cause metadata to be
86
- # erased by automatic marking
87
- return true if (seek_offset - 1) == message.offset
88
- return false if revoked?
89
-
90
- # If we are not inside a transaction but this is a transactional topic, we mark with
91
- # artificially created transaction
92
- stored = if producer.transactional?
93
- mark_with_transaction(message, offset_metadata, true)
94
- elsif @_transactional_marking
95
- raise Errors::NonTransactionalMarkingAttemptError
96
- else
97
- client.mark_as_consumed(message, offset_metadata)
98
- end
99
-
100
- return revoked? unless stored
101
-
102
- self.seek_offset = message.offset + 1
103
- end
104
-
105
- true
106
- ensure
107
- @_current_offset_metadata = nil
108
- end
109
-
110
- # Marks message as consumed in a sync way.
111
- #
112
- # @param message [Messages::Message] last successfully processed message.
113
- # @param offset_metadata [String, nil] offset metadata string or nil if nothing
114
- # @return [Boolean] true if we were able to mark the offset, false otherwise.
115
- # False indicates that we were not able and that we have lost the partition.
116
- def mark_as_consumed!(message, offset_metadata = @_current_offset_metadata)
117
- if @_in_transaction
118
- mark_in_transaction(message, offset_metadata, false)
119
- elsif @_in_transaction_marked
120
- mark_in_memory(message)
121
- else
122
- # seek offset can be nil only in case `#seek` was invoked with offset reset request
123
- # In case like this we ignore marking
124
- return true if seek_offset.nil?
125
- # Ignore if it is the same offset as the one that is marked currently
126
- # We ignore second marking because it changes nothing and in case of people using
127
- # metadata storage but with automatic offset marking, this would cause metadata to be
128
- # erased by automatic marking
129
- return true if (seek_offset - 1) == message.offset
130
- return false if revoked?
131
-
132
- # If we are not inside a transaction but this is a transactional topic, we mark with
133
- # artificially created transaction
134
- stored = if producer.transactional?
135
- mark_with_transaction(message, offset_metadata, false)
136
- elsif @_transactional_marking
137
- raise Errors::NonTransactionalMarkingAttemptError
138
- else
139
- client.mark_as_consumed!(message, offset_metadata)
140
- end
141
-
142
- return revoked? unless stored
143
-
144
- self.seek_offset = message.offset + 1
145
- end
146
-
147
- true
148
- ensure
149
- @_current_offset_metadata = nil
150
- end
151
-
152
- # Starts producer transaction, saves the transaction context for transactional marking
153
- # and runs user code in this context
154
- #
155
- # Transactions on a consumer level differ from those initiated by the producer as they
156
- # allow to mark offsets inside of the transaction. If the transaction is initialized
157
- # only from the consumer, the offset will be stored in a regular fashion.
158
- #
159
- # @param active_producer [WaterDrop::Producer] alternative producer instance we may want
160
- # to use. It is useful when we have connection pool or any other selective engine for
161
- # managing multiple producers. If not provided, default producer taken from `#producer`
162
- # will be used.
163
- #
164
- # @yield code that we want to run in a transaction
165
- #
166
- # @note Please note, that if you provide the producer, it will reassign the producer of
167
- # the consumer for the transaction time. This means, that in case you would even
168
- # accidentally refer to `Consumer#producer` from other threads, it will contain the
169
- # reassigned producer and not the initially used/assigned producer. It is done that
170
- # way, so the message producing aliases operate from within transactions and since the
171
- # producer in transaction is locked, it will prevent other threads from using it.
172
- def transaction(active_producer = producer)
173
- default_producer = nil
174
- transaction_started = nil
175
-
176
- monitor.instrument("consumer.consuming.transaction", caller: self) do
177
- default_producer = producer
178
- self.producer = active_producer
179
-
180
- transaction_started = false
181
- transaction_completed = false
182
-
183
- # Prevent from nested transactions. It would not make any sense
184
- raise Errors::TransactionAlreadyInitializedError if @_in_transaction
185
-
186
- transaction_started = true
187
- @_transaction_marked = []
188
- @_in_transaction = true
189
- @_in_transaction_marked = false
190
-
191
- producer.transaction do
192
- yield
193
-
194
- # Ensure this transaction is rolled back if we have lost the ownership of this
195
- # transaction. We do it only for transactions that contain offset management as for
196
- # producer only, this is not relevant.
197
- raise Errors::AssignmentLostError if @_in_transaction_marked && revoked?
198
-
199
- # If we do not reach this, we should not move seek offsets because it means that
200
- # either an error occured or transaction was aborted.
201
- # In case of error, it will bubble up so no issue but in case of abort, while we
202
- # do not reach this place, the code will continue
203
- transaction_completed = true
204
- end
205
-
206
- @_in_transaction = false
207
-
208
- # This offset is already stored in transaction but we set it here anyhow because we
209
- # want to make sure our internal in-memory state is aligned with the transaction
210
- #
211
- # @note We never need to use the blocking `#mark_as_consumed!` here because the
212
- # offset anyhow was already stored during the transaction
213
- #
214
- # @note Since the offset could have been already stored in Kafka (could have because
215
- # you can have transactions without marking), we use the `@_in_transaction_marked`
216
- # state to decide if we need to dispatch the offset via client at all
217
- # (if post transaction, then we do not have to)
218
- #
219
- # @note In theory we could only keep reference to the most recent marking and reject
220
- # others. We however do not do it for two reasons:
221
- # - User may have non standard flow relying on some alternative order and we want
222
- # to mimic this
223
- # - Complex strategies like VPs can use this in VPs to mark in parallel without
224
- # having to redefine the transactional flow completely
225
- #
226
- # @note This should be applied only if transaction did not error and if it was not
227
- # aborted.
228
- if transaction_completed
229
- @_transaction_marked.each do |marking|
230
- marking.pop ? mark_as_consumed(*marking) : mark_as_consumed!(*marking)
231
- end
232
- end
233
-
234
- true
235
- end
236
- ensure
237
- self.producer = default_producer
238
-
239
- if transaction_started
240
- @_transaction_marked.clear
241
- @_in_transaction = false
242
- @_in_transaction_marked = false
243
- end
244
- end
245
-
246
- # Stores the next offset for processing inside of the transaction and stores it in a
247
- # local accumulator for post-transaction status update
248
- #
249
- # @param message [Messages::Message] message we want to commit inside of a transaction
250
- # @param offset_metadata [String, nil] offset metadata or nil if none
251
- # @param async [Boolean] should we mark in async or sync way (applicable only to post
252
- # transaction state synchronization usage as within transaction it is always sync)
253
- def mark_in_transaction(message, offset_metadata, async)
254
- raise Errors::TransactionRequiredError unless @_in_transaction
255
- raise Errors::AssignmentLostError if revoked?
256
-
257
- producer.transaction_mark_as_consumed(
258
- client,
259
- message,
260
- offset_metadata
261
- )
262
-
263
- # This one is long lived and used to make sure, that users do not mix transactional
264
- # marking with non-transactional. When this happens we should raise error
265
- @_transactional_marking = true
266
- @_in_transaction_marked = true
267
- @_transaction_marked ||= []
268
- @_transaction_marked << [message, offset_metadata, async]
269
- end
270
-
271
- # @private
272
- # @param message [Messages::Message] message we want to commit inside of a transaction
273
- # @param offset_metadata [String, nil] offset metadata or nil if none
274
- # @param async [Boolean] should we mark in async or sync way (applicable only to post
275
- # transaction state synchronization usage as within transaction it is always sync)
276
- # @return [Boolean] false if marking failed otherwise true
277
- def mark_with_transaction(message, offset_metadata, async)
278
- # This flag is used by VPs to differentiate between user initiated transactions and
279
- # post-execution system transactions.
280
- @_transaction_internal = true
281
-
282
- transaction do
283
- mark_in_transaction(message, offset_metadata, async)
284
- end
285
-
286
- true
287
- # We handle both cases here because this is a private API for internal usage and we want
288
- # the post-user code execution marking with transactional producer to result in a
289
- # boolean state of marking for further framework flow. This is a normalization to make it
290
- # behave the same way as it would behave with a non-transactional one
291
- rescue Rdkafka::RdkafkaError, Errors::AssignmentLostError
292
- false
293
- ensure
294
- @_transaction_internal = false
295
- end
296
-
297
- # Marks the current state only in memory as the offset marking has already happened
298
- # using the producer transaction
299
- # @param message [Messages::Message] last successfully processed message.
300
- # @return [Boolean] true if all good, false if we lost assignment and no point in marking
301
- def mark_in_memory(message)
302
- # seek offset can be nil only in case `#seek` was invoked with offset reset request
303
- # In case like this we ignore marking
304
- return true if seek_offset.nil?
305
- # Ignore if it is the same offset as the one that is marked currently
306
- # We ignore second marking because it changes nothing and in case of people using
307
- # metadata storage but with automatic offset marking, this would cause metadata to be
308
- # erased by automatic marking
309
- return true if (seek_offset - 1) == message.offset
310
- return false if revoked?
311
-
312
- # If we have already marked this successfully in a transaction that was running
313
- # we should not mark it again with the client offset delegation but instead we should
314
- # just align the in-memory state
315
- self.seek_offset = message.offset + 1
316
-
317
- true
318
- end
319
-
320
- # No actions needed for the standard flow here
321
- def handle_before_schedule_consume
322
- monitor.instrument("consumer.before_schedule_consume", caller: self)
323
-
324
- nil
325
- end
326
-
327
- # Increment number of attempts per one "full" job. For all VP on a single topic partition
328
- # this also should run once.
329
- def handle_before_consume
330
- coordinator.on_started do
331
- coordinator.pause_tracker.increment
332
- end
333
- end
334
-
335
- # Run the user consumption code
336
- def handle_consume
337
- # We should not run the work at all on a partition that was revoked
338
- # This can happen primarily when an LRJ job gets to the internal worker queue and
339
- # this partition is revoked prior processing.
340
- unless revoked?
341
- monitor.instrument("consumer.consume", caller: self)
342
- monitor.instrument("consumer.consumed", caller: self) do
343
- consume
344
- end
345
- end
346
-
347
- # Mark job as successful
348
- coordinator.success!(self)
349
- rescue => e
350
- # If failed, mark as failed
351
- coordinator.failure!(self, e)
352
-
353
- # Re-raise so reported in the consumer
354
- raise e
355
- ensure
356
- # We need to decrease number of jobs that this coordinator coordinates as it has
357
- # finished
358
- coordinator.decrement(:consume)
359
- end
360
-
361
- # Standard flow without any features
362
- def handle_after_consume
363
- coordinator.on_finished do |last_group_message|
364
- return if revoked?
365
-
366
- if coordinator.success?
367
- coordinator.pause_tracker.reset
368
-
369
- # Do not mark last message if pause happened. This prevents a scenario where pause
370
- # is overridden upon rebalance by marking
371
- return if coordinator.manual_pause?
372
-
373
- mark_as_consumed(last_group_message)
374
- else
375
- retry_after_pause
376
- end
377
- end
378
- end
379
-
380
- # Standard flow for revocation
381
- def handle_revoked
382
- coordinator.on_revoked do
383
- resume
384
-
385
- coordinator.revoke
386
- end
387
-
388
- monitor.instrument("consumer.revoke", caller: self)
389
- monitor.instrument("consumer.revoked", caller: self) do
390
- revoked
391
- end
392
- ensure
393
- coordinator.decrement(:revoked)
394
- end
395
-
396
- # No action needed for the tick standard flow
397
- def handle_before_schedule_tick
398
- monitor.instrument("consumer.before_schedule_tick", caller: self)
399
-
400
- nil
401
- end
402
-
403
- # Runs the consumer `#tick` method with reporting
404
- def handle_tick
405
- monitor.instrument("consumer.tick", caller: self)
406
- monitor.instrument("consumer.ticked", caller: self) do
407
- tick
408
- end
409
- ensure
410
- coordinator.decrement(:periodic)
411
- end
412
- end
413
- end
414
- end
415
- end
416
- end
@@ -1,280 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Karafka Pro - Source Available Commercial Software
4
- # Copyright (c) 2017-present Maciej Mensfeld. All rights reserved.
5
- #
6
- # This software is NOT open source. It is source-available commercial software
7
- # requiring a paid license for use. It is NOT covered by LGPL.
8
- #
9
- # The author retains all right, title, and interest in this software,
10
- # including all copyrights, patents, and other intellectual property rights.
11
- # No patent rights are granted under this license.
12
- #
13
- # PROHIBITED:
14
- # - Use without a valid commercial license
15
- # - Redistribution, modification, or derivative works without authorization
16
- # - Reverse engineering, decompilation, or disassembly of this software
17
- # - Use as training data for AI/ML models or inclusion in datasets
18
- # - Scraping, crawling, or automated collection for any purpose
19
- #
20
- # PERMITTED:
21
- # - Reading, referencing, and linking for personal or commercial use
22
- # - Runtime retrieval by AI assistants, coding agents, and RAG systems
23
- # for the purpose of providing contextual help to Karafka users
24
- #
25
- # Receipt, viewing, or possession of this software does not convey or
26
- # imply any license or right beyond those expressly stated above.
27
- #
28
- # License: https://karafka.io/docs/Pro-License-Comm/
29
- # Contact: contact@karafka.io
30
-
31
- module Karafka
32
- module Pro
33
- module Processing
34
- module Strategies
35
- # Namespace for all the strategies starting with DLQ
36
- module Dlq
37
- # Only dead letter queue enabled
38
- module Default
39
- include Strategies::Default
40
-
41
- # Features for this strategy
42
- FEATURES = %i[
43
- dead_letter_queue
44
- ].freeze
45
-
46
- # Override of the standard `#mark_as_consumed` in order to handle the pause tracker
47
- # reset in case DLQ is marked as fully independent. When DLQ is marked independent,
48
- # any offset marking causes the pause count tracker to reset. This is useful when
49
- # the error is not due to the collective batch operations state but due to intermediate
50
- # "crawling" errors that move with it
51
- #
52
- # @see `Strategies::Default#mark_as_consumed` for more details
53
- # @param message [Messages::Message]
54
- # @param offset_metadata [String, nil]
55
- def mark_as_consumed(message, offset_metadata = @_current_offset_metadata)
56
- return super unless retrying?
57
- return super unless topic.dead_letter_queue.independent?
58
- return false unless super
59
-
60
- coordinator.pause_tracker.reset
61
-
62
- true
63
- ensure
64
- @_current_offset_metadata = nil
65
- end
66
-
67
- # Override of the standard `#mark_as_consumed!`. Resets the pause tracker count in case
68
- # DLQ was configured with the `independent` flag.
69
- #
70
- # @see `Strategies::Default#mark_as_consumed!` for more details
71
- # @param message [Messages::Message]
72
- # @param offset_metadata [String, nil]
73
- def mark_as_consumed!(message, offset_metadata = @_current_offset_metadata)
74
- return super unless retrying?
75
- return super unless topic.dead_letter_queue.independent?
76
- return false unless super
77
-
78
- coordinator.pause_tracker.reset
79
-
80
- true
81
- ensure
82
- @_current_offset_metadata = nil
83
- end
84
-
85
- # When we encounter non-recoverable message, we skip it and go on with our lives
86
- def handle_after_consume
87
- coordinator.on_finished do |last_group_message|
88
- return if revoked?
89
-
90
- if coordinator.success?
91
- coordinator.pause_tracker.reset
92
-
93
- return if coordinator.manual_pause?
94
-
95
- mark_as_consumed(last_group_message)
96
- else
97
- apply_dlq_flow do
98
- dispatch_if_needed_and_mark_as_consumed
99
- end
100
- end
101
- end
102
- end
103
-
104
- # Finds the message may want to skip (all, starting from first)
105
- # @private
106
- # @return [Array<Karafka::Messages::Message, Boolean>] message we may want to skip and
107
- # information if this message was from marked offset or figured out via mom flow
108
- def find_skippable_message
109
- skippable_message = messages.raw.find do |msg|
110
- coordinator.marked? && msg.offset == seek_offset
111
- end
112
-
113
- # If we don't have the message matching the last comitted offset, it means that
114
- # user operates with manual offsets and we're beyond the batch in which things
115
- # broke for the first time. Then we skip the first (as no markings) and we
116
- # move on one by one.
117
- skippable_message ? [skippable_message, true] : [messages.first, false]
118
- end
119
-
120
- # Moves the broken message into a separate queue defined via the settings
121
- #
122
- # @param skippable_message [Array<Karafka::Messages::Message>] message we want to
123
- # dispatch to DLQ
124
- def dispatch_to_dlq(skippable_message)
125
- # DLQ should never try to dispatch a message that was cleaned. It message was
126
- # cleaned, we will not have all the needed data. If you see this error, it means
127
- # that your processing flow is not as expected and you have cleaned message that
128
- # should not be cleaned as it should go to the DLQ
129
- raise(Cleaner::Errors::MessageCleanedError) if skippable_message.cleaned?
130
-
131
- producer.public_send(
132
- topic.dead_letter_queue.dispatch_method,
133
- build_dlq_message(
134
- skippable_message
135
- )
136
- )
137
-
138
- # Notify about dispatch on the events bus
139
- monitor.instrument(
140
- "dead_letter_queue.dispatched",
141
- caller: self,
142
- message: skippable_message
143
- )
144
- end
145
-
146
- # Dispatches the message to the DLQ (when needed and when applicable based on settings)
147
- # and marks this message as consumed for non MOM flows.
148
- #
149
- # If producer is transactional and config allows, uses transaction to do that
150
- def dispatch_if_needed_and_mark_as_consumed
151
- skippable_message, = find_skippable_message
152
-
153
- dispatch = lambda do
154
- dispatch_to_dlq(skippable_message) if dispatch_to_dlq?
155
-
156
- if mark_after_dispatch?
157
- mark_dispatched_to_dlq(skippable_message)
158
- else
159
- self.seek_offset = skippable_message.offset + 1
160
- end
161
- end
162
-
163
- if dispatch_in_a_transaction?
164
- transaction { dispatch.call }
165
- else
166
- dispatch.call
167
- end
168
- end
169
-
170
- # @param skippable_message [Array<Karafka::Messages::Message>]
171
- # @return [Hash] dispatch DLQ message
172
- def build_dlq_message(skippable_message)
173
- source_partition = skippable_message.partition.to_s
174
-
175
- dlq_message = {
176
- topic: @_dispatch_to_dlq_topic || topic.dead_letter_queue.topic,
177
- key: skippable_message.raw_key,
178
- partition_key: source_partition,
179
- payload: skippable_message.raw_payload,
180
- headers: skippable_message.raw_headers.merge(
181
- "source_topic" => topic.name,
182
- "source_partition" => source_partition,
183
- "source_offset" => skippable_message.offset.to_s,
184
- "source_consumer_group" => topic.consumer_group.id,
185
- "source_attempts" => attempt.to_s,
186
- "source_trace_id" => errors_tracker.trace_id
187
- )
188
- }
189
-
190
- # Optional method user can define in consumer to enhance the dlq message hash with
191
- # some extra details if needed or to replace payload, etc
192
- if respond_to?(:enhance_dlq_message, true)
193
- enhance_dlq_message(
194
- dlq_message,
195
- skippable_message
196
- )
197
- end
198
-
199
- dlq_message
200
- end
201
-
202
- # @return [Boolean] should we dispatch the message to DLQ or not. When the dispatch
203
- # topic is set to false, we will skip the dispatch, effectively ignoring the broken
204
- # message without taking any action.
205
- def dispatch_to_dlq?
206
- return false unless topic.dead_letter_queue.topic
207
- return false unless @_dispatch_to_dlq
208
-
209
- true
210
- end
211
-
212
- # @return [Boolean] should we use a transaction to move the data to the DLQ.
213
- # We can do it only when producer is transactional and configuration for DLQ
214
- # transactional dispatches is not set to false.
215
- def dispatch_in_a_transaction?
216
- producer.transactional? && topic.dead_letter_queue.transactional?
217
- end
218
-
219
- # @return [Boolean] should we mark given message as consumed after dispatch.
220
- # For default non MOM strategies if user did not explicitly tell us not to, we mark
221
- # it. Default is `nil`, which means `true` in this case. If user provided alternative
222
- # value, we go with it.
223
- def mark_after_dispatch?
224
- return true if topic.dead_letter_queue.mark_after_dispatch.nil?
225
-
226
- topic.dead_letter_queue.mark_after_dispatch
227
- end
228
-
229
- # Runs the DLQ strategy and based on it it performs certain operations
230
- #
231
- # In case of `:skip` and `:dispatch` will run the exact flow provided in a block
232
- # In case of `:retry` always `#retry_after_pause` is applied
233
- def apply_dlq_flow
234
- flow, target_topic = topic.dead_letter_queue.strategy.call(errors_tracker, attempt)
235
-
236
- case flow
237
- when :retry
238
- retry_after_pause
239
-
240
- return
241
- when :skip
242
- @_dispatch_to_dlq = false
243
- when :dispatch
244
- @_dispatch_to_dlq = true
245
- # Use custom topic if it was returned from the strategy
246
- @_dispatch_to_dlq_topic = target_topic || topic.dead_letter_queue.topic
247
- else
248
- raise Karafka::UnsupportedCaseError, flow
249
- end
250
-
251
- yield
252
-
253
- # We reset the pause to indicate we will now consider it as "ok".
254
- coordinator.pause_tracker.reset
255
-
256
- # Always backoff after DLQ dispatch even on skip to prevent overloads on errors
257
- pause(seek_offset, nil, false)
258
- ensure
259
- @_dispatch_to_dlq_topic = nil
260
- end
261
-
262
- # Marks message that went to DLQ (if applicable) based on the requested method
263
- # @param skippable_message [Karafka::Messages::Message]
264
- def mark_dispatched_to_dlq(skippable_message)
265
- case topic.dead_letter_queue.marking_method
266
- when :mark_as_consumed
267
- mark_as_consumed(skippable_message)
268
- when :mark_as_consumed!
269
- mark_as_consumed!(skippable_message)
270
- else
271
- # This should never happen. Bug if encountered. Please report
272
- raise Karafka::Errors::UnsupportedCaseError
273
- end
274
- end
275
- end
276
- end
277
- end
278
- end
279
- end
280
- end