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
@@ -71,7 +71,7 @@ module Karafka
71
71
  batch_size: consumer.messages.size,
72
72
  first_offset: consumer.messages.metadata.first_offset,
73
73
  last_offset: consumer.messages.metadata.last_offset,
74
- consumer_group: consumer.topic.consumer_group.id,
74
+ consumer_group: consumer.topic.group.id,
75
75
  topic: consumer.topic.name,
76
76
  partition: consumer.partition,
77
77
  attempt: consumer.coordinator.pause_tracker.attempt
@@ -166,20 +166,20 @@ module Karafka
166
166
  # @param event [Karafka::Core::Monitoring::Event]
167
167
  def on_statistics_emitted(event)
168
168
  statistics = event[:statistics]
169
- consumer_group_id = event[:consumer_group_id]
169
+ group_id = event[:group_id]
170
170
 
171
171
  rd_kafka_metrics.each do |metric|
172
- report_metric(metric, statistics, consumer_group_id)
172
+ report_metric(metric, statistics, group_id)
173
173
  end
174
174
 
175
- report_aggregated_topics_metrics(statistics, consumer_group_id)
175
+ report_aggregated_topics_metrics(statistics, group_id)
176
176
  end
177
177
 
178
178
  # Reports a given metric statistics to Appsignal
179
179
  # @param metric [RdKafkaMetric] metric value object
180
180
  # @param statistics [Hash] hash with all the statistics emitted
181
- # @param consumer_group_id [String] cg in context which we operate
182
- def report_metric(metric, statistics, consumer_group_id)
181
+ # @param group_id [String] group id in context which we operate
182
+ def report_metric(metric, statistics, group_id)
183
183
  case metric.scope
184
184
  when :root
185
185
  # Do nothing on the root metrics as the same metrics are reported in a granular
@@ -188,8 +188,7 @@ module Karafka
188
188
  when :brokers
189
189
  statistics.fetch("brokers").each_value do |broker_statistics|
190
190
  # Skip bootstrap nodes
191
- # Bootstrap nodes have nodeid -1, other nodes have positive
192
- # node ids
191
+ # Bootstrap nodes have nodeid -1, other nodes have positive node ids
193
192
  next if broker_statistics["nodeid"] == -1
194
193
 
195
194
  public_send(
@@ -218,7 +217,7 @@ module Karafka
218
217
  metric.name,
219
218
  partition_statistics.dig(*metric.key_location),
220
219
  {
221
- consumer_group: consumer_group_id,
220
+ consumer_group: group_id,
222
221
  topic: topic_name,
223
222
  partition: partition_name
224
223
  }
@@ -233,8 +232,8 @@ module Karafka
233
232
  # Publishes aggregated topic-level metrics that are sum of per partition metrics
234
233
  #
235
234
  # @param statistics [Hash] hash with all the statistics emitted
236
- # @param consumer_group_id [String] cg in context which we operate
237
- def report_aggregated_topics_metrics(statistics, consumer_group_id)
235
+ # @param group_id [String] group id in context which we operate
236
+ def report_aggregated_topics_metrics(statistics, group_id)
238
237
  config.aggregated_rd_kafka_metrics.each do |metric|
239
238
  statistics.fetch("topics").each do |topic_name, topic_values|
240
239
  sum = 0
@@ -253,7 +252,7 @@ module Karafka
253
252
  metric.name,
254
253
  sum,
255
254
  {
256
- consumer_group: consumer_group_id,
255
+ consumer_group: group_id,
257
256
  topic: topic_name
258
257
  }
259
258
  )
@@ -314,11 +313,11 @@ module Karafka
314
313
  # @param consumer [Karafka::BaseConsumer] Karafka consumer instance
315
314
  def with_multiple_resolutions(consumer)
316
315
  topic_name = consumer.topic.name
317
- consumer_group_id = consumer.topic.consumer_group.id
316
+ group_id = consumer.topic.group.id
318
317
  partition = consumer.partition
319
318
 
320
319
  tags = {
321
- consumer_group: consumer_group_id,
320
+ consumer_group: group_id,
322
321
  topic: topic_name
323
322
  }
324
323
 
@@ -328,10 +327,8 @@ module Karafka
328
327
 
329
328
  # Sends minute based probing metrics
330
329
  def minute_probe
331
- concurrency = Karafka::App.config.concurrency
332
-
333
330
  count("processes_count", 1, {})
334
- count("threads_count", concurrency, {})
331
+ count("threads_count", Karafka::Server.workers.size, {})
335
332
  end
336
333
  end
337
334
  end
@@ -80,9 +80,9 @@ module Karafka
80
80
  # @param event [Karafka::Core::Monitoring::Event]
81
81
  def on_statistics_emitted(event)
82
82
  statistics = event[:statistics]
83
- consumer_group_id = event[:consumer_group_id]
83
+ group_id = event[:group_id]
84
84
 
85
- tags = ["consumer_group:#{consumer_group_id}"]
85
+ tags = ["consumer_group:#{group_id}"]
86
86
  tags.concat(default_tags)
87
87
 
88
88
  rd_kafka_metrics.each do |metric|
@@ -111,9 +111,9 @@ module Karafka
111
111
  time_taken = event[:time]
112
112
  messages_count = event[:messages_buffer].size
113
113
 
114
- consumer_group_id = event[:subscription_group].consumer_group.id
114
+ group_id = event[:subscription_group].group.id
115
115
 
116
- tags = ["consumer_group:#{consumer_group_id}"]
116
+ tags = ["consumer_group:#{group_id}"]
117
117
  tags.concat(default_tags)
118
118
 
119
119
  histogram("listener.polling.time_taken", time_taken, tags: tags)
@@ -164,7 +164,7 @@ module Karafka
164
164
  jq_stats = event[:jobs_queue].statistics
165
165
 
166
166
  tags = default_tags
167
- gauge("worker.total_threads", Karafka::App.config.concurrency, tags: tags)
167
+ gauge("worker.total_threads", Karafka::Server.workers.size, tags: tags)
168
168
  histogram("worker.processing", jq_stats[:busy], tags: tags)
169
169
  histogram("worker.enqueued_jobs", jq_stats[:enqueued], tags: tags)
170
170
  end
@@ -241,8 +241,7 @@ module Karafka
241
241
  when :brokers
242
242
  statistics.fetch("brokers").each_value do |broker_statistics|
243
243
  # Skip bootstrap nodes
244
- # Bootstrap nodes have nodeid -1, other nodes have positive
245
- # node ids
244
+ # Bootstrap nodes have nodeid -1, other nodes have positive node ids
246
245
  next if broker_statistics["nodeid"] == -1
247
246
 
248
247
  tags = ["broker:#{broker_statistics["nodename"]}"]
@@ -290,12 +289,12 @@ module Karafka
290
289
  def consumer_tags(consumer)
291
290
  messages = consumer.messages
292
291
  metadata = messages.metadata
293
- consumer_group_id = consumer.topic.consumer_group.id
292
+ group_id = consumer.topic.group.id
294
293
 
295
294
  [
296
295
  "topic:#{metadata.topic}",
297
296
  "partition:#{metadata.partition}",
298
- "consumer_group:#{consumer_group_id}"
297
+ "consumer_group:#{group_id}"
299
298
  ]
300
299
  end
301
300
  end
@@ -39,11 +39,15 @@ module Karafka
39
39
 
40
40
  # Responds to a HTTP request with the process liveness status
41
41
  def respond
42
- body = JSON.generate(status_body)
43
-
44
42
  client = @server.accept
45
43
  client.gets
46
- client.print "HTTP/1.1 #{healthy? ? OK_CODE : FAIL_CODE}\r\n"
44
+ # Compute body after accepting so it reflects current health at request time.
45
+ # Derive the HTTP status code from the same snapshot to guarantee consistency -
46
+ # calling healthy? separately could observe a different state.
47
+ snapshot = status_body
48
+ body = JSON.generate(snapshot)
49
+ code = (snapshot[:status] == "healthy") ? OK_CODE : FAIL_CODE
50
+ client.print "HTTP/1.1 #{code}\r\n"
47
51
  client.print "Content-Type: application/json\r\n"
48
52
  client.print "Content-Length: #{body.bytesize}\r\n"
49
53
  client.print "\r\n"
@@ -158,36 +158,39 @@ module Karafka
158
158
  @mutex.synchronize(&)
159
159
  end
160
160
 
161
- # @return [Integer] object id of the current thread
162
- def thread_id
163
- Thread.current.object_id
161
+ # @return [Integer] object id of the current fiber
162
+ # @note We use fiber object id instead of thread object id to ensure fiber-safety.
163
+ # Multiple fibers can run on the same thread, and using thread id would cause them
164
+ # to overwrite each other's timestamps.
165
+ def fiber_id
166
+ Fiber.current.object_id
164
167
  end
165
168
 
166
- # Update the polling tick time for current thread
169
+ # Update the polling tick time for current fiber
167
170
  def mark_polling_tick
168
171
  synchronize do
169
- @pollings[thread_id] = monotonic_now
172
+ @pollings[fiber_id] = monotonic_now
170
173
  end
171
174
  end
172
175
 
173
- # Clear current thread polling time tracker
176
+ # Clear current fiber polling time tracker
174
177
  def clear_polling_tick
175
178
  synchronize do
176
- @pollings.delete(thread_id)
179
+ @pollings.delete(fiber_id)
177
180
  end
178
181
  end
179
182
 
180
183
  # Update the processing tick time
181
184
  def mark_consumption_tick
182
185
  synchronize do
183
- @consumptions[thread_id] = monotonic_now
186
+ @consumptions[fiber_id] = monotonic_now
184
187
  end
185
188
  end
186
189
 
187
- # Clear current thread consumption time tracker
190
+ # Clear current fiber consumption time tracker
188
191
  def clear_consumption_tick
189
192
  synchronize do
190
- @consumptions.delete(thread_id)
193
+ @consumptions.delete(fiber_id)
191
194
  end
192
195
  end
193
196
 
@@ -46,12 +46,25 @@ module Karafka
46
46
 
47
47
  # Check if License module and required methods are already defined
48
48
  # @return [Boolean]
49
+ # @raise [Errors::InvalidLicenseTokenError] when License module exists but is missing
50
+ # required methods (token or version)
49
51
  def license_fully_defined?
50
52
  return false unless const_defined?("::Karafka::License")
51
53
 
52
- # Check if the required methods exist
53
- ::Karafka::License.respond_to?(:token) &&
54
- ::Karafka::License.respond_to?(:version)
54
+ missing = []
55
+ missing << "#token" unless ::Karafka::License.respond_to?(:token)
56
+ missing << "#version" unless ::Karafka::License.respond_to?(:version)
57
+
58
+ return true if missing.empty?
59
+
60
+ raise(
61
+ Errors::InvalidLicenseTokenError,
62
+ <<~MSG.tr("\n", " ")
63
+ Karafka::License module is defined but missing required method(s): #{missing.join(", ")}.
64
+ When defining Karafka::License manually, both #token and #version must be implemented.
65
+ Please refer to https://karafka.io/docs/Pro-Enterprise-License-Setup/ for details.
66
+ MSG
67
+ )
55
68
  end
56
69
 
57
70
  # Attempt to safely load license without executing gem code
@@ -48,8 +48,7 @@ module Karafka
48
48
  break if revoked?
49
49
 
50
50
  # We cannot early stop when running virtual partitions because the intermediate state
51
- # would force us not to commit the offsets. This would cause extensive
52
- # double-processing
51
+ # would force us not to commit the offsets. This would cause extensive double-processing
53
52
  break if ::Karafka::App.stopping? && !topic.virtual_partitions?
54
53
 
55
54
  consume_job(message)
@@ -40,8 +40,7 @@ module Karafka
40
40
  deserializer: %i[internal active_job deserializer]
41
41
  )
42
42
 
43
- # Defaults for dispatching
44
- # They can be updated by using `#karafka_options` on the job
43
+ # Defaults for dispatching They can be updated by using `#karafka_options` on the job
45
44
  DEFAULTS = {
46
45
  dispatch_method: :produce_async,
47
46
  dispatch_many_method: :produce_many_async,
@@ -77,30 +77,30 @@ module Karafka
77
77
  private_constant :OFFSETS_TOPIC, :DEFAULT_LAST_COMMITTED_AT_OFFSET
78
78
 
79
79
  class << self
80
- # @param consumer_group_id [String] consumer group to read offsets for
80
+ # @param group_id [String] consumer group to read offsets for
81
81
  # @param last_committed_at [Time] approximate time of last successful offset commit
82
82
  # (default: 1 hour ago). A good rule of thumb is the crash time minus 10 minutes
83
83
  # @return [Hash{String => Hash{Integer => Integer}}]
84
84
  # @see #read_committed_offsets
85
85
  def read_committed_offsets(
86
- consumer_group_id,
86
+ group_id,
87
87
  last_committed_at: Time.now - DEFAULT_LAST_COMMITTED_AT_OFFSET
88
88
  )
89
- new.read_committed_offsets(consumer_group_id, last_committed_at: last_committed_at)
89
+ new.read_committed_offsets(group_id, last_committed_at: last_committed_at)
90
90
  end
91
91
 
92
- # @param consumer_group_id [String] consumer group id
92
+ # @param group_id [String] consumer group id
93
93
  # @return [Integer] __consumer_offsets partition number
94
94
  # @see #offsets_partition_for
95
- def offsets_partition_for(consumer_group_id)
96
- new.offsets_partition_for(consumer_group_id)
95
+ def offsets_partition_for(group_id)
96
+ new.offsets_partition_for(group_id)
97
97
  end
98
98
 
99
- # @param consumer_group_id [String] consumer group to look up
99
+ # @param group_id [String] consumer group to look up
100
100
  # @return [Hash] coordinator broker info
101
101
  # @see #coordinator_for
102
- def coordinator_for(consumer_group_id)
103
- new.coordinator_for(consumer_group_id)
102
+ def coordinator_for(group_id)
103
+ new.coordinator_for(group_id)
104
104
  end
105
105
 
106
106
  # @param partition [Integer] __consumer_offsets partition to scan
@@ -143,7 +143,7 @@ module Karafka
143
143
  # caller's responsibility to verify that all expected topic-partitions are present before
144
144
  # using the result for migration or other operations.
145
145
  #
146
- # @param consumer_group_id [String] consumer group to read offsets for
146
+ # @param group_id [String] consumer group to read offsets for
147
147
  # @param last_committed_at [Time] approximate time of last successful offset commit
148
148
  # (default: 1 hour ago). A good rule of thumb is the crash time minus 10 minutes
149
149
  # @return [Hash{String => Hash{Integer => Integer}}]
@@ -174,11 +174,11 @@ module Karafka
174
174
  #
175
175
  # # Now reconfigure your consumers to use 'sync_v2' and restart them
176
176
  def read_committed_offsets(
177
- consumer_group_id,
177
+ group_id,
178
178
  last_committed_at: Time.now - DEFAULT_LAST_COMMITTED_AT_OFFSET
179
179
  )
180
180
  committed = Hash.new { |h, k| h[k] = {} }
181
- target_partition = offsets_partition_for(consumer_group_id)
181
+ target_partition = offsets_partition_for(group_id)
182
182
 
183
183
  iterator = Pro::Iterator.new(
184
184
  { OFFSETS_TOPIC => { target_partition => last_committed_at } },
@@ -190,7 +190,7 @@ module Karafka
190
190
 
191
191
  parsed = parse_offset_commit(message)
192
192
  next unless parsed
193
- next unless parsed[:group] == consumer_group_id
193
+ next unless parsed[:group] == group_id
194
194
 
195
195
  if parsed[:offset].nil?
196
196
  # Tombstone — offset was deleted, remove from results
@@ -211,14 +211,14 @@ module Karafka
211
211
  # hash: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1], computed with int32 overflow
212
212
  # semantics. Utils.abs maps Integer.MIN_VALUE to 0.
213
213
  #
214
- # @param consumer_group_id [String] consumer group id
214
+ # @param group_id [String] consumer group id
215
215
  # @return [Integer] __consumer_offsets partition number
216
216
  #
217
217
  # @example Check which partition stores offsets for a group
218
218
  # Karafka::Admin::Recovery.offsets_partition_for('my-group')
219
219
  # #=> 17
220
- def offsets_partition_for(consumer_group_id)
221
- h = java_hash_code(consumer_group_id)
220
+ def offsets_partition_for(group_id)
221
+ h = java_hash_code(group_id)
222
222
  # Kafka's Utils.abs: Integer.MIN_VALUE maps to 0
223
223
  h = (h == -2_147_483_648) ? 0 : h.abs
224
224
  h % offsets_partition_count
@@ -233,7 +233,7 @@ module Karafka
233
233
  # returned broker is the one that is down or in a FAILED state, the group is stuck and
234
234
  # needs migration.
235
235
  #
236
- # @param consumer_group_id [String] consumer group to look up
236
+ # @param group_id [String] consumer group to look up
237
237
  # @return [Hash{Symbol => Object}] coordinator info with :partition, :broker_id,
238
238
  # and :broker_host keys
239
239
  #
@@ -246,8 +246,8 @@ module Karafka
246
246
  # if info[:broker_id] == failed_broker_id
247
247
  # puts "Group 'my-group' is stuck on failed broker #{info[:broker_host]}"
248
248
  # end
249
- def coordinator_for(consumer_group_id)
250
- target_partition = offsets_partition_for(consumer_group_id)
249
+ def coordinator_for(group_id)
250
+ target_partition = offsets_partition_for(group_id)
251
251
  metadata = cluster_info
252
252
 
253
253
  offsets_topic = metadata.topics.find { |t| t[:topic_name] == OFFSETS_TOPIC }
@@ -37,7 +37,7 @@ module Karafka
37
37
  #
38
38
  # Methods here are suppose to be always available or are expected to be redefined
39
39
  module BaseConsumer
40
- # @return [Karafka::Pro::Processing::Coordinators::ErrorsTracker] tracker for errors that
40
+ # @return [Karafka::Pro::Processing::ConsumerGroups::Coordinators::ErrorsTracker] tracker for errors that
41
41
  # occurred during processing until another successful processing
42
42
  #
43
43
  # @note This will always contain **only** details of errors that occurred during `#consume`
@@ -53,7 +53,7 @@ module Karafka
53
53
  coordinator.errors_tracker
54
54
  end
55
55
 
56
- # @return [Karafka::Pro::Processing::SubscriptionGroupsCoordinator] Coordinator allowing to
56
+ # @return [Karafka::Pro::Processing::ConsumerGroups::SubscriptionGroupsCoordinator] Coordinator allowing to
57
57
  # pause and resume polling of the given subscription group jobs queue for postponing
58
58
  # further work.
59
59
  #
@@ -62,7 +62,7 @@ module Karafka
62
62
  # @note This is a low-level API used for cross-topic coordination and some advanced features.
63
63
  # Use it at own risk.
64
64
  def subscription_groups_coordinator
65
- Processing::SubscriptionGroupsCoordinator.instance
65
+ Processing::ConsumerGroups::SubscriptionGroupsCoordinator.instance
66
66
  end
67
67
  end
68
68
  end
@@ -46,7 +46,7 @@ module Karafka
46
46
  include
47
47
  exclude
48
48
  ].each do |action|
49
- optional(:"#{action}_consumer_groups") { |cg| cg.is_a?(Array) }
49
+ optional(:"#{action}_consumer_groups") { |val| val.is_a?(Array) }
50
50
  optional(:"#{action}_subscription_groups") { |sg| sg.is_a?(Array) }
51
51
  optional(:"#{action}_topics") { |topics| topics.is_a?(Array) }
52
52
 
@@ -58,7 +58,7 @@ module Karafka
58
58
  # If there were no consumer_groups declared in the server cli, it means that we will
59
59
  # run all of them and no need to validate them here at all
60
60
  next if value.empty?
61
- next if (value - Karafka::App.consumer_groups.map(&:name)).empty?
61
+ next if (value - Karafka::App.routes.map(&:name)).empty?
62
62
 
63
63
  # Found unknown consumer groups
64
64
  [[[:"#{action}_consumer_groups"], :consumer_groups_inclusion]]
@@ -74,7 +74,7 @@ module Karafka
74
74
  next if value.empty?
75
75
 
76
76
  subscription_groups = Karafka::App
77
- .consumer_groups
77
+ .routes
78
78
  .map(&:subscription_groups)
79
79
  .flatten
80
80
  .map(&:name)
@@ -95,7 +95,7 @@ module Karafka
95
95
  next if value.empty?
96
96
 
97
97
  topics = Karafka::App
98
- .consumer_groups
98
+ .routes
99
99
  .map(&:subscription_groups)
100
100
  .flatten
101
101
  .map(&:topics)
@@ -107,7 +107,7 @@ module Karafka
107
107
  # If there are any patterns defined, we cannot report on topics inclusions because
108
108
  # topics may be added during boot or runtime. We go with simple assumption:
109
109
  # if there are patterns defined, we do not check the inclusions at all
110
- next unless Karafka::App.consumer_groups.map(&:patterns).flatten.empty?
110
+ next unless Karafka::App.routes.map(&:patterns).flatten.empty?
111
111
 
112
112
  # Found unknown topics
113
113
  [[[:"#{action}_topics"], :topics_inclusion]]
@@ -82,24 +82,24 @@ module Karafka
82
82
  end
83
83
 
84
84
  # Collects the offsets for the segment origin consumer group and the parallel segments
85
- # consumers groups. We use segment origin cg offsets as a baseline for the distribution
86
- # and use existing (if any) parallel segments cgs offsets for validations.
85
+ # consumers groups. We use segment origin group offsets as a baseline for the
86
+ # distribution and use existing (if any) parallel segments groups offsets for validations.
87
87
  #
88
88
  # @param segment_origin [String] name of the origin consumer group
89
89
  # @param segments [Array<Karafka::Routing::ConsumerGroup>]
90
- # @return [Hash] fetched offsets for all the cg topics for all the consumer groups
90
+ # @return [Hash] fetched offsets for all the group topics for all the groups
91
91
  def collect_offsets(segment_origin, segments)
92
92
  topics_names = segments.first.topics.map(&:name)
93
- consumer_groups = [segment_origin, segments.map(&:name)].flatten
93
+ groups = [segment_origin, segments.map(&:name)].flatten
94
94
 
95
- consumer_groups_with_topics = consumer_groups
95
+ groups_with_topics = groups
96
96
  .to_h { |name| [name, topics_names] }
97
97
 
98
98
  lags_with_offsets = Karafka::Admin.read_lags_with_offsets(
99
- consumer_groups_with_topics
99
+ groups_with_topics
100
100
  )
101
101
 
102
- lags_with_offsets.each do |_cg_name, topics|
102
+ lags_with_offsets.each do |_group_name, topics|
103
103
  topics.each do |_topic_name, partitions|
104
104
  partitions.transform_values! { |details| details[:offset] }
105
105
  end
@@ -97,8 +97,8 @@ module Karafka
97
97
  collapse = Hash.new { |h, k| h[k] = {} }
98
98
  segments_names = segments.map(&:name)
99
99
 
100
- offsets.each do |cg_name, topics|
101
- next unless segments_names.include?(cg_name)
100
+ offsets.each do |group_name, topics|
101
+ next unless segments_names.include?(group_name)
102
102
 
103
103
  topics.each do |topic_name, partitions|
104
104
  partitions.each do |partition_id, offset|
@@ -128,8 +128,8 @@ module Karafka
128
128
  def validate!(offsets, segment_origin)
129
129
  collapse = Hash.new { |h, k| h[k] = {} }
130
130
 
131
- offsets.each do |cg_name, topics|
132
- next if cg_name == segment_origin
131
+ offsets.each do |group_name, topics|
132
+ next if group_name == segment_origin
133
133
 
134
134
  topics.each do |topic_name, partitions|
135
135
  partitions.each do |partition_id, offset|
@@ -101,15 +101,15 @@ module Karafka
101
101
  # It prevents users from overwriting the already set segments distribution.
102
102
  # Adding new topics to the same parallel segments consumer group does not require us to
103
103
  # run this at all and on top of that users can always use `--consumer_groups` flag to
104
- # limit the cgs that we will be operating here
104
+ # limit the groups that we will be operating here
105
105
  #
106
106
  # @param offsets [Hash]
107
107
  # @param segments [Array<Karafka::Routing::ConsumerGroup>]
108
108
  def validate!(offsets, segments)
109
109
  segments_names = segments.map(&:name)
110
110
 
111
- offsets.each do |cg_name, topics|
112
- next unless segments_names.include?(cg_name)
111
+ offsets.each do |group_name, topics|
112
+ next unless segments_names.include?(group_name)
113
113
 
114
114
  topics.each do |topic_name, partitions|
115
115
  partitions.each do |partition_id, offset|
@@ -117,7 +117,7 @@ module Karafka
117
117
 
118
118
  raise(
119
119
  Karafka::Errors::CommandValidationError,
120
- "Parallel segment #{red(cg_name)} already has offset #{red(offset)} " \
120
+ "Parallel segment #{red(group_name)} already has offset #{red(offset)} " \
121
121
  "set for #{red("#{topic_name}##{partition_id}")}"
122
122
  )
123
123
  end
@@ -136,8 +136,8 @@ module Karafka
136
136
  distributions = []
137
137
  segments_names = segments.map(&:name)
138
138
 
139
- offsets.each do |cg_name, topics|
140
- next if segments_names.include?(cg_name)
139
+ offsets.each do |group_name, topics|
140
+ next if segments_names.include?(group_name)
141
141
 
142
142
  distribution = {}
143
143
 
@@ -94,8 +94,7 @@ module Karafka
94
94
  # Skip negative and time based offsets
95
95
  next unless offset.is_a?(Integer) && offset >= 0
96
96
 
97
- # Exact offsets can be used as they are
98
- # No need for extra operations
97
+ # Exact offsets can be used as they are No need for extra operations
99
98
  @mapped_topics[name][partition] = offset
100
99
  end
101
100
  end
@@ -108,31 +107,52 @@ module Karafka
108
107
  # heavily compacted topics, this may return less than the desired number but it is a
109
108
  # limitation that is documented.
110
109
  def resolve_partitions_with_negative_offsets
110
+ # Collect all integer-offset partitions (positive and negative) and the subset
111
+ # that actually need LWM/HWM resolution
112
+ warm_up_partitions = {}
113
+ negative_partitions = {}
114
+
111
115
  @expanded_topics.each do |name, partitions|
112
116
  next unless partitions.is_a?(Hash)
113
117
 
114
118
  partitions.each do |partition, offset|
115
- # Care only about numerical offsets
116
- #
117
- # For time based we already resolve them via librdkafka lookup API
118
119
  next unless offset.is_a?(Integer)
119
120
 
120
- low_offset, high_offset = @consumer.query_watermark_offsets(name, partition)
121
+ (warm_up_partitions[name] ||= []) << partition
122
+ (negative_partitions[name] ||= {})[partition] = offset if offset.negative?
123
+ end
124
+ end
121
125
 
122
- # Care only about negative offsets (last n messages)
123
- #
124
- # We reject the above results but we **NEED** to run the `#query_watermark_offsets`
125
- # for each topic partition nonetheless. Without this, librdkafka fetches a lot more
126
- # metadata about each topic and each partition and this takes much more time than
127
- # just getting watermarks. If we do not run watermark, at least an extra second
128
- # is added at the beginning of iterator flow
129
- #
130
- # This may not be significant when this runs in the background but in case of
131
- # using iterator in thins like Puma, it heavily impacts the end user experience
132
- next unless offset.negative?
126
+ return if warm_up_partitions.empty?
127
+
128
+ # A single batched offsets_for_times call on the consumer handle warms up
129
+ # librdkafka's per-partition metadata cache for all integer-offset partitions in
130
+ # one roundtrip. Without this pre-fetch, librdkafka triggers a much broader
131
+ # metadata refresh when assign is called later, adding at least a second to
132
+ # iterator startup noticeable in latency-sensitive contexts like Puma.
133
+ # The epoch timestamp ensures every partition returns its LWM; the result is
134
+ # intentionally discarded since we only need the warm-up side effect here.
135
+ warm_up_tpl = Rdkafka::Consumer::TopicPartitionList.new
136
+ warm_up_partitions.each do |name, part_ids|
137
+ warm_up_tpl.add_topic_and_partitions_with_offsets(
138
+ name, part_ids.to_h { |p| [p, Time.at(0)] }
139
+ )
140
+ end
141
+ @consumer.offsets_for_times(warm_up_tpl)
133
142
 
143
+ return if negative_partitions.empty?
144
+
145
+ # Batch-fetch LWM and HWM for all negative-offset partitions in two admin calls
146
+ # (one for :earliest, one for :latest) instead of N per-partition consumer calls
147
+ watermarks = Karafka::Admin::Topics.read_watermark_offsets(
148
+ negative_partitions.transform_values(&:keys)
149
+ )
150
+
151
+ negative_partitions.each do |name, partitions|
152
+ partitions.each do |partition, offset|
134
153
  # We add because this offset is negative
135
- @mapped_topics[name][partition] = [high_offset + offset, low_offset].max
154
+ low, high = watermarks.dig(name, partition) || [0, 0]
155
+ @mapped_topics[name][partition] = [high + offset, low].max
136
156
  end
137
157
  end
138
158
  end