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
@@ -18,65 +18,64 @@ module Karafka
18
18
  private_constant :LONG_TIME_AGO, :DAY_IN_SECONDS
19
19
 
20
20
  class << self
21
- # @param consumer_group_id [String] consumer group for which we want to move offsets
21
+ # @param group_id [String] group for which we want to move offsets
22
22
  # @param topics_with_partitions_and_offsets [Hash] hash with topics and settings
23
23
  # @see #seek
24
- def seek(consumer_group_id, topics_with_partitions_and_offsets)
25
- new.seek(consumer_group_id, topics_with_partitions_and_offsets)
24
+ def seek(group_id, topics_with_partitions_and_offsets)
25
+ new.seek(group_id, topics_with_partitions_and_offsets)
26
26
  end
27
27
 
28
- # @param previous_name [String] old consumer group name
29
- # @param new_name [String] new consumer group name
28
+ # @param previous_name [String] old group name
29
+ # @param new_name [String] new group name
30
30
  # @param topics [Array<String>] topics for which we want to copy offsets
31
31
  # @see #copy
32
32
  def copy(previous_name, new_name, topics)
33
33
  new.copy(previous_name, new_name, topics)
34
34
  end
35
35
 
36
- # @param previous_name [String] old consumer group name
37
- # @param new_name [String] new consumer group name
36
+ # @param previous_name [String] old group name
37
+ # @param new_name [String] new group name
38
38
  # @param topics [Array<String>] topics for which we want to migrate offsets
39
- # @param delete_previous [Boolean] should we delete previous consumer group after rename
39
+ # @param delete_previous [Boolean] should we delete previous group after rename
40
40
  # @see #rename
41
41
  def rename(previous_name, new_name, topics, delete_previous: true)
42
42
  new.rename(previous_name, new_name, topics, delete_previous: delete_previous)
43
43
  end
44
44
 
45
- # @param consumer_group_id [String] consumer group name
45
+ # @param group_id [String] group name
46
46
  # @see #delete
47
- def delete(consumer_group_id)
48
- new.delete(consumer_group_id)
47
+ def delete(group_id)
48
+ new.delete(group_id)
49
49
  end
50
50
 
51
- # @param consumer_group_id [String] consumer group id to trigger rebalance for
51
+ # @param group_id [String] group id to trigger rebalance for
52
52
  # @see #trigger_rebalance
53
- def trigger_rebalance(consumer_group_id)
54
- new.trigger_rebalance(consumer_group_id)
53
+ def trigger_rebalance(group_id)
54
+ new.trigger_rebalance(group_id)
55
55
  end
56
56
 
57
- # @param consumer_groups_with_topics [Hash{String => Array<String>}] hash with consumer
58
- # groups names with array of topics
57
+ # @param groups_with_topics [Hash{String => Array<String>}] hash with group names with
58
+ # array of topics
59
59
  # @param active_topics_only [Boolean] if set to false, will select also inactive topics
60
60
  # @see #read_lags_with_offsets
61
- def read_lags_with_offsets(consumer_groups_with_topics = {}, active_topics_only: true)
61
+ def read_lags_with_offsets(groups_with_topics = {}, active_topics_only: true)
62
62
  new.read_lags_with_offsets(
63
- consumer_groups_with_topics,
63
+ groups_with_topics,
64
64
  active_topics_only: active_topics_only
65
65
  )
66
66
  end
67
67
  end
68
68
 
69
- # Moves the offset on a given consumer group and provided topic to the requested location
69
+ # Moves the offset on a given group and provided topic to the requested location
70
70
  #
71
- # @param consumer_group_id [String] id of the consumer group for which we want to move the
72
- # existing offset
71
+ # @param group_id [String] id of the group for which we want to move the existing offset
73
72
  # @param topics_with_partitions_and_offsets [Hash] Hash with list of topics and settings to
74
73
  # where to move given consumer. It allows us to move particular partitions or whole
75
74
  # topics if we want to reset all partitions to for example a point in time.
76
75
  #
77
76
  # @return [void]
78
77
  #
79
- # @note This method should **not** be executed on a running consumer group as it creates a
78
+ # @note This method should **not** be executed on a running group as it creates a
80
79
  # "fake" consumer and uses it to move offsets.
81
80
  #
82
81
  # @example Move a single topic partition nr 1 offset to 100
@@ -99,7 +98,7 @@ module Karafka
99
98
  #
100
99
  # @example Move offset of a single partition to latest
101
100
  # Karafka::Admin::ConsumerGroups.seek('group-id', { 'topic' => { 1 => 'latest' } })
102
- def seek(consumer_group_id, topics_with_partitions_and_offsets)
101
+ def seek(group_id, topics_with_partitions_and_offsets)
103
102
  tpl_base = {}
104
103
 
105
104
  # Normalize the data so we always have all partitions and topics in the same format
@@ -161,28 +160,41 @@ module Karafka
161
160
  end
162
161
  end
163
162
 
164
- settings = { "group.id": consumer_group_id }
163
+ settings = { "group.id": group_id }
165
164
 
166
165
  with_consumer(settings) do |consumer|
167
166
  # If we have any time based stuff to resolve, we need to do it prior to commits
168
167
  unless time_tpl.empty?
169
168
  real_offsets = consumer.offsets_for_times(time_tpl)
170
169
 
171
- real_offsets.to_h.each do |name, results|
170
+ # Collect all partitions where the timestamp is beyond the last message
171
+ # (negative offset returned) so we can fetch their HWMs in a single batch
172
+ # admin call instead of one per-partition consumer call
173
+ real_offsets_by_topic = real_offsets.to_h
174
+ hwm_specs = {}
175
+ real_offsets_by_topic.each do |name, results|
172
176
  results.each do |result|
173
177
  raise(Errors::InvalidTimeBasedOffsetError) unless result
178
+ next unless result.offset.negative?
174
179
 
175
- partition = result.partition
180
+ (hwm_specs[name] ||= []) << { partition: result.partition, offset: :latest }
181
+ end
182
+ end
176
183
 
177
- # Negative offset means we're beyond last message and we need to query for the
178
- # high watermark offset to get the most recent offset and move there
179
- if result.offset.negative?
180
- _, offset = consumer.query_watermark_offsets(name, result.partition)
181
- else
182
- # If we get an offset, it means there existed a message close to this time
183
- # location
184
- offset = result.offset
184
+ hwms = {}
185
+ unless hwm_specs.empty?
186
+ with_admin do |admin|
187
+ admin.list_offsets(hwm_specs).wait(max_wait_timeout_ms: max_wait_time_ms).offsets.each do |r|
188
+ (hwms[r[:topic]] ||= {})[r[:partition]] = r[:offset]
185
189
  end
190
+ end
191
+ end
192
+
193
+ real_offsets_by_topic.each do |name, results|
194
+ results.each do |result|
195
+ partition = result.partition
196
+ # If offset is negative the timestamp was beyond the last message; use HWM
197
+ offset = result.offset.negative? ? hwms.dig(name, partition) : result.offset
186
198
 
187
199
  # Since now we have proper offsets, we can add this to the final tpl for commit
188
200
  tpl.to_h[name] ||= []
@@ -198,18 +210,18 @@ module Karafka
198
210
  end
199
211
  end
200
212
 
201
- # Takes consumer group and its topics and copies all the offsets to a new named group
213
+ # Takes group and its topics and copies all the offsets to a new named group
202
214
  #
203
- # @param previous_name [String] old consumer group name
204
- # @param new_name [String] new consumer group name
215
+ # @param previous_name [String] old group name
216
+ # @param new_name [String] new group name
205
217
  # @param topics [Array<String>] topics for which we want to migrate offsets during rename
206
218
  #
207
219
  # @return [Boolean] true if anything was migrated, otherwise false
208
220
  #
209
- # @note This method should **not** be executed on a running consumer group as it creates a
221
+ # @note This method should **not** be executed on a running group as it creates a
210
222
  # "fake" consumer and uses it to move offsets.
211
223
  #
212
- # @note If new consumer group exists, old offsets will be added to it.
224
+ # @note If new group exists, old offsets will be added to it.
213
225
  def copy(previous_name, new_name, topics)
214
226
  remap = Hash.new { |h, k| h[k] = {} }
215
227
 
@@ -236,24 +248,24 @@ module Karafka
236
248
  true
237
249
  end
238
250
 
239
- # Takes consumer group and its topics and migrates all the offsets to a new named group
251
+ # Takes group and its topics and migrates all the offsets to a new named group
240
252
  #
241
- # @param previous_name [String] old consumer group name
242
- # @param new_name [String] new consumer group name
253
+ # @param previous_name [String] old group name
254
+ # @param new_name [String] new group name
243
255
  # @param topics [Array<String>] topics for which we want to migrate offsets during rename
244
- # @param delete_previous [Boolean] should we delete previous consumer group after rename.
256
+ # @param delete_previous [Boolean] should we delete previous group after rename.
245
257
  # Defaults to true.
246
258
  #
247
259
  # @return [Boolean] true if rename (and optionally removal) was ok or false if there was
248
260
  # nothing really to rename
249
261
  #
250
- # @note This method should **not** be executed on a running consumer group as it creates a
262
+ # @note This method should **not** be executed on a running group as it creates a
251
263
  # "fake" consumer and uses it to move offsets.
252
264
  #
253
265
  # @note After migration unless `delete_previous` is set to `false`, old group will be
254
266
  # removed.
255
267
  #
256
- # @note If new consumer group exists, old offsets will be added to it.
268
+ # @note If new group exists, old offsets will be added to it.
257
269
  def rename(previous_name, new_name, topics, delete_previous: true)
258
270
  copy_result = copy(previous_name, new_name, topics)
259
271
 
@@ -265,35 +277,35 @@ module Karafka
265
277
  true
266
278
  end
267
279
 
268
- # Removes given consumer group (if exists)
280
+ # Removes given group (if exists)
269
281
  #
270
- # @param consumer_group_id [String] consumer group name
282
+ # @param group_id [String] group name
271
283
  #
272
284
  # @return [void]
273
285
  #
274
- # @note This method should not be used on a running consumer group as it will not yield any
286
+ # @note This method should not be used on a running group as it will not yield any
275
287
  # results.
276
- def delete(consumer_group_id)
288
+ def delete(group_id)
277
289
  with_admin do |admin|
278
- handler = admin.delete_group(consumer_group_id)
290
+ handler = admin.delete_group(group_id)
279
291
  handler.wait(max_wait_timeout_ms: max_wait_time_ms)
280
292
  end
281
293
  end
282
294
 
283
- # Triggers a rebalance for the specified consumer group by briefly joining and leaving
295
+ # Triggers a rebalance for the specified group by briefly joining and leaving
284
296
  #
285
- # @param consumer_group_id [String] consumer group id to trigger rebalance for
297
+ # @param group_id [String] group id to trigger rebalance for
286
298
  #
287
299
  # @return [void]
288
300
  #
289
- # @raise [Karafka::Errors::InvalidConfigurationError] when consumer group is not found in
301
+ # @raise [Karafka::Errors::InvalidConfigurationError] when group is not found in
290
302
  # routing or has no topics
291
303
  #
292
- # @note This method creates a temporary "fake" consumer that joins the consumer group,
304
+ # @note This method creates a temporary "fake" consumer that joins the group,
293
305
  # triggering a rebalance when it joins and another when it leaves. This should only be
294
306
  # used for operational/testing purposes as it causes two rebalances.
295
307
  #
296
- # @note The consumer group does not need to be running for this to work, but if it is,
308
+ # @note The group does not need to be running for this to work, but if it is,
297
309
  # it will experience rebalances.
298
310
  #
299
311
  # @note The behavior follows the configured rebalance protocol. For cooperative sticky
@@ -302,38 +314,38 @@ module Karafka
302
314
  # stopping all consumers.
303
315
  #
304
316
  # @note Topics are always detected from the routing configuration. The consumer settings
305
- # (kafka config) are taken from the first topic in the consumer group to ensure
317
+ # (kafka config) are taken from the first topic in the group to ensure
306
318
  # consistency with the actual consumer configuration.
307
319
  #
308
- # @example Trigger rebalance for a consumer group
320
+ # @example Trigger rebalance for a group
309
321
  # Karafka::Admin::ConsumerGroups.trigger_rebalance('my-group')
310
- def trigger_rebalance(consumer_group_id)
311
- consumer_group = Karafka::App.routes.find { |cg| cg.id == consumer_group_id }
322
+ def trigger_rebalance(group_id)
323
+ group = Karafka::App.routes.find { |g| g.id == group_id }
312
324
 
313
- unless consumer_group
325
+ unless group
314
326
  raise(
315
327
  Errors::InvalidConfigurationError,
316
- "Consumer group '#{consumer_group_id}' not found in routing"
328
+ "Group '#{group_id}' not found in routing"
317
329
  )
318
330
  end
319
331
 
320
- topics = consumer_group.topics.map(&:name)
332
+ topics = group.topics.map(&:name)
321
333
 
322
334
  if topics.empty?
323
335
  raise(
324
336
  Errors::InvalidConfigurationError,
325
- "Consumer group '#{consumer_group_id}' has no topics"
337
+ "Group '#{group_id}' has no topics"
326
338
  )
327
339
  end
328
340
 
329
341
  # Get the first topic to extract kafka settings
330
- first_topic = consumer_group.topics.first
342
+ first_topic = group.topics.first
331
343
 
332
- # Build consumer settings using the consumer group's kafka config from first topic
344
+ # Build consumer settings using the group's kafka config from first topic
333
345
  # This ensures we use the same settings as the actual consumers
334
346
  # Following the same pattern as in Karafka::Connection::Client#build_kafka
335
347
  consumer_settings = Setup::AttributesMap.consumer(first_topic.kafka.dup)
336
- consumer_settings[:"group.id"] = consumer_group.id
348
+ consumer_settings[:"group.id"] = group.id
337
349
  consumer_settings[:"enable.auto.offset.store"] = false
338
350
  consumer_settings[:"auto.offset.reset"] ||= first_topic.initial_offset
339
351
 
@@ -350,26 +362,25 @@ module Karafka
350
362
  end
351
363
  end
352
364
 
353
- # Reads lags and offsets for given topics in the context of consumer groups defined in the
354
- # routing
365
+ # Reads lags and offsets for given topics in the context of groups defined in the routing
355
366
  #
356
- # @param consumer_groups_with_topics [Hash{String => Array<String>}] hash with consumer
357
- # groups names with array of topics to query per consumer group inside
367
+ # @param groups_with_topics [Hash{String => Array<String>}] hash with group names with
368
+ # array of topics to query per group inside
358
369
  # @param active_topics_only [Boolean] if set to false, when we use routing topics, will
359
370
  # select also topics that are marked as inactive in routing
360
371
  #
361
372
  # @return [Hash{String => Hash{Integer => Hash{Integer => Object}}}] hash where the top
362
- # level keys are the consumer groups and values are hashes with topics and inside
373
+ # level keys are the groups and values are hashes with topics and inside
363
374
  # partitions with lags and offsets
364
375
  #
365
376
  # @note For topics that do not exist, topic details will be set to an empty hash
366
377
  #
367
- # @note For topics that exist but were never consumed by a given CG we set `-1` as lag and
368
- # the offset on each of the partitions that were not consumed.
378
+ # @note For topics that exist but were never consumed by a given group we set `-1` as lag
379
+ # and the offset on each of the partitions that were not consumed.
369
380
  #
370
381
  # @note This lag reporting is for committed lags and is "Kafka-centric", meaning that this
371
382
  # represents lags from Kafka perspective and not the consumer. They may differ.
372
- def read_lags_with_offsets(consumer_groups_with_topics = {}, active_topics_only: true)
383
+ def read_lags_with_offsets(groups_with_topics = {}, active_topics_only: true)
373
384
  # We first fetch all the topics with partitions count that exist in the cluster so we
374
385
  # do not query for topics that do not exist and so we can get partitions count for all
375
386
  # the topics we may need. The non-existent and not consumed will be filled at the end
@@ -377,82 +388,82 @@ module Karafka
377
388
  [topic[:topic_name], topic[:partition_count]]
378
389
  end.freeze
379
390
 
380
- # If no expected CGs, we use all from routing that have active topics
381
- if consumer_groups_with_topics.empty?
382
- consumer_groups_with_topics = Karafka::App.routes.to_h do |cg|
383
- cg_topics = cg.topics.select do |cg_topic|
384
- active_topics_only ? cg_topic.active? : true
391
+ # If no expected groups, we use all from routing that have active topics
392
+ if groups_with_topics.empty?
393
+ groups_with_topics = Karafka::App.routes.to_h do |group|
394
+ group_topics = group.topics.select do |group_topic|
395
+ active_topics_only ? group_topic.active? : true
385
396
  end
386
397
 
387
- [cg.id, cg_topics.map(&:name)]
398
+ [group.id, group_topics.map(&:name)]
388
399
  end
389
400
  end
390
401
 
391
402
  # We make a copy because we will remove once with non-existing topics
392
- # We keep original requested consumer groups with topics for later backfilling
393
- cgs_with_topics = consumer_groups_with_topics.dup
394
- cgs_with_topics.transform_values!(&:dup)
403
+ # We keep original requested groups with topics for later backfilling
404
+ queryable_groups = groups_with_topics.dup
405
+ queryable_groups.transform_values!(&:dup)
395
406
 
396
407
  # We can query only topics that do exist, this is why we are cleaning those that do not
397
408
  # exist
398
- cgs_with_topics.each_value do |requested_topics|
409
+ queryable_groups.each_value do |requested_topics|
399
410
  requested_topics.delete_if { |topic| !existing_topics.include?(topic) }
400
411
  end
401
412
 
402
413
  groups_lags = Hash.new { |h, k| h[k] = {} }
403
414
  groups_offs = Hash.new { |h, k| h[k] = {} }
404
415
 
405
- cgs_with_topics.each do |cg, topics|
416
+ queryable_groups.each do |group, topics|
406
417
  # Do not add to tpl topics that do not exist
407
418
  next if topics.empty?
408
419
 
409
420
  tpl = Rdkafka::Consumer::TopicPartitionList.new
410
421
 
411
- with_consumer("group.id": cg) do |consumer|
422
+ with_consumer("group.id": group) do |consumer|
412
423
  topics.each { |topic| tpl.add_topic(topic, existing_topics[topic]) }
413
424
 
414
425
  commit_offsets = consumer.committed(tpl)
415
426
 
416
427
  commit_offsets.to_h.each do |topic, partitions|
417
- groups_offs[cg][topic] = {}
428
+ groups_offs[group][topic] = {}
418
429
 
419
430
  partitions.each do |partition|
420
431
  # -1 when no offset is stored
421
- groups_offs[cg][topic][partition.partition] = partition.offset || -1
432
+ groups_offs[group][topic][partition.partition] = partition.offset || -1
422
433
  end
423
434
  end
424
435
 
425
436
  consumer.lag(commit_offsets).each do |topic, partitions_lags|
426
- groups_lags[cg][topic] = partitions_lags
437
+ groups_lags[group][topic] = partitions_lags
427
438
  end
428
439
  end
429
440
  end
430
441
 
431
- consumer_groups_with_topics.each do |cg, topics|
432
- groups_lags[cg]
442
+ groups_with_topics.each do |group, topics|
443
+ groups_lags[group]
433
444
 
434
445
  topics.each do |topic|
435
- groups_lags[cg][topic] ||= {}
446
+ groups_lags[group][topic] ||= {}
436
447
 
437
448
  next unless existing_topics.key?(topic)
438
449
 
439
- # We backfill because there is a case where our consumer group would consume for
450
+ # We backfill because there is a case where our group would consume for
440
451
  # example only one partition out of 20, rest needs to get -1
441
452
  existing_topics[topic].times do |partition_id|
442
- groups_lags[cg][topic][partition_id] ||= -1
453
+ groups_lags[group][topic][partition_id] ||= -1
443
454
  end
444
455
  end
445
456
  end
446
457
 
447
458
  merged = Hash.new { |h, k| h[k] = {} }
448
459
 
449
- groups_lags.each do |cg, topics|
460
+ groups_lags.each do |group, topics|
450
461
  topics.each do |topic, partitions|
451
- merged[cg][topic] = {}
462
+ merged[group][topic] = {}
452
463
 
453
464
  partitions.each do |partition, lag|
454
- merged[cg][topic][partition] = {
455
- offset: groups_offs.fetch(cg).fetch(topic).fetch(partition),
465
+ merged[group][topic][partition] = {
466
+ offset: groups_offs.fetch(group).fetch(topic).fetch(partition),
456
467
  lag: lag
457
468
  }
458
469
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ class Admin
5
+ # Isolation level constants for Kafka operations.
6
+ #
7
+ # Controls whether a query returns the high-watermark (includes messages from uncommitted
8
+ # or in-flight transactions) or the Last Stable Offset (excludes them).
9
+ #
10
+ # For non-transactional topics both values give the same result.
11
+ module IsolationLevels
12
+ # Default. Returns the high-watermark offset, which includes messages written by
13
+ # producers that have not yet committed (or aborted) their transaction.
14
+ READ_UNCOMMITTED = Rdkafka::Bindings::RD_KAFKA_ISOLATION_LEVEL_READ_UNCOMMITTED
15
+
16
+ # Returns the Last Stable Offset (LSO): the highest offset that a READ_COMMITTED
17
+ # consumer would actually see. Use this when computing lag on topics produced with
18
+ # transactional producers, otherwise the high-watermark overstates lag.
19
+ READ_COMMITTED = Rdkafka::Bindings::RD_KAFKA_ISOLATION_LEVEL_READ_COMMITTED
20
+ end
21
+ end
22
+ end
@@ -52,6 +52,13 @@ module Karafka
52
52
  def info(topic_name)
53
53
  new.info(topic_name)
54
54
  end
55
+
56
+ # @param topic_partition_offsets [Hash{String => Array<Hash>}] topics with partition specs
57
+ # @param isolation_level [Integer, nil] optional isolation level constant
58
+ # @see #read_partition_offsets
59
+ def read_partition_offsets(topic_partition_offsets, isolation_level: nil)
60
+ new.read_partition_offsets(topic_partition_offsets, isolation_level: isolation_level)
61
+ end
55
62
  end
56
63
 
57
64
  # Allows us to read messages from the topic
@@ -186,8 +193,7 @@ module Karafka
186
193
  end
187
194
  end
188
195
 
189
- # Fetches the watermark offsets for a given topic partition or multiple topics and
190
- # partitions
196
+ # Fetches the watermark offsets for a given topic partition or multiple topics and partitions
191
197
  #
192
198
  # @param name_or_hash [String, Symbol, Hash] topic name or hash with topics and partitions
193
199
  # @param partition [Integer, nil] partition number
@@ -217,13 +223,30 @@ module Karafka
217
223
  # Normalize input to hash format
218
224
  topics_with_partitions = partition ? { name_or_hash => [partition] } : name_or_hash
219
225
 
220
- result = Hash.new { |h, k| h[k] = {} }
226
+ low_specs = {}
227
+ high_specs = {}
228
+
229
+ topics_with_partitions.each do |topic, partitions|
230
+ low_specs[topic] = partitions.map { |p| { partition: p, offset: :earliest } }
231
+ high_specs[topic] = partitions.map { |p| { partition: p, offset: :latest } }
232
+ end
233
+
234
+ lows = {}
235
+ highs = {}
236
+
237
+ with_admin do |admin|
238
+ admin.list_offsets(low_specs).wait(max_wait_timeout_ms: max_wait_time_ms).offsets.each do |r|
239
+ (lows[r[:topic]] ||= {})[r[:partition]] = r[:offset]
240
+ end
241
+ admin.list_offsets(high_specs).wait(max_wait_timeout_ms: max_wait_time_ms).offsets.each do |r|
242
+ (highs[r[:topic]] ||= {})[r[:partition]] = r[:offset]
243
+ end
244
+ end
221
245
 
222
- with_consumer do |consumer|
223
- topics_with_partitions.each do |topic, partitions|
224
- partitions.each do |partition_id|
225
- result[topic][partition_id] = consumer.query_watermark_offsets(topic, partition_id)
226
- end
246
+ result = Hash.new { |h, k| h[k] = {} }
247
+ topics_with_partitions.each do |topic, partitions|
248
+ partitions.each do |partition_id|
249
+ result[topic][partition_id] = [lows.dig(topic.to_s, partition_id), highs.dig(topic.to_s, partition_id)]
227
250
  end
228
251
  end
229
252
 
@@ -231,6 +254,78 @@ module Karafka
231
254
  partition ? result.dig(name_or_hash, partition) : result
232
255
  end
233
256
 
257
+ # Queries partition offsets by specification using the Kafka ListOffsets admin API.
258
+ #
259
+ # This is a lower-level, more flexible alternative to `#read_watermark_offsets`. The key
260
+ # differences are:
261
+ #
262
+ # - Transactional correctness: `read_watermark_offsets` always returns the high-watermark
263
+ # offset, which includes messages from uncommitted or in-flight transactions. A
264
+ # `READ_COMMITTED` consumer will never see those messages, so lag calculated from the
265
+ # high-watermark is overstated on transactionally-produced topics. Passing
266
+ # `isolation_level: Karafka::Admin::IsolationLevels::READ_COMMITTED` here
267
+ # returns the Last Stable Offset (LSO) — the highest offset a `READ_COMMITTED` consumer
268
+ # would actually reach — giving accurate lag figures.
269
+ #
270
+ # - `:max_timestamp` spec: returns the offset of the message with the highest timestamp
271
+ # in the partition. Not available via watermarks.
272
+ #
273
+ # - Leader epoch: the response includes `leader_epoch`, which can be used to detect
274
+ # stale metadata or fencing conditions.
275
+ #
276
+ # - Admin API: operates through the admin client rather than a consumer connection.
277
+ #
278
+ # For non-transactional topics, `:latest` here and `read_watermark_offsets` high-watermark
279
+ # return the same value.
280
+ #
281
+ # @param topic_partition_offsets [Hash{String => Array<Hash>}] hash with topic names as keys
282
+ # and arrays of partition specs as values. Each spec must have:
283
+ # - `:partition` [Integer] the partition number
284
+ # - `:offset` [Symbol, Integer] `:earliest`, `:latest`, `:max_timestamp`, or an Integer
285
+ # timestamp in milliseconds (returns the first offset at or after that timestamp)
286
+ # Each partition may appear at most once per call.
287
+ # @param isolation_level [Integer, nil] optional isolation level constant. Pass
288
+ # `Karafka::Admin::IsolationLevels::READ_COMMITTED` to get the LSO instead of the
289
+ # high-watermark for `:latest` queries on transactionally-produced topics.
290
+ #
291
+ # @return [Array<Hash>] array of result hashes, each containing:
292
+ # - `:topic` [String]
293
+ # - `:partition` [Integer]
294
+ # - `:offset` [Integer]
295
+ # - `:timestamp` [Integer] (-1 when not applicable)
296
+ # - `:leader_epoch` [Integer, nil]
297
+ #
298
+ # @raise [Rdkafka::RdkafkaError] on per-partition errors or connection issues
299
+ #
300
+ # @example Query earliest offset for partition 0 and latest for partition 1
301
+ # Karafka::Admin::Topics.read_partition_offsets(
302
+ # 'events' => [
303
+ # { partition: 0, offset: :earliest },
304
+ # { partition: 1, offset: :latest }
305
+ # ]
306
+ # )
307
+ # # => [
308
+ # # { topic: 'events', partition: 0, offset: 0, timestamp: -1, leader_epoch: nil },
309
+ # # { topic: 'events', partition: 1, offset: 100, timestamp: -1, leader_epoch: nil }
310
+ # # ]
311
+ #
312
+ # @example Get LSO (Last Stable Offset) for accurate lag on transactional topics
313
+ # Karafka::Admin::Topics.read_partition_offsets(
314
+ # 'events' => [{ partition: 0, offset: :latest }],
315
+ # isolation_level: Karafka::Admin::IsolationLevels::READ_COMMITTED
316
+ # )
317
+ #
318
+ # @example Find offset at a specific point in time
319
+ # Karafka::Admin::Topics.read_partition_offsets(
320
+ # 'events' => [{ partition: 0, offset: 1_700_000_000_000 }]
321
+ # )
322
+ def read_partition_offsets(topic_partition_offsets, isolation_level: nil)
323
+ with_admin do |admin|
324
+ handle = admin.list_offsets(topic_partition_offsets, isolation_level: isolation_level)
325
+ handle.wait(max_wait_timeout_ms: max_wait_time_ms).offsets
326
+ end
327
+ end
328
+
234
329
  # Returns basic topic metadata
235
330
  #
236
331
  # @param topic_name [String] name of the topic we're interested in