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
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Declaratives
5
+ # The main entry point for the declaratives subsystem. Returned by `Karafka::App.declaratives`.
6
+ # Provides the `draw` DSL and programmatic access to topic declarations and operations.
7
+ class Builder
8
+ attr_reader :repository
9
+
10
+ def initialize
11
+ @repository = Repository.new
12
+ @defaults = ->(_) {}
13
+ end
14
+
15
+ # DSL entry point for declaring topics outside of routing blocks.
16
+ #
17
+ # @param block [Proc] block to evaluate in builder context
18
+ #
19
+ # @example
20
+ # Karafka::App.declaratives.draw do
21
+ # topic :orders do
22
+ # partitions 10
23
+ # replication_factor 3
24
+ # config 'retention.ms' => 604_800_000
25
+ # end
26
+ # end
27
+ def draw(&block)
28
+ instance_eval(&block)
29
+ end
30
+
31
+ # Sets default values applied to every topic declared after this call.
32
+ # Defaults are evaluated before the topic block, so topic-specific values override them.
33
+ #
34
+ # @param block [Proc] block evaluated in each topic's context before the topic block
35
+ def defaults(&block)
36
+ @defaults = block
37
+ end
38
+
39
+ # Declares a topic with the given name. If a topic with this name was already declared
40
+ # (via routing bridge or a prior draw call), the existing declaration is returned and
41
+ # the block is evaluated on it (allowing additive configuration).
42
+ #
43
+ # @param name [String, Symbol] topic name
44
+ # @param block [Proc] optional block evaluated in the topic's context
45
+ # @return [Karafka::Declaratives::Topic] the declaration
46
+ def topic(name, &block)
47
+ declaration = @repository.find_or_create(name)
48
+ declaration.instance_eval(&@defaults)
49
+ declaration.instance_eval(&block) if block
50
+ declaration
51
+ end
52
+
53
+ # @return [Array<Karafka::Declaratives::Topic>] all active topic declarations
54
+ def topics
55
+ @repository.active
56
+ end
57
+
58
+ # @param name [String, Symbol] topic name
59
+ # @return [Karafka::Declaratives::Topic, nil] specific topic declaration
60
+ def find_topic(name)
61
+ @repository.find(name)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Declaratives
5
+ # Namespace for declaratives-specific validation contracts
6
+ module Contracts
7
+ # Validates declarative topic configuration. This is the canonical location for declarative
8
+ # topic validation, replacing the routing feature contract.
9
+ class Topic < Karafka::Contracts::Base
10
+ configure do |config|
11
+ config.error_messages = YAML.safe_load_file(
12
+ File.join(Karafka.gem_root, "config", "locales", "errors.yml")
13
+ ).fetch("en").fetch("validations").fetch("declaratives").fetch("topic")
14
+ end
15
+
16
+ nested :declaratives do
17
+ required(:active) { |val| [true, false].include?(val) }
18
+ required(:partitions) { |val| val.is_a?(Integer) && val.positive? }
19
+ required(:replication_factor) { |val| val.is_a?(Integer) && val.positive? }
20
+ required(:details) do |val|
21
+ val.is_a?(Hash) &&
22
+ val.keys.all?(Symbol)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Declaratives
5
+ # Holds all topic declarations. Single source of truth for "what topics have been declared."
6
+ # Both the new DSL and the routing bridge populate this repository.
7
+ class Repository
8
+ def initialize
9
+ @topics = {}
10
+ end
11
+
12
+ # Finds an existing declaration or creates a new one for the given topic name
13
+ # @param name [String, Symbol] topic name
14
+ # @return [Karafka::Declaratives::Topic] the declaration
15
+ def find_or_create(name)
16
+ @topics[name.to_s] ||= Topic.new(name)
17
+ end
18
+
19
+ # @return [Array<Karafka::Declaratives::Topic>] all declarations where active? is true
20
+ def active
21
+ @topics.values.select(&:active?)
22
+ end
23
+
24
+ # @param name [String, Symbol] topic name
25
+ # @return [Karafka::Declaratives::Topic, nil] the declaration or nil
26
+ def find(name)
27
+ @topics[name.to_s]
28
+ end
29
+
30
+ # Iterates over all declarations
31
+ # @param block [Proc] block to yield each topic to
32
+ def each(&block)
33
+ @topics.each_value(&block)
34
+ end
35
+
36
+ # @return [Integer] number of declarations
37
+ def size
38
+ @topics.size
39
+ end
40
+
41
+ # @return [Boolean] are there any declarations
42
+ def empty?
43
+ @topics.empty?
44
+ end
45
+
46
+ # Removes all declarations
47
+ def clear
48
+ @topics.clear
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Declaratives
5
+ # Represents a single declarative topic definition - what a topic should look like on the
6
+ # broker. This is a standalone object, independent of routing concepts like consumers or
7
+ # subscription groups.
8
+ class Topic
9
+ attr_reader :name, :details
10
+ attr_writer :active, :partitions, :replication_factor, :details
11
+
12
+ # Bootstrap servers for the Kafka cluster this topic belongs to.
13
+ # Set by the routing bridge from the routing topic's kafka config.
14
+ # Topics declared via the standalone DSL leave this nil (treated as default cluster).
15
+ attr_accessor :bootstrap_servers
16
+
17
+ # @param name [String, Symbol] topic name
18
+ def initialize(name)
19
+ @name = name.to_s
20
+ @active = true
21
+ @partitions = 1
22
+ @replication_factor = 1
23
+ @details = {}
24
+ @bootstrap_servers = nil
25
+ end
26
+
27
+ # Self-accessor for backwards compatibility.
28
+ # CLI commands that previously accessed topic.declaratives.partitions on routing topics
29
+ # can now call the same on Declaratives::Topic instances directly.
30
+ #
31
+ # @return [Karafka::Declaratives::Topic] self
32
+ def declaratives
33
+ self
34
+ end
35
+
36
+ # Gets or sets the active flag.
37
+ #
38
+ # The active flag exists because the routing bridge (Routing::Features::Declaratives::Topic)
39
+ # auto-creates a declaration for every routing topic that calls config(). Some routing
40
+ # topics - notably Pro pattern-matched virtual topics - must exist in routing but cannot
41
+ # be managed declaratively (their real Kafka topic names are unknown). Those call
42
+ # config(active: false) to opt out. Once the routing bridge is retired and declaratives
43
+ # are defined exclusively via Karafka::App.declaratives.draw, this flag becomes
44
+ # unnecessary: topics simply won't be declared if they shouldn't be managed.
45
+ #
46
+ # @param value [Symbol, Boolean] when :not_set returns current value, otherwise sets it
47
+ # @return [Boolean] active state
48
+ def active(value = :not_set)
49
+ if value == :not_set
50
+ @active
51
+ else
52
+ @active = value
53
+ end
54
+ end
55
+
56
+ # @return [Boolean] is this topic actively managed via declaratives
57
+ def active?
58
+ @active
59
+ end
60
+
61
+ # Gets or sets the partition count
62
+ # @param value [Symbol, Integer] when :not_set returns current value, otherwise sets it
63
+ # @return [Integer] partition count
64
+ def partitions(value = :not_set)
65
+ if value == :not_set
66
+ @partitions
67
+ else
68
+ @partitions = value
69
+ end
70
+ end
71
+
72
+ # Gets or sets the replication factor
73
+ # @param value [Symbol, Integer] when :not_set returns current value, otherwise sets it
74
+ # @return [Integer] replication factor
75
+ def replication_factor(value = :not_set)
76
+ if value == :not_set
77
+ @replication_factor
78
+ else
79
+ @replication_factor = value
80
+ end
81
+ end
82
+
83
+ # Merges Kafka topic configuration entries into the details hash
84
+ # @param entries [Hash] topic config entries like 'retention.ms' => 604_800_000
85
+ def config(entries = {})
86
+ @details.merge!(entries.transform_keys(&:to_sym))
87
+ end
88
+
89
+ # @return [Hash] hash representation matching the old Config struct's to_h output
90
+ def to_h
91
+ {
92
+ active: @active,
93
+ partitions: @partitions,
94
+ replication_factor: @replication_factor,
95
+ details: @details
96
+ }
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ # Top-level namespace for declarative topic management (infrastructure-as-code).
5
+ # Declarative topics define what topics should exist on the Kafka cluster with what
6
+ # configuration. This is independent of routing, which defines how messages are consumed.
7
+ module Declaratives
8
+ end
9
+ end
@@ -25,14 +25,14 @@ module Karafka
25
25
  end
26
26
 
27
27
  # Runs the requested code if it was not executed previously recently
28
- def call
28
+ def call(...)
29
29
  now = monotonic_now
30
30
 
31
31
  return if now - @last_called_at < @interval
32
32
 
33
33
  @last_called_at = now
34
34
 
35
- @block.call
35
+ @block.call(...)
36
36
  end
37
37
 
38
38
  # Runs the requested code bypassing any time frequencies
@@ -14,10 +14,33 @@ module Karafka
14
14
  class AssignmentsTracker
15
15
  include Singleton
16
16
 
17
+ class << self
18
+ # @return [Hash{Karafka::Routing::Topic => Array<Integer>}]
19
+ # @see #current
20
+ def current
21
+ instance.current
22
+ end
23
+
24
+ # @return [Hash{Karafka::Routing::Topic => Hash{Integer => Integer}}]
25
+ # @see #generations
26
+ def generations
27
+ instance.generations
28
+ end
29
+
30
+ # @param topic [Karafka::Routing::Topic]
31
+ # @param partition [Integer]
32
+ # @return [Integer]
33
+ # @see #generation
34
+ def generation(topic, partition)
35
+ instance.generation(topic, partition)
36
+ end
37
+ end
38
+
17
39
  # Initializes the assignments tracker with empty assignments
18
40
  def initialize
19
41
  @mutex = Mutex.new
20
42
  @assignments = Hash.new { |hash, key| hash[key] = [] }
43
+ @generations = Hash.new { |h, k| h[k] = {} }
21
44
  end
22
45
 
23
46
  # Returns all the active/current assignments of this given process
@@ -44,10 +67,41 @@ module Karafka
44
67
  assignments.freeze
45
68
  end
46
69
 
47
- # Clears all the assignments
70
+ # Returns the generation counts for all partitions that have ever been assigned
71
+ #
72
+ # @return [Hash{Karafka::Routing::Topic => Hash{Integer => Integer}}] topic to partition
73
+ # generation mapping. Generation starts at 1 on first assignment and increments on each
74
+ # reassignment. Revoked partitions remain in the hash with their last generation value.
75
+ #
76
+ # @note Returns a frozen deep copy to prevent external mutation
77
+ def generations
78
+ result = {}
79
+
80
+ @mutex.synchronize do
81
+ @generations.each do |topic, partitions|
82
+ result[topic] = partitions.dup.freeze
83
+ end
84
+ end
85
+
86
+ result.freeze
87
+ end
88
+
89
+ # Returns the generation count for a specific topic-partition
90
+ #
91
+ # @param topic [Karafka::Routing::Topic]
92
+ # @param partition [Integer]
93
+ # @return [Integer] generation count (0 if never assigned, 1+ otherwise)
94
+ def generation(topic, partition)
95
+ @mutex.synchronize do
96
+ @generations.dig(topic, partition) || 0
97
+ end
98
+ end
99
+
100
+ # Clears all the assignments and generations
48
101
  def clear
49
102
  @mutex.synchronize do
50
103
  @assignments.clear
104
+ @generations.clear
51
105
  end
52
106
  end
53
107
 
@@ -125,7 +179,16 @@ module Karafka
125
179
  event[:tpl].to_h.each do |topic, partitions|
126
180
  topic = sg.topics.find(topic)
127
181
 
128
- @assignments[topic] += partitions.map(&:partition)
182
+ partition_ids = []
183
+
184
+ partitions.each do |partition|
185
+ partition_id = partition.partition
186
+ partition_ids << partition_id
187
+ @generations[topic][partition_id] ||= 0
188
+ @generations[topic][partition_id] += 1
189
+ end
190
+
191
+ @assignments[topic] += partition_ids
129
192
  @assignments[topic].sort!
130
193
  end
131
194
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Instrumentation
5
+ # Callbacks used to transport things from rdkafka
6
+ module Callbacks
7
+ # Consumer-group-specific librdkafka callbacks
8
+ module ConsumerGroups
9
+ # Callback that kicks in when consumer error occurs and is published in a background thread
10
+ class Error
11
+ include Helpers::ConfigImporter.new(
12
+ monitor: %i[monitor]
13
+ )
14
+
15
+ # @param subscription_group_id [String]
16
+ # @param group_id [String] id of the owning group (consumer group today)
17
+ # @param client_name [String] rdkafka client name
18
+ def initialize(subscription_group_id, group_id, client_name)
19
+ @subscription_group_id = subscription_group_id
20
+ @group_id = group_id
21
+ @client_name = client_name
22
+ end
23
+
24
+ # Runs the instrumentation monitor with error
25
+ # @param client_name [String] rdkafka client name
26
+ # @param error [Rdkafka::Error] error that occurred
27
+ # @note It will only instrument on errors of the client of our consumer
28
+ def call(client_name, error)
29
+ # Emit only errors related to our client Same as with statistics (mor explanation there)
30
+ return unless @client_name == client_name
31
+
32
+ monitor.instrument(
33
+ "error.occurred",
34
+ caller: self,
35
+ subscription_group_id: @subscription_group_id,
36
+ consumer_group_id: @group_id,
37
+ group_id: @group_id,
38
+ type: "librdkafka.error",
39
+ error: error
40
+ )
41
+ rescue => e
42
+ monitor.instrument(
43
+ "error.occurred",
44
+ caller: self,
45
+ subscription_group_id: @subscription_group_id,
46
+ consumer_group_id: @group_id,
47
+ group_id: @group_id,
48
+ type: "callbacks.error.error",
49
+ error: e
50
+ )
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Instrumentation
5
+ module Callbacks
6
+ # Consumer-group-specific librdkafka callbacks (rebalance events etc.)
7
+ module ConsumerGroups
8
+ # Callback that connects to the librdkafka rebalance callback and converts those events
9
+ # into our internal events
10
+ class Rebalance
11
+ include Helpers::ConfigImporter.new(
12
+ monitor: %i[monitor]
13
+ )
14
+
15
+ # @param subscription_group [Karafka::Routes::SubscriptionGroup] subscription group for
16
+ # which we want to manage rebalances
17
+ # @param client_id [String] id of the client managing this rebalance
18
+ def initialize(subscription_group, client_id)
19
+ @subscription_group = subscription_group
20
+ @client_id = client_id
21
+ end
22
+
23
+ # Publishes an event that partitions are going to be revoked.
24
+ # At this stage we can still commit offsets, etc.
25
+ #
26
+ # @param tpl [Rdkafka::Consumer::TopicPartitionList]
27
+ def on_partitions_revoke(tpl)
28
+ instrument("partitions_revoke", tpl)
29
+ end
30
+
31
+ # Publishes an event that partitions are going to be assigned
32
+ #
33
+ # @param tpl [Rdkafka::Consumer::TopicPartitionList]
34
+ def on_partitions_assign(tpl)
35
+ instrument("partitions_assign", tpl)
36
+ end
37
+
38
+ # Publishes an event that partitions were revoked. This is after we've lost them, so no
39
+ # option to commit offsets.
40
+ #
41
+ # @param tpl [Rdkafka::Consumer::TopicPartitionList]
42
+ def on_partitions_revoked(tpl)
43
+ instrument("partitions_revoked", tpl)
44
+ end
45
+
46
+ # Publishes an event that partitions were assigned.
47
+ #
48
+ # @param tpl [Rdkafka::Consumer::TopicPartitionList]
49
+ def on_partitions_assigned(tpl)
50
+ instrument("partitions_assigned", tpl)
51
+ end
52
+
53
+ private
54
+
55
+ # Publishes info that a rebalance event of a given type has happened
56
+ #
57
+ # @param name [String] name of the event
58
+ # @param tpl [Rdkafka::Consumer::TopicPartitionList]
59
+ def instrument(name, tpl)
60
+ monitor.instrument(
61
+ "rebalance.#{name}",
62
+ caller: self,
63
+ # We keep the id references here for backwards compatibility as some of the monitors
64
+ # may use the id references
65
+ subscription_group_id: @subscription_group.id,
66
+ subscription_group: @subscription_group,
67
+ # `consumer_group_id:` / `consumer_group:` are kept for backwards compatibility.
68
+ # `group_id:` / `group:` are the forward-looking polymorphic keys and carry the same
69
+ # value. The legacy keys will be retired once share groups land.
70
+ consumer_group_id: @subscription_group.group.id,
71
+ consumer_group: @subscription_group.group,
72
+ group_id: @subscription_group.group.id,
73
+ group: @subscription_group.group,
74
+ client_id: @client_id,
75
+ tpl: tpl
76
+ )
77
+ rescue => e
78
+ monitor.instrument(
79
+ "error.occurred",
80
+ caller: self,
81
+ subscription_group_id: @subscription_group.id,
82
+ consumer_group_id: @subscription_group.group.id,
83
+ group_id: @subscription_group.group.id,
84
+ type: "callbacks.rebalance.#{name}.error",
85
+ client_id: @client_id,
86
+ error: e
87
+ )
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Instrumentation
5
+ module Callbacks
6
+ module ConsumerGroups
7
+ # Statistics callback handler
8
+ # @see `WaterDrop::Instrumentation::Callbacks::Statistics` for details on why we decorate
9
+ # those statistics
10
+ class Statistics
11
+ include Helpers::ConfigImporter.new(
12
+ monitor: %i[monitor]
13
+ )
14
+
15
+ # @param subscription_group_id [String]
16
+ # @param group_id [String] id of the owning group (consumer group today)
17
+ # @param client_name [String] rdkafka client name
18
+ def initialize(subscription_group_id, group_id, client_name)
19
+ @subscription_group_id = subscription_group_id
20
+ @group_id = group_id
21
+ @client_name = client_name
22
+ @statistics_decorator = Karafka::Core::Monitoring::StatisticsDecorator.new
23
+ end
24
+
25
+ # Emits decorated statistics to the monitor
26
+ # @param statistics [Hash] rdkafka statistics
27
+ def call(statistics)
28
+ # Emit only statistics related to our client
29
+ # rdkafka does not have per-instance statistics hook, thus we need to make sure that we
30
+ # emit only stats that are related to current producer. Otherwise we would emit all of
31
+ # all the time.
32
+ return unless @client_name == statistics["name"]
33
+
34
+ monitor.instrument(
35
+ "statistics.emitted",
36
+ subscription_group_id: @subscription_group_id,
37
+ consumer_group_id: @group_id,
38
+ group_id: @group_id,
39
+ statistics: @statistics_decorator.call(statistics)
40
+ )
41
+ # We need to catch and handle any potential errors coming from the instrumentation pipeline
42
+ # as otherwise, in case of statistics which run in the main librdkafka thread, any crash
43
+ # will hang the whole process.
44
+ rescue => e
45
+ monitor.instrument(
46
+ "error.occurred",
47
+ caller: self,
48
+ subscription_group_id: @subscription_group_id,
49
+ consumer_group_id: @group_id,
50
+ group_id: @group_id,
51
+ type: "callbacks.statistics.error",
52
+ error: e
53
+ )
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -28,9 +28,9 @@ module Karafka
28
28
  def on_connection_listener_before_fetch_loop(event)
29
29
  listener_id = event[:caller].id
30
30
  subscription_group = event[:subscription_group]
31
- consumer_group_id = subscription_group.consumer_group.id
31
+ group_id = subscription_group.group.id
32
32
  topics = subscription_group.topics.select(&:active?).map(&:name).join(", ")
33
- group_details = "#{consumer_group_id}/#{subscription_group.id}"
33
+ group_details = "#{group_id}/#{subscription_group.id}"
34
34
 
35
35
  info(
36
36
  "[#{listener_id}] Group #{group_details} subscribing to topics: #{topics}"
@@ -93,6 +93,25 @@ module Karafka
93
93
  MSG
94
94
  end
95
95
 
96
+ # Logs info about the workers pool scaling up
97
+ #
98
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
99
+ def on_worker_scaling_up(event)
100
+ from = event[:from]
101
+ to = event[:to]
102
+ info "Workers pool scaled up from #{from} to #{to} workers"
103
+ end
104
+
105
+ # Logs info about the workers pool scaling down.
106
+ # The actual size change happens asynchronously as workers pick up nil sentinels and exit.
107
+ #
108
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
109
+ def on_worker_scaling_down(event)
110
+ from = event[:from]
111
+ to = event[:to]
112
+ info "Workers pool scaling down from #{from} to #{to} workers"
113
+ end
114
+
96
115
  # Prints info about a consumer pause occurrence. Irrelevant if user or system initiated.
97
116
  #
98
117
  # @param event [Karafka::Core::Monitoring::Event] event details including payload
@@ -224,7 +243,7 @@ module Karafka
224
243
  # @param event [Karafka::Core::Monitoring::Event] event details with revoked partitions
225
244
  def on_rebalance_partitions_revoked(event)
226
245
  revoked_partitions = event[:tpl].to_h.transform_values { |part| part.map(&:partition) }
227
- group_id = event[:consumer_group_id]
246
+ group_id = event[:group_id]
228
247
  client_id = event[:client_id]
229
248
  group_prefix = "[#{client_id}] Group #{group_id} rebalance"
230
249
 
@@ -242,7 +261,7 @@ module Karafka
242
261
  # @param event [Karafka::Core::Monitoring::Event] event details with assigned partitions
243
262
  def on_rebalance_partitions_assigned(event)
244
263
  assigned_partitions = event[:tpl].to_h.transform_values { |part| part.map(&:partition) }
245
- group_id = event[:consumer_group_id]
264
+ group_id = event[:group_id]
246
265
  client_id = event[:client_id]
247
266
  group_prefix = "[#{client_id}] Group #{group_id} rebalance"
248
267
 
@@ -475,8 +494,7 @@ module Karafka
475
494
  def error_details(event)
476
495
  caller_ref = event[:caller]
477
496
 
478
- # Collect extra info if it was a consumer related error.
479
- # Those come from user code
497
+ # Collect extra info if it was a consumer related error. Those come from user code
480
498
  details = case caller_ref
481
499
  when Karafka::BaseConsumer
482
500
  extract_consumer_info(caller_ref)
@@ -497,7 +515,7 @@ module Karafka
497
515
  # @return [Hash] hash with consumer specific info for details of error
498
516
  def extract_consumer_info(consumer)
499
517
  {
500
- consumer_group: consumer.topic.consumer_group.id,
518
+ consumer_group: consumer.topic.group.id,
501
519
  subscription_group: consumer.topic.subscription_group.id,
502
520
  topic: consumer.topic.name,
503
521
  partition: consumer.partition,
@@ -510,7 +528,7 @@ module Karafka
510
528
  # @return [Hash] hash with client specific info for details of error
511
529
  def extract_client_info(client)
512
530
  {
513
- consumer_group: client.subscription_group.consumer_group.id,
531
+ consumer_group: client.subscription_group.group.id,
514
532
  subscription_group: client.subscription_group.id
515
533
  }
516
534
  end
@@ -519,7 +537,7 @@ module Karafka
519
537
  # @return [Hash] hash with listener specific info for details of error
520
538
  def extract_listener_info(listener)
521
539
  {
522
- consumer_group: listener.subscription_group.consumer_group.id,
540
+ consumer_group: listener.subscription_group.group.id,
523
541
  subscription_group: listener.subscription_group.id
524
542
  }
525
543
  end
@@ -108,6 +108,8 @@ module Karafka
108
108
  worker.process
109
109
  worker.processed
110
110
  worker.completed
111
+ worker.scaling.up
112
+ worker.scaling.down
111
113
 
112
114
  error.occurred
113
115
  ].freeze