karafka 2.4.0 → 2.4.18

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 (326) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +26 -34
  4. data/.github/workflows/ci.yml +18 -6
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +146 -1
  7. data/Gemfile +10 -5
  8. data/Gemfile.lock +60 -39
  9. data/LICENSE +8 -3
  10. data/bin/integrations +13 -1
  11. data/certs/cert.pem +26 -0
  12. data/config/locales/errors.yml +18 -2
  13. data/config/locales/pro_errors.yml +44 -0
  14. data/docker-compose.yml +1 -3
  15. data/karafka.gemspec +6 -4
  16. data/lib/active_job/queue_adapters/karafka_adapter.rb +18 -7
  17. data/lib/karafka/active_job/dispatcher.rb +13 -0
  18. data/lib/karafka/active_job/job_extensions.rb +3 -0
  19. data/lib/karafka/admin.rb +86 -0
  20. data/lib/karafka/app.rb +17 -0
  21. data/lib/karafka/base_consumer.rb +130 -19
  22. data/lib/karafka/cli/base.rb +24 -8
  23. data/lib/karafka/cli/install.rb +2 -1
  24. data/lib/karafka/cli/server.rb +1 -0
  25. data/lib/karafka/cli/swarm.rb +1 -0
  26. data/lib/karafka/cli/topics/align.rb +12 -2
  27. data/lib/karafka/cli/topics/plan.rb +54 -6
  28. data/lib/karafka/cli/topics.rb +45 -18
  29. data/lib/karafka/connection/client.rb +102 -35
  30. data/lib/karafka/connection/listener.rb +48 -11
  31. data/lib/karafka/connection/messages_buffer.rb +19 -6
  32. data/lib/karafka/connection/proxy.rb +3 -0
  33. data/lib/karafka/connection/raw_messages_buffer.rb +43 -9
  34. data/lib/karafka/connection/rebalance_manager.rb +24 -13
  35. data/lib/karafka/contracts/config.rb +4 -0
  36. data/lib/karafka/contracts/consumer_group.rb +17 -0
  37. data/lib/karafka/contracts/routing.rb +59 -0
  38. data/lib/karafka/contracts/topic.rb +14 -0
  39. data/lib/karafka/embedded.rb +46 -3
  40. data/lib/karafka/errors.rb +3 -2
  41. data/lib/karafka/helpers/async.rb +11 -2
  42. data/lib/karafka/helpers/config_importer.rb +13 -0
  43. data/lib/karafka/instrumentation/assignments_tracker.rb +7 -2
  44. data/lib/karafka/instrumentation/logger_listener.rb +45 -4
  45. data/lib/karafka/instrumentation/notifications.rb +12 -0
  46. data/lib/karafka/instrumentation/vendors/appsignal/client.rb +32 -11
  47. data/lib/karafka/instrumentation/vendors/appsignal/errors_listener.rb +1 -1
  48. data/lib/karafka/instrumentation/vendors/appsignal/metrics_listener.rb +3 -1
  49. data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +17 -19
  50. data/lib/karafka/instrumentation/vendors/datadog/metrics_listener.rb +27 -18
  51. data/lib/karafka/instrumentation/vendors/kubernetes/base_listener.rb +2 -2
  52. data/lib/karafka/instrumentation/vendors/kubernetes/liveness_listener.rb +41 -13
  53. data/lib/karafka/messages/message.rb +9 -9
  54. data/lib/karafka/pro/active_job/consumer.rb +2 -10
  55. data/lib/karafka/pro/active_job/dispatcher.rb +67 -19
  56. data/lib/karafka/pro/active_job/job_options_contract.rb +12 -10
  57. data/lib/karafka/pro/base_consumer.rb +2 -10
  58. data/lib/karafka/pro/cleaner/errors.rb +2 -10
  59. data/lib/karafka/pro/cleaner/messages/message.rb +14 -12
  60. data/lib/karafka/pro/cleaner/messages/messages.rb +2 -10
  61. data/lib/karafka/pro/cleaner/messages/metadata.rb +41 -0
  62. data/lib/karafka/pro/cleaner.rb +3 -10
  63. data/lib/karafka/pro/connection/manager.rb +6 -10
  64. data/lib/karafka/pro/connection/multiplexing/listener.rb +2 -10
  65. data/lib/karafka/pro/contracts/base.rb +2 -10
  66. data/lib/karafka/pro/contracts/server_cli_options.rb +2 -10
  67. data/lib/karafka/pro/encryption/cipher.rb +2 -10
  68. data/lib/karafka/pro/encryption/contracts/config.rb +2 -10
  69. data/lib/karafka/pro/encryption/errors.rb +2 -10
  70. data/lib/karafka/pro/encryption/messages/middleware.rb +2 -10
  71. data/lib/karafka/pro/encryption/messages/parser.rb +2 -10
  72. data/lib/karafka/pro/encryption/setup/config.rb +2 -10
  73. data/lib/karafka/pro/encryption.rb +2 -10
  74. data/lib/karafka/pro/instrumentation/performance_tracker.rb +2 -10
  75. data/lib/karafka/pro/iterator/expander.rb +2 -10
  76. data/lib/karafka/pro/iterator/tpl_builder.rb +2 -10
  77. data/lib/karafka/pro/iterator.rb +2 -10
  78. data/lib/karafka/pro/loader.rb +5 -11
  79. data/lib/karafka/pro/processing/adaptive_iterator/consumer.rb +54 -0
  80. data/lib/karafka/pro/processing/adaptive_iterator/tracker.rb +67 -0
  81. data/lib/karafka/pro/processing/collapser.rb +2 -10
  82. data/lib/karafka/pro/processing/coordinator.rb +2 -10
  83. data/lib/karafka/pro/processing/coordinators/errors_tracker.rb +2 -10
  84. data/lib/karafka/pro/processing/coordinators/filters_applier.rb +19 -10
  85. data/lib/karafka/pro/processing/coordinators/virtual_offset_manager.rb +2 -10
  86. data/lib/karafka/pro/processing/executor.rb +2 -10
  87. data/lib/karafka/pro/processing/expansions_selector.rb +3 -10
  88. data/lib/karafka/pro/processing/filters/base.rb +14 -10
  89. data/lib/karafka/pro/processing/filters/delayer.rb +4 -12
  90. data/lib/karafka/pro/processing/filters/expirer.rb +2 -10
  91. data/lib/karafka/pro/processing/filters/inline_insights_delayer.rb +2 -10
  92. data/lib/karafka/pro/processing/filters/throttler.rb +2 -10
  93. data/lib/karafka/pro/processing/filters/virtual_limiter.rb +2 -10
  94. data/lib/karafka/pro/processing/jobs/consume_non_blocking.rb +4 -10
  95. data/lib/karafka/pro/processing/jobs/eofed_non_blocking.rb +26 -0
  96. data/lib/karafka/pro/processing/jobs/periodic.rb +4 -10
  97. data/lib/karafka/pro/processing/jobs/periodic_non_blocking.rb +4 -10
  98. data/lib/karafka/pro/processing/jobs/revoked_non_blocking.rb +4 -10
  99. data/lib/karafka/pro/processing/jobs_builder.rb +14 -10
  100. data/lib/karafka/pro/processing/jobs_queue.rb +2 -10
  101. data/lib/karafka/pro/processing/offset_metadata/consumer.rb +2 -10
  102. data/lib/karafka/pro/processing/offset_metadata/fetcher.rb +2 -10
  103. data/lib/karafka/pro/processing/offset_metadata/listener.rb +2 -10
  104. data/lib/karafka/pro/processing/partitioner.rb +35 -24
  105. data/lib/karafka/pro/processing/periodic_job/consumer.rb +2 -10
  106. data/lib/karafka/pro/processing/piping/consumer.rb +2 -10
  107. data/lib/karafka/pro/processing/schedulers/base.rb +2 -10
  108. data/lib/karafka/pro/processing/schedulers/default.rb +3 -10
  109. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom.rb +3 -11
  110. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom_vp.rb +3 -11
  111. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom.rb +2 -10
  112. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom_vp.rb +2 -10
  113. data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom.rb +3 -11
  114. data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom_vp.rb +3 -11
  115. data/lib/karafka/pro/processing/strategies/aj/dlq_mom.rb +2 -10
  116. data/lib/karafka/pro/processing/strategies/aj/dlq_mom_vp.rb +2 -10
  117. data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom.rb +2 -10
  118. data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom_vp.rb +3 -11
  119. data/lib/karafka/pro/processing/strategies/aj/ftr_mom.rb +2 -10
  120. data/lib/karafka/pro/processing/strategies/aj/ftr_mom_vp.rb +2 -10
  121. data/lib/karafka/pro/processing/strategies/aj/lrj_mom.rb +2 -10
  122. data/lib/karafka/pro/processing/strategies/aj/lrj_mom_vp.rb +5 -13
  123. data/lib/karafka/pro/processing/strategies/aj/mom.rb +2 -10
  124. data/lib/karafka/pro/processing/strategies/aj/mom_vp.rb +2 -10
  125. data/lib/karafka/pro/processing/strategies/base.rb +2 -10
  126. data/lib/karafka/pro/processing/strategies/default.rb +140 -58
  127. data/lib/karafka/pro/processing/strategies/dlq/default.rb +23 -15
  128. data/lib/karafka/pro/processing/strategies/dlq/ftr.rb +2 -10
  129. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj.rb +3 -11
  130. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom.rb +7 -11
  131. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom_vp.rb +2 -10
  132. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_vp.rb +2 -10
  133. data/lib/karafka/pro/processing/strategies/dlq/ftr_mom.rb +19 -11
  134. data/lib/karafka/pro/processing/strategies/dlq/ftr_mom_vp.rb +2 -10
  135. data/lib/karafka/pro/processing/strategies/dlq/ftr_vp.rb +2 -10
  136. data/lib/karafka/pro/processing/strategies/dlq/lrj.rb +3 -11
  137. data/lib/karafka/pro/processing/strategies/dlq/lrj_mom.rb +19 -11
  138. data/lib/karafka/pro/processing/strategies/dlq/lrj_mom_vp.rb +2 -10
  139. data/lib/karafka/pro/processing/strategies/dlq/lrj_vp.rb +2 -10
  140. data/lib/karafka/pro/processing/strategies/dlq/mom.rb +24 -16
  141. data/lib/karafka/pro/processing/strategies/dlq/mom_vp.rb +2 -10
  142. data/lib/karafka/pro/processing/strategies/dlq/vp.rb +2 -10
  143. data/lib/karafka/pro/processing/strategies/ftr/default.rb +17 -12
  144. data/lib/karafka/pro/processing/strategies/ftr/vp.rb +2 -10
  145. data/lib/karafka/pro/processing/strategies/lrj/default.rb +5 -13
  146. data/lib/karafka/pro/processing/strategies/lrj/ftr.rb +3 -11
  147. data/lib/karafka/pro/processing/strategies/lrj/ftr_mom.rb +2 -10
  148. data/lib/karafka/pro/processing/strategies/lrj/ftr_mom_vp.rb +2 -10
  149. data/lib/karafka/pro/processing/strategies/lrj/ftr_vp.rb +2 -10
  150. data/lib/karafka/pro/processing/strategies/lrj/mom.rb +4 -12
  151. data/lib/karafka/pro/processing/strategies/lrj/mom_vp.rb +2 -10
  152. data/lib/karafka/pro/processing/strategies/lrj/vp.rb +2 -10
  153. data/lib/karafka/pro/processing/strategies/mom/default.rb +2 -10
  154. data/lib/karafka/pro/processing/strategies/mom/ftr.rb +2 -10
  155. data/lib/karafka/pro/processing/strategies/mom/ftr_vp.rb +2 -10
  156. data/lib/karafka/pro/processing/strategies/mom/vp.rb +2 -10
  157. data/lib/karafka/pro/processing/strategies/vp/default.rb +5 -10
  158. data/lib/karafka/pro/processing/strategies.rb +2 -10
  159. data/lib/karafka/pro/processing/strategy_selector.rb +2 -10
  160. data/lib/karafka/pro/processing/subscription_groups_coordinator.rb +2 -10
  161. data/lib/karafka/pro/recurring_tasks/consumer.rb +97 -0
  162. data/lib/karafka/pro/recurring_tasks/contracts/config.rb +45 -0
  163. data/lib/karafka/pro/recurring_tasks/contracts/task.rb +33 -0
  164. data/lib/karafka/pro/recurring_tasks/deserializer.rb +27 -0
  165. data/lib/karafka/pro/recurring_tasks/dispatcher.rb +79 -0
  166. data/lib/karafka/pro/recurring_tasks/errors.rb +26 -0
  167. data/lib/karafka/pro/recurring_tasks/executor.rb +144 -0
  168. data/lib/karafka/pro/recurring_tasks/listener.rb +30 -0
  169. data/lib/karafka/pro/recurring_tasks/matcher.rb +30 -0
  170. data/lib/karafka/pro/recurring_tasks/schedule.rb +55 -0
  171. data/lib/karafka/pro/recurring_tasks/serializer.rb +105 -0
  172. data/lib/karafka/pro/recurring_tasks/setup/config.rb +44 -0
  173. data/lib/karafka/pro/recurring_tasks/task.rb +143 -0
  174. data/lib/karafka/pro/recurring_tasks.rb +79 -0
  175. data/lib/karafka/pro/routing/features/active_job/builder.rb +2 -10
  176. data/lib/karafka/pro/routing/features/active_job.rb +2 -10
  177. data/lib/karafka/pro/routing/features/adaptive_iterator/config.rb +26 -0
  178. data/lib/karafka/pro/routing/features/adaptive_iterator/contracts/topic.rb +66 -0
  179. data/lib/karafka/pro/routing/features/adaptive_iterator/topic.rb +54 -0
  180. data/lib/karafka/pro/routing/features/adaptive_iterator.rb +23 -0
  181. data/lib/karafka/pro/routing/features/base.rb +2 -10
  182. data/lib/karafka/pro/routing/features/dead_letter_queue/contracts/topic.rb +2 -10
  183. data/lib/karafka/pro/routing/features/dead_letter_queue/topic.rb +2 -10
  184. data/lib/karafka/pro/routing/features/dead_letter_queue.rb +2 -10
  185. data/lib/karafka/pro/routing/features/delaying/config.rb +2 -10
  186. data/lib/karafka/pro/routing/features/delaying/contracts/topic.rb +2 -10
  187. data/lib/karafka/pro/routing/features/delaying/topic.rb +2 -10
  188. data/lib/karafka/pro/routing/features/delaying.rb +2 -10
  189. data/lib/karafka/pro/routing/features/direct_assignments/config.rb +2 -10
  190. data/lib/karafka/pro/routing/features/direct_assignments/contracts/consumer_group.rb +2 -10
  191. data/lib/karafka/pro/routing/features/direct_assignments/contracts/topic.rb +2 -10
  192. data/lib/karafka/pro/routing/features/direct_assignments/subscription_group.rb +2 -10
  193. data/lib/karafka/pro/routing/features/direct_assignments/topic.rb +2 -10
  194. data/lib/karafka/pro/routing/features/direct_assignments.rb +2 -10
  195. data/lib/karafka/pro/routing/features/expiring/config.rb +2 -10
  196. data/lib/karafka/pro/routing/features/expiring/contracts/topic.rb +2 -10
  197. data/lib/karafka/pro/routing/features/expiring/topic.rb +2 -10
  198. data/lib/karafka/pro/routing/features/expiring.rb +2 -10
  199. data/lib/karafka/pro/routing/features/filtering/config.rb +2 -10
  200. data/lib/karafka/pro/routing/features/filtering/contracts/topic.rb +2 -10
  201. data/lib/karafka/pro/routing/features/filtering/topic.rb +2 -10
  202. data/lib/karafka/pro/routing/features/filtering.rb +2 -10
  203. data/lib/karafka/pro/routing/features/inline_insights/config.rb +2 -10
  204. data/lib/karafka/pro/routing/features/inline_insights/contracts/topic.rb +2 -10
  205. data/lib/karafka/pro/routing/features/inline_insights/topic.rb +2 -10
  206. data/lib/karafka/pro/routing/features/inline_insights.rb +2 -10
  207. data/lib/karafka/pro/routing/features/long_running_job/config.rb +2 -10
  208. data/lib/karafka/pro/routing/features/long_running_job/contracts/topic.rb +2 -10
  209. data/lib/karafka/pro/routing/features/long_running_job/topic.rb +2 -10
  210. data/lib/karafka/pro/routing/features/long_running_job.rb +2 -10
  211. data/lib/karafka/pro/routing/features/multiplexing/config.rb +2 -10
  212. data/lib/karafka/pro/routing/features/multiplexing/contracts/topic.rb +2 -10
  213. data/lib/karafka/pro/routing/features/multiplexing/patches/contracts/consumer_group.rb +2 -10
  214. data/lib/karafka/pro/routing/features/multiplexing/proxy.rb +2 -10
  215. data/lib/karafka/pro/routing/features/multiplexing/subscription_group.rb +2 -10
  216. data/lib/karafka/pro/routing/features/multiplexing/subscription_groups_builder.rb +2 -10
  217. data/lib/karafka/pro/routing/features/multiplexing.rb +2 -10
  218. data/lib/karafka/pro/routing/features/non_blocking_job/topic.rb +2 -10
  219. data/lib/karafka/pro/routing/features/non_blocking_job.rb +2 -10
  220. data/lib/karafka/pro/routing/features/offset_metadata/config.rb +2 -10
  221. data/lib/karafka/pro/routing/features/offset_metadata/contracts/topic.rb +2 -10
  222. data/lib/karafka/pro/routing/features/offset_metadata/topic.rb +2 -10
  223. data/lib/karafka/pro/routing/features/offset_metadata.rb +2 -10
  224. data/lib/karafka/pro/routing/features/patterns/builder.rb +2 -10
  225. data/lib/karafka/pro/routing/features/patterns/config.rb +2 -10
  226. data/lib/karafka/pro/routing/features/patterns/consumer_group.rb +2 -10
  227. data/lib/karafka/pro/routing/features/patterns/contracts/consumer_group.rb +2 -10
  228. data/lib/karafka/pro/routing/features/patterns/contracts/pattern.rb +2 -10
  229. data/lib/karafka/pro/routing/features/patterns/contracts/topic.rb +2 -10
  230. data/lib/karafka/pro/routing/features/patterns/detector.rb +2 -10
  231. data/lib/karafka/pro/routing/features/patterns/pattern.rb +2 -10
  232. data/lib/karafka/pro/routing/features/patterns/patterns.rb +2 -10
  233. data/lib/karafka/pro/routing/features/patterns/topic.rb +2 -10
  234. data/lib/karafka/pro/routing/features/patterns/topics.rb +2 -10
  235. data/lib/karafka/pro/routing/features/patterns.rb +2 -10
  236. data/lib/karafka/pro/routing/features/pausing/contracts/topic.rb +2 -10
  237. data/lib/karafka/pro/routing/features/pausing/topic.rb +2 -10
  238. data/lib/karafka/pro/routing/features/pausing.rb +2 -10
  239. data/lib/karafka/pro/routing/features/periodic_job/config.rb +2 -10
  240. data/lib/karafka/pro/routing/features/periodic_job/contracts/topic.rb +2 -10
  241. data/lib/karafka/pro/routing/features/periodic_job/topic.rb +2 -10
  242. data/lib/karafka/pro/routing/features/periodic_job.rb +2 -10
  243. data/lib/karafka/pro/routing/features/recurring_tasks/builder.rb +123 -0
  244. data/lib/karafka/pro/routing/features/recurring_tasks/config.rb +20 -0
  245. data/lib/karafka/pro/routing/features/recurring_tasks/contracts/topic.rb +32 -0
  246. data/lib/karafka/pro/routing/features/recurring_tasks/proxy.rb +19 -0
  247. data/lib/karafka/pro/routing/features/recurring_tasks/topic.rb +36 -0
  248. data/lib/karafka/pro/routing/features/recurring_tasks.rb +17 -0
  249. data/lib/karafka/pro/routing/features/scheduled_messages/builder.rb +123 -0
  250. data/lib/karafka/pro/routing/features/scheduled_messages/config.rb +20 -0
  251. data/lib/karafka/pro/routing/features/scheduled_messages/contracts/topic.rb +32 -0
  252. data/lib/karafka/pro/routing/features/scheduled_messages/proxy.rb +19 -0
  253. data/lib/karafka/pro/routing/features/scheduled_messages/topic.rb +36 -0
  254. data/lib/karafka/pro/routing/features/scheduled_messages.rb +16 -0
  255. data/lib/karafka/pro/routing/features/swarm/config.rb +2 -10
  256. data/lib/karafka/pro/routing/features/swarm/contracts/routing.rb +2 -10
  257. data/lib/karafka/pro/routing/features/swarm/contracts/topic.rb +2 -10
  258. data/lib/karafka/pro/routing/features/swarm/topic.rb +2 -10
  259. data/lib/karafka/pro/routing/features/swarm.rb +2 -10
  260. data/lib/karafka/pro/routing/features/throttling/config.rb +2 -10
  261. data/lib/karafka/pro/routing/features/throttling/contracts/topic.rb +2 -10
  262. data/lib/karafka/pro/routing/features/throttling/topic.rb +2 -10
  263. data/lib/karafka/pro/routing/features/throttling.rb +2 -10
  264. data/lib/karafka/pro/routing/features/virtual_partitions/config.rb +3 -10
  265. data/lib/karafka/pro/routing/features/virtual_partitions/contracts/topic.rb +3 -10
  266. data/lib/karafka/pro/routing/features/virtual_partitions/topic.rb +10 -12
  267. data/lib/karafka/pro/routing/features/virtual_partitions.rb +2 -10
  268. data/lib/karafka/pro/scheduled_messages/consumer.rb +177 -0
  269. data/lib/karafka/pro/scheduled_messages/contracts/config.rb +48 -0
  270. data/lib/karafka/pro/scheduled_messages/contracts/message.rb +88 -0
  271. data/lib/karafka/pro/scheduled_messages/daily_buffer.rb +71 -0
  272. data/lib/karafka/pro/scheduled_messages/day.rb +37 -0
  273. data/lib/karafka/pro/scheduled_messages/deserializers/headers.rb +38 -0
  274. data/lib/karafka/pro/scheduled_messages/deserializers/payload.rb +27 -0
  275. data/lib/karafka/pro/scheduled_messages/dispatcher.rb +114 -0
  276. data/lib/karafka/pro/scheduled_messages/errors.rb +20 -0
  277. data/lib/karafka/pro/scheduled_messages/max_epoch.rb +33 -0
  278. data/lib/karafka/pro/scheduled_messages/proxy.rb +177 -0
  279. data/lib/karafka/pro/scheduled_messages/schema_validator.rb +29 -0
  280. data/lib/karafka/pro/scheduled_messages/serializer.rb +47 -0
  281. data/lib/karafka/pro/scheduled_messages/setup/config.rb +52 -0
  282. data/lib/karafka/pro/scheduled_messages/state.rb +54 -0
  283. data/lib/karafka/pro/scheduled_messages/tracker.rb +56 -0
  284. data/lib/karafka/pro/scheduled_messages.rb +59 -0
  285. data/lib/karafka/pro/swarm/liveness_listener.rb +2 -10
  286. data/lib/karafka/processing/coordinator.rb +14 -0
  287. data/lib/karafka/processing/executor.rb +29 -1
  288. data/lib/karafka/processing/jobs/base.rb +13 -0
  289. data/lib/karafka/processing/jobs/consume.rb +2 -0
  290. data/lib/karafka/processing/jobs/eofed.rb +29 -0
  291. data/lib/karafka/processing/jobs/idle.rb +2 -0
  292. data/lib/karafka/processing/jobs/revoked.rb +2 -0
  293. data/lib/karafka/processing/jobs/shutdown.rb +2 -0
  294. data/lib/karafka/processing/jobs_builder.rb +6 -0
  295. data/lib/karafka/processing/schedulers/default.rb +1 -0
  296. data/lib/karafka/processing/strategies/aj_dlq_mom.rb +1 -1
  297. data/lib/karafka/processing/strategies/default.rb +45 -13
  298. data/lib/karafka/processing/strategies/dlq.rb +19 -5
  299. data/lib/karafka/processing/strategies/dlq_mom.rb +27 -8
  300. data/lib/karafka/processing/worker.rb +26 -13
  301. data/lib/karafka/railtie.rb +11 -42
  302. data/lib/karafka/routing/builder.rb +19 -1
  303. data/lib/karafka/routing/consumer_group.rb +9 -14
  304. data/lib/karafka/routing/features/dead_letter_queue/config.rb +3 -0
  305. data/lib/karafka/routing/features/dead_letter_queue/contracts/topic.rb +1 -0
  306. data/lib/karafka/routing/features/dead_letter_queue/topic.rb +7 -2
  307. data/lib/karafka/routing/features/eofed/config.rb +15 -0
  308. data/lib/karafka/routing/features/eofed/contracts/topic.rb +39 -0
  309. data/lib/karafka/routing/features/eofed/topic.rb +31 -0
  310. data/lib/karafka/routing/features/eofed.rb +14 -0
  311. data/lib/karafka/routing/subscription_group.rb +29 -1
  312. data/lib/karafka/routing/topic.rb +24 -1
  313. data/lib/karafka/runner.rb +10 -9
  314. data/lib/karafka/server.rb +37 -1
  315. data/lib/karafka/setup/attributes_map.rb +11 -4
  316. data/lib/karafka/setup/config.rb +11 -52
  317. data/lib/karafka/setup/defaults_injector.rb +64 -0
  318. data/lib/karafka/swarm/node.rb +2 -0
  319. data/lib/karafka/swarm/supervisor.rb +11 -2
  320. data/lib/karafka/templates/karafka.rb.erb +2 -2
  321. data/lib/karafka/version.rb +1 -1
  322. data/lib/karafka.rb +47 -7
  323. data.tar.gz.sig +0 -0
  324. metadata +116 -33
  325. metadata.gz.sig +0 -0
  326. data/certs/cert_chain.pem +0 -26
@@ -0,0 +1,177 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This code is part of Karafka Pro, a commercial component not licensed under LGPL.
4
+ # See LICENSE for details.
5
+
6
+ module Karafka
7
+ module Pro
8
+ module ScheduledMessages
9
+ # Proxy used to wrap the scheduled messages with the correct dispatch envelope.
10
+ # Each message that goes to the scheduler topic needs to have specific headers and other
11
+ # details that are required by the system so we know how and when to dispatch it.
12
+ #
13
+ # Each message that goes to the proxy topic needs to have a unique key. We inject those
14
+ # automatically unless user provides one in an envelope. Since we want to make sure, that
15
+ # the messages dispatched by the user all go to the same partition (if with same key), we
16
+ # inject a partition_key based on the user key or other details if present. That allows us
17
+ # to make sure, that they will always go to the same partition on our side.
18
+ #
19
+ # This wrapper validates the initial message that user wants to send in the future, as well
20
+ # as the envelope and specific requirements for a message to be send in the future
21
+ module Proxy
22
+ # General WaterDrop message contract. Before we envelop a message, we need to be certain
23
+ # it is correct, hence we use this contract.
24
+ MSG_CONTRACT = ::WaterDrop::Contracts::Message.new(
25
+ # Payload size is a subject to the target producer dispatch validation, so we set it
26
+ # to 100MB basically to ignore it here.
27
+ max_payload_size: 104_857_600
28
+ )
29
+
30
+ # Post-rebind contract to ensure, that user provided all needed details that would allow
31
+ # the system to operate correctly
32
+ POST_CONTRACT = Contracts::Message.new
33
+
34
+ # Attributes used to build a partition key for the schedules topic dispatch of a given
35
+ # message. We use this order as this order describes the priority of usage.
36
+ PARTITION_KEY_BASE_ATTRIBUTES = %i[
37
+ partition
38
+ partition_key
39
+ ].freeze
40
+
41
+ private_constant :MSG_CONTRACT, :POST_CONTRACT, :PARTITION_KEY_BASE_ATTRIBUTES
42
+
43
+ class << self
44
+ # Generates a schedule message envelope wrapping the original dispatch
45
+ #
46
+ # @param message [Hash] message hash of a message that would originally go to WaterDrop
47
+ # producer directly.
48
+ # @param epoch [Integer] time in the future (or now) when dispatch this message in the
49
+ # Unix epoch timestamp
50
+ # @param envelope [Hash] Special details that the envelop needs to have, like a unique
51
+ # key. If unique key is not provided we build a random unique one and use a
52
+ # partition_key based on the original message key (if present) to ensure that all
53
+ # relevant messages are dispatched to the same topic partition.
54
+ # @return [Hash] dispatched message wrapped with an envelope
55
+ #
56
+ # @note This proxy does **not** inject the dispatched messages topic unless provided in
57
+ # the envelope. That's because user can have multiple scheduled messages topics to
58
+ # group outgoing messages, etc.
59
+ def schedule(message:, epoch:, envelope: {})
60
+ # We need to ensure that the message we want to proxy is fully legit. Otherwise, since
61
+ # we envelope details like target topic, we could end up having incorrect data to
62
+ # schedule
63
+ MSG_CONTRACT.validate!(message, WaterDrop::Errors::MessageInvalidError)
64
+
65
+ headers = (message[:headers] || {}).merge(
66
+ 'schedule_schema_version' => ScheduledMessages::SCHEMA_VERSION,
67
+ 'schedule_target_epoch' => epoch.to_i.to_s,
68
+ 'schedule_source_type' => 'schedule'
69
+ )
70
+
71
+ export(headers, message, :topic)
72
+ export(headers, message, :partition)
73
+ export(headers, message, :key)
74
+ export(headers, message, :partition_key)
75
+
76
+ proxy_message = {
77
+ payload: message[:payload],
78
+ headers: headers
79
+ }.merge(envelope)
80
+
81
+ enrich(proxy_message, message)
82
+ validate!(proxy_message)
83
+
84
+ proxy_message
85
+ end
86
+
87
+ # Generates a tombstone message to cancel already scheduled message dispatch
88
+ # @param key [String] key used by the original message as a unique identifier
89
+ # @param envelope [Hash] Special details that can identify the message location like
90
+ # topic and partition (if used) so the cancellation goes to the correct location.
91
+ # @return [Hash] cancellation message
92
+ #
93
+ # @note Technically it is a tombstone but we differentiate just for the sake of ability
94
+ # to debug stuff if needed
95
+ def cancel(key:, envelope: {})
96
+ proxy_message = {
97
+ key: key,
98
+ payload: nil,
99
+ headers: {
100
+ 'schedule_schema_version' => ScheduledMessages::SCHEMA_VERSION,
101
+ 'schedule_source_type' => 'cancel'
102
+ }
103
+ }.merge(envelope)
104
+
105
+ # Ensure user provided envelope is with all expected details
106
+ validate!(proxy_message)
107
+
108
+ proxy_message
109
+ end
110
+
111
+ # Builds tombstone with the dispatched message details. Those details can be used
112
+ # in Web UI, etc when analyzing dispatches.
113
+ # @param message [Karafka::Messages::Message] message we want to tombstone
114
+ # topic and partition (if used) so the cancellation goes to the correct location.
115
+ def tombstone(message:)
116
+ {
117
+ key: message.key,
118
+ payload: nil,
119
+ topic: message.topic,
120
+ partition: message.partition,
121
+ headers: message.raw_headers.merge(
122
+ 'schedule_schema_version' => ScheduledMessages::SCHEMA_VERSION,
123
+ 'schedule_source_type' => 'tombstone',
124
+ 'schedule_source_offset' => message.offset.to_s
125
+ )
126
+ }
127
+ end
128
+
129
+ private
130
+
131
+ # Transfers the message key attributes into headers. Since we need to have our own
132
+ # envelope key and other details, we transfer the original message details into headers
133
+ # so we can re-use them when we dispatch the scheduled messages at an appropriate time
134
+ #
135
+ # @param headers [Hash] envelope headers to which we will add appropriate attribute
136
+ # @param message [Hash] original user message
137
+ # @param attribute [Symbol] attribute we're interested in exporting to headers
138
+ # @note Modifies headers in place
139
+ def export(headers, message, attribute)
140
+ return unless message.key?(attribute)
141
+
142
+ headers["schedule_target_#{attribute}"] = message.fetch(attribute).to_s
143
+ end
144
+
145
+ # Adds the key and (if applicable) partition key to ensure, that related messages that
146
+ # user wants to dispatch in the future, are all in the same topic partition.
147
+ # @param proxy_message [Hash] our message envelope
148
+ # @param message [Hash] user original message
149
+ # @note Modifies `proxy_message` in place
150
+ def enrich(proxy_message, message)
151
+ # If there is an envelope message key already, nothing needed
152
+ return if proxy_message.key?(:key)
153
+
154
+ proxy_message[:key] = "#{message[:topic]}-#{SecureRandom.uuid}"
155
+
156
+ PARTITION_KEY_BASE_ATTRIBUTES.each do |attribute|
157
+ next unless message.key?(attribute)
158
+ # Do not overwrite if explicitely set by the user
159
+ next if proxy_message.key?(attribute)
160
+
161
+ proxy_message[:partition_key] = message.fetch(attribute).to_s
162
+ end
163
+ end
164
+
165
+ # Final validations to make sure all user provided extra data and what we have built
166
+ # complies with our requirements
167
+ # @param proxy_message [Hash] our message envelope
168
+ def validate!(proxy_message)
169
+ POST_CONTRACT.validate!(proxy_message)
170
+ # After proxy specific validations we also ensure, that the final form is correct
171
+ MSG_CONTRACT.validate!(proxy_message, WaterDrop::Errors::MessageInvalidError)
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This code is part of Karafka Pro, a commercial component not licensed under LGPL.
4
+ # See LICENSE for details.
5
+
6
+ module Karafka
7
+ module Pro
8
+ module ScheduledMessages
9
+ # Validator that checks if we can process this scheduled message
10
+ # If we encounter message that has a schema version higher than our process is aware of
11
+ # we raise and error and do not process. This is to make sure we do not deal with messages
12
+ # that are not compatible in case of schema changes.
13
+ module SchemaValidator
14
+ class << self
15
+ # Check if we can work with this schema message and raise error if not.
16
+ #
17
+ # @param message [Karafka::Messages::Message]
18
+ def call(message)
19
+ message_version = message.headers['schedule_schema_version']
20
+
21
+ return if message_version <= ScheduledMessages::SCHEMA_VERSION
22
+
23
+ raise Errors::IncompatibleSchemaError, message_version
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This code is part of Karafka Pro, a commercial component not licensed under LGPL.
4
+ # See LICENSE for details.
5
+
6
+ module Karafka
7
+ module Pro
8
+ module ScheduledMessages
9
+ # Serializers used to build payloads (if applicable) for dispatch
10
+ # @note We only deal with states payload. Other payloads are not ours but end users.
11
+ class Serializer
12
+ include ::Karafka::Core::Helpers::Time
13
+
14
+ # @param tracker [Tracker] tracker based on which we build the state
15
+ # @return [String] compressed payload with the state details
16
+ def state(tracker)
17
+ data = {
18
+ schema_version: ScheduledMessages::STATES_SCHEMA_VERSION,
19
+ dispatched_at: float_now,
20
+ state: tracker.state,
21
+ daily: tracker.daily
22
+ }
23
+
24
+ compress(
25
+ serialize(data)
26
+ )
27
+ end
28
+
29
+ private
30
+
31
+ # @param hash [Hash] hash to cast to json
32
+ # @return [String] json hash
33
+ def serialize(hash)
34
+ hash.to_json
35
+ end
36
+
37
+ # Compresses the provided data
38
+ #
39
+ # @param data [String] data to compress
40
+ # @return [String] compressed data
41
+ def compress(data)
42
+ Zlib::Deflate.deflate(data)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This code is part of Karafka Pro, a commercial component not licensed under LGPL.
4
+ # See LICENSE for details.
5
+
6
+ module Karafka
7
+ module Pro
8
+ module ScheduledMessages
9
+ # Setup and config related recurring tasks components
10
+ module Setup
11
+ # Config for recurring tasks
12
+ class Config
13
+ extend ::Karafka::Core::Configurable
14
+
15
+ setting(:consumer_class, default: Consumer)
16
+ setting(:group_id, default: 'karafka_scheduled_messages')
17
+
18
+ # By default we will run the scheduling every 15 seconds since we provide a minute-based
19
+ # precision. Can be increased when having dedicated processes to run this. Lower values
20
+ # mean more frequent execution on low-throughput topics meaning higher precision.
21
+ setting(:interval, default: 15_000)
22
+
23
+ # How many messages should be flush in one go from the dispatcher at most. If we have
24
+ # more messages to dispatch, they will be chunked.
25
+ setting(:flush_batch_size, default: 1_000)
26
+
27
+ # Producer to use. By default uses default Karafka producer.
28
+ setting(
29
+ :producer,
30
+ constructor: -> { ::Karafka.producer },
31
+ lazy: true
32
+ )
33
+
34
+ # Class we use to dispatch messages
35
+ setting(:dispatcher_class, default: Dispatcher)
36
+
37
+ # Postfix for the states topic to build the states based on the group name + postfix
38
+ setting(:states_postfix, default: '_states')
39
+
40
+ setting(:deserializers) do
41
+ # Deserializer for schedules messages to convert epochs
42
+ setting(:headers, default: Deserializers::Headers.new)
43
+ # Only applicable to states
44
+ setting(:payload, default: Deserializers::Payload.new)
45
+ end
46
+
47
+ configure
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This code is part of Karafka Pro, a commercial component not licensed under LGPL.
4
+ # See LICENSE for details.
5
+
6
+ module Karafka
7
+ module Pro
8
+ module ScheduledMessages
9
+ # Represents the loading/bootstrapping state of the given topic partition
10
+ #
11
+ # Bootstrapping can be in the following states:
12
+ # - fresh - when we got an assignment but we did not load the schedule yet
13
+ # - loading - when we are in the process of bootstrapping the daily state and we consume
14
+ # historical messages to build the needed schedules.
15
+ # - loaded - state in which we finished loading all the schedules and we can dispatch
16
+ # messages when the time comes and we can process real-time incoming schedules and
17
+ # changes to schedules as they appear in the stream.
18
+ class State
19
+ # @param loaded [nil, false, true] is the state loaded or not yet. `nil` indicates, it is
20
+ # a fresh, pre-seek state.
21
+ def initialize(loaded = nil)
22
+ @loaded = loaded
23
+ end
24
+
25
+ # @return [Boolean] are we in a fresh, pre-bootstrap state
26
+ def fresh?
27
+ @loaded.nil?
28
+ end
29
+
30
+ # Marks the current state as fully loaded
31
+ def loaded!
32
+ @loaded = true
33
+ end
34
+
35
+ # @return [Boolean] are we in a loaded state
36
+ def loaded?
37
+ @loaded == true
38
+ end
39
+
40
+ # @return [String] current state string representation
41
+ def to_s
42
+ case @loaded
43
+ when nil
44
+ 'fresh'
45
+ when false
46
+ 'loading'
47
+ when true
48
+ 'loaded'
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This code is part of Karafka Pro, a commercial component not licensed under LGPL.
4
+ # See LICENSE for details.
5
+
6
+ module Karafka
7
+ module Pro
8
+ module ScheduledMessages
9
+ # Tracks basic state and metrics about schedules to be dispatched
10
+ #
11
+ # It provides accurate today dispatch taken from daily buffer and estimates for future days
12
+ class Tracker
13
+ # @return [Hash<String, Integer>]
14
+ attr_reader :daily
15
+
16
+ # @return [String] current state
17
+ attr_accessor :state
18
+
19
+ def initialize
20
+ @daily = Hash.new { |h, k| h[k] = 0 }
21
+ @created_at = Time.now.to_i
22
+ end
23
+
24
+ # Accurate (because coming from daily buffer) number of things to schedule
25
+ #
26
+ # @param sum [Integer]
27
+ def today=(sum)
28
+ @daily[epoch_to_date(@created_at)] = sum
29
+ end
30
+
31
+ # Tracks message dispatch
32
+ #
33
+ # It is only relevant for future days as for today we use accurate metrics from the daily
34
+ # buffer
35
+ #
36
+ # @param message [Karafka::Messages::Message] schedule message. Should **not** be a
37
+ # tombstone message. Tombstone messages cancellations are not tracked because it would
38
+ # drastically increase complexity. For given day we use the accurate counter and for
39
+ # future days we use estimates.
40
+ def track(message)
41
+ epoch = message.headers['schedule_target_epoch']
42
+
43
+ @daily[epoch_to_date(epoch)] += 1
44
+ end
45
+
46
+ private
47
+
48
+ # @param epoch [Integer] epoch time
49
+ # @return [String] epoch matching date
50
+ def epoch_to_date(epoch)
51
+ Time.at(epoch).utc.to_date.to_s
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This code is part of Karafka Pro, a commercial component not licensed under LGPL.
4
+ # See LICENSE for details.
5
+
6
+ module Karafka
7
+ module Pro
8
+ # This feature allows for proxying messages via a special topic that can dispatch them
9
+ # at a later time, hence scheduled messages. Such messages need to have a special format
10
+ # but aside from that they are regular Kafka messages.
11
+ #
12
+ # This work was conceptually inspired by the Go scheduler:
13
+ # https://github.com/etf1/kafka-message-scheduler though I did not look at the implementation
14
+ # itself. Just the concept of daily in-memory scheduling.
15
+ module ScheduledMessages
16
+ # Version of the schema we use for envelops in scheduled messages.
17
+ # We use it to detect any potential upgrades similar to other components of Karafka and to
18
+ # stop processing of incompatible versions
19
+ SCHEMA_VERSION = '1.0.0'
20
+
21
+ # Version of the states schema. Used to publish per partition simple aggregated metrics
22
+ # that can be used for schedules reporting
23
+ STATES_SCHEMA_VERSION = '1.0.0'
24
+
25
+ class << self
26
+ # Runs the `Proxy.call`
27
+ # @param kwargs [Hash] things requested by the proxy
28
+ # @return [Hash] message wrapped with the scheduled message envelope
29
+ def schedule(**kwargs)
30
+ Proxy.schedule(**kwargs)
31
+ end
32
+
33
+ # Generates a tombstone message to cancel given dispatch (if not yet happened)
34
+ # @param kwargs [Hash] things requested by the proxy
35
+ # @return [Hash] tombstone cancelling message
36
+ def cancel(**kwargs)
37
+ Proxy.cancel(**kwargs)
38
+ end
39
+
40
+ # Below are private APIs
41
+
42
+ # Sets up additional config scope, validations and other things
43
+ #
44
+ # @param config [Karafka::Core::Configurable::Node] root node config
45
+ def pre_setup(config)
46
+ # Expand the config with this feature specific stuff
47
+ config.instance_eval do
48
+ setting(:scheduled_messages, default: Setup::Config.config)
49
+ end
50
+ end
51
+
52
+ # @param config [Karafka::Core::Configurable::Node] root node config
53
+ def post_setup(config)
54
+ RecurringTasks::Contracts::Config.new.validate!(config.to_h)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,15 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This Karafka component is a Pro component under a commercial license.
4
- # This Karafka component is NOT licensed under LGPL.
5
- #
6
- # All of the commercial components are present in the lib/karafka/pro directory of this
7
- # repository and their usage requires commercial license agreement.
8
- #
9
- # Karafka has also commercial-friendly license, commercial support and commercial components.
10
- #
11
- # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
- # your code to Maciej Mensfeld.
3
+ # This code is part of Karafka Pro, a commercial component not licensed under LGPL.
4
+ # See LICENSE for details.
13
5
 
14
6
  module Karafka
15
7
  module Pro
@@ -15,6 +15,13 @@ module Karafka
15
15
 
16
16
  attr_reader :pause_tracker, :seek_offset, :topic, :partition
17
17
 
18
+ # This can be set directly on the listener because it can be triggered on first run without
19
+ # any messages
20
+ attr_accessor :eofed
21
+
22
+ # Last polled at time set based on the incoming last poll time
23
+ attr_accessor :last_polled_at
24
+
18
25
  def_delegators :@pause_tracker, :attempt, :paused?
19
26
 
20
27
  # @param topic [Karafka::Routing::Topic]
@@ -32,7 +39,9 @@ module Karafka
32
39
  @mutex = Mutex.new
33
40
  @marked = false
34
41
  @failure = false
42
+ @eofed = false
35
43
  @changed_at = monotonic_now
44
+ @last_polled_at = @changed_at
36
45
  end
37
46
 
38
47
  # Starts the coordinator for given consumption jobs
@@ -146,6 +155,11 @@ module Karafka
146
155
  @revoked
147
156
  end
148
157
 
158
+ # @return [Boolean] did we reach end of partition when polling data
159
+ def eofed?
160
+ @eofed
161
+ end
162
+
149
163
  # @return [Boolean] was the new seek offset assigned at least once. This is needed because
150
164
  # by default we assign seek offset of a first message ever, however this is insufficient
151
165
  # for DLQ in a scenario where the first message would be broken. We would never move
@@ -81,6 +81,13 @@ module Karafka
81
81
  consumer.on_before_consume
82
82
  end
83
83
 
84
+ # Runs the wrap/around execution context appropriate for a given action
85
+ # @param action [Symbol] action execution wrapped with our block
86
+ # @param block [Proc] execution context
87
+ def wrap(action, &block)
88
+ consumer.on_wrap(action, &block)
89
+ end
90
+
84
91
  # Runs consumer data processing against given batch and handles failures and errors.
85
92
  def consume
86
93
  # We run the consumer client logic...
@@ -104,6 +111,18 @@ module Karafka
104
111
  consumer.on_idle
105
112
  end
106
113
 
114
+ # Runs the code needed before eofed work is scheduled
115
+ def before_schedule_eofed
116
+ consumer.on_before_schedule_eofed
117
+ end
118
+
119
+ # Runs consumed eofed operation.
120
+ # This may run even when there were no messages received prior. This will however not
121
+ # run when eof is received together with messages as in such case `#consume` will run
122
+ def eofed
123
+ consumer.on_eofed
124
+ end
125
+
107
126
  # Runs code needed before revoked job is scheduled
108
127
  def before_schedule_revoked
109
128
  consumer.on_before_schedule_revoked if @consumer
@@ -162,13 +181,22 @@ module Karafka
162
181
  expansions.each { |expansion| consumer.singleton_class.include(expansion) }
163
182
 
164
183
  consumer.client = @client
165
- consumer.producer = ::Karafka::App.producer
166
184
  consumer.coordinator = @coordinator
185
+ # We assign producer only when not available already. It may already be available if
186
+ # user redefined the `#producer` method for example. This can be useful for example when
187
+ # having a multi-cluster setup and using a totally custom producer
188
+ consumer.producer ||= ::Karafka::App.producer
167
189
  # Since we have some message-less flows (idle, etc), we initialize consumer with empty
168
190
  # messages set. In production we have persistent consumers, so this is not a performance
169
191
  # overhead as this will happen only once per consumer lifetime
170
192
  consumer.messages = empty_messages
171
193
 
194
+ # Run the post-initialization hook for users that need to run some actions when consumer
195
+ # is built and ready (all basic state and info).
196
+ # Users should **not** overwrite the `#initialize` because it won't have all the needed
197
+ # data assigned yet.
198
+ consumer.on_initialized
199
+
172
200
  consumer
173
201
  end
174
202
  end
@@ -15,6 +15,11 @@ module Karafka
15
15
 
16
16
  attr_reader :executor
17
17
 
18
+ class << self
19
+ # @return [Symbol] Job matching appropriate action
20
+ attr_accessor :action
21
+ end
22
+
18
23
  # Creates a new job instance
19
24
  def initialize
20
25
  # All jobs are blocking by default and they can release the lock when blocking operations
@@ -23,6 +28,14 @@ module Karafka
23
28
  @status = :pending
24
29
  end
25
30
 
31
+ # Runs the wrap/around job hook within which the rest of the flow happens
32
+ # @param block [Proc] whole user related processing flow
33
+ # @note We inject the action name so user can decide whether to run custom logic on a
34
+ # given action or not.
35
+ def wrap(&block)
36
+ executor.wrap(self.class.action, &block)
37
+ end
38
+
26
39
  # When redefined can run any code prior to the job being scheduled
27
40
  # @note This will run in the listener thread and not in the worker
28
41
  def before_schedule
@@ -9,6 +9,8 @@ module Karafka
9
9
  # @return [Array<Rdkafka::Consumer::Message>] array with messages
10
10
  attr_reader :messages
11
11
 
12
+ self.action = :consume
13
+
12
14
  # @param executor [Karafka::Processing::Executor] executor that is suppose to run a given
13
15
  # job
14
16
  # @param messages [Karafka::Messages::Messages] karafka messages batch
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Processing
5
+ module Jobs
6
+ # Job that runs the eofed operation when we receive eof without messages alongside.
7
+ class Eofed < Base
8
+ self.action = :eofed
9
+
10
+ # @param executor [Karafka::Processing::Executor] executor that is suppose to run the job
11
+ # @return [Eofed]
12
+ def initialize(executor)
13
+ @executor = executor
14
+ super()
15
+ end
16
+
17
+ # Runs code prior to scheduling this eofed job
18
+ def before_schedule
19
+ executor.before_schedule_eofed
20
+ end
21
+
22
+ # Runs the eofed job via an executor.
23
+ def call
24
+ executor.eofed
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -6,6 +6,8 @@ module Karafka
6
6
  # Type of job that we may use to run some extra handling that happens without the user
7
7
  # related lifecycle event like consumption, revocation, etc.
8
8
  class Idle < Base
9
+ self.action = :idle
10
+
9
11
  # @param executor [Karafka::Processing::Executor] executor that is suppose to run a given
10
12
  # job on an active consumer
11
13
  # @return [Shutdown]
@@ -5,6 +5,8 @@ module Karafka
5
5
  module Jobs
6
6
  # Job that runs the revoked operation when we loose a partition on a consumer that lost it.
7
7
  class Revoked < Base
8
+ self.action = :revoked
9
+
8
10
  # @param executor [Karafka::Processing::Executor] executor that is suppose to run the job
9
11
  # @return [Revoked]
10
12
  def initialize(executor)