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
@@ -23,11 +23,16 @@ module Karafka
23
23
  # @param action_name [String] action name. For processing this should be equal to
24
24
  # consumer class + method name
25
25
  def start_transaction(action_name)
26
- transaction = ::Appsignal::Transaction.create(
27
- SecureRandom.uuid,
28
- namespace_name,
29
- ::Appsignal::Transaction::GenericRequest.new({})
30
- )
26
+ transaction =
27
+ if version_4_or_newer?
28
+ ::Appsignal::Transaction.create(namespace_name)
29
+ else
30
+ ::Appsignal::Transaction.create(
31
+ SecureRandom.uuid,
32
+ namespace_name,
33
+ ::Appsignal::Transaction::GenericRequest.new({})
34
+ )
35
+ end
31
36
 
32
37
  transaction.set_action_if_nil(action_name)
33
38
  end
@@ -45,10 +50,10 @@ module Karafka
45
50
  def metadata=(metadata_hash)
46
51
  return unless transaction?
47
52
 
48
- transaction = ::Appsignal::Transaction.current
53
+ current_transaction = transaction
49
54
 
50
55
  stringify_hash(metadata_hash).each do |key, value|
51
- transaction.set_metadata(key, value)
56
+ current_transaction.set_metadata(key, value)
52
57
  end
53
58
  end
54
59
 
@@ -78,15 +83,20 @@ module Karafka
78
83
  )
79
84
  end
80
85
 
81
- # Sends the error that occurred to Appsignal
86
+ # Report the error that occurred to Appsignal
82
87
  #
83
88
  # @param error [Object] error we want to ship to Appsignal
84
- def send_error(error)
89
+ def report_error(error)
90
+ if ::Appsignal.respond_to?(:report_error)
91
+ # This helper will always report the error
92
+ ::Appsignal.report_error(error) do |transaction|
93
+ transaction.set_namespace(namespace_name)
94
+ end
85
95
  # If we have an active transaction we should use it instead of creating a generic one
86
96
  # That way proper namespace and other data may be transferred
87
97
  #
88
98
  # In case there is no transaction, a new generic background job one will be used
89
- if transaction?
99
+ elsif transaction?
90
100
  transaction.set_error(error)
91
101
  else
92
102
  ::Appsignal.send_error(error) do |transaction|
@@ -99,7 +109,11 @@ module Karafka
99
109
  # @param name [Symbol] probe name
100
110
  # @param probe [Proc] code to run every minute
101
111
  def register_probe(name, probe)
102
- ::Appsignal::Minutely.probes.register(name, probe)
112
+ if ::Appsignal::Probes.respond_to?(:register)
113
+ ::Appsignal::Probes.register(name, probe)
114
+ else
115
+ ::Appsignal::Minutely.probes.register(name, probe)
116
+ end
103
117
  end
104
118
 
105
119
  private
@@ -129,6 +143,13 @@ module Karafka
129
143
  def namespace_name
130
144
  @namespace_name ||= ::Appsignal::Transaction::BACKGROUND_JOB
131
145
  end
146
+
147
+ # @return [Boolean] is this v4+ version of Appsignal gem or older. Used for backwards
148
+ # compatibility checks.
149
+ def version_4_or_newer?
150
+ @version_4_or_newer ||=
151
+ Gem::Version.new(::Appsignal::VERSION) >= Gem::Version.new('4.0.0')
152
+ end
132
153
  end
133
154
  end
134
155
  end
@@ -21,7 +21,7 @@ module Karafka
21
21
  #
22
22
  # @param event [Karafka::Core::Monitoring::Event]
23
23
  def on_error_occurred(event)
24
- client.send_error(event[:error])
24
+ client.report_error(event[:error])
25
25
  end
26
26
  end
27
27
  end
@@ -48,6 +48,7 @@ module Karafka
48
48
  consumer.revoked.error
49
49
  consumer.shutdown.error
50
50
  consumer.tick.error
51
+ consumer.eofed.error
51
52
  ].freeze
52
53
 
53
54
  private_constant :USER_CONSUMER_ERROR_TYPES
@@ -107,7 +108,8 @@ module Karafka
107
108
  [
108
109
  %i[revoke revoked revoked],
109
110
  %i[shutting_down shutdown shutdown],
110
- %i[tick ticked tick]
111
+ %i[tick ticked tick],
112
+ %i[eof eofed eofed]
111
113
  ].each do |before, after, name|
112
114
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
113
115
  # Keeps track of user code execution
@@ -35,6 +35,7 @@ module Karafka
35
35
  def initialize(&block)
36
36
  configure
37
37
  setup(&block) if block
38
+ @job_types_cache = {}
38
39
  end
39
40
 
40
41
  # @param block [Proc] configuration block
@@ -51,28 +52,11 @@ module Karafka
51
52
  push_tags
52
53
 
53
54
  job = event[:job]
54
- job_type = job.class.to_s.split('::').last
55
+ job_type = fetch_job_type(job.class)
55
56
  consumer = job.executor.topic.consumer
56
57
  topic = job.executor.topic.name
57
58
 
58
- action = case job_type
59
- when 'Periodic'
60
- 'tick'
61
- when 'PeriodicNonBlocking'
62
- 'tick'
63
- when 'Shutdown'
64
- 'shutdown'
65
- when 'Revoked'
66
- 'revoked'
67
- when 'RevokedNonBlocking'
68
- 'revoked'
69
- when 'Idle'
70
- 'idle'
71
- else
72
- 'consume'
73
- end
74
-
75
- current_span.resource = "#{consumer}##{action}"
59
+ current_span.resource = "#{consumer}##{job.class.action}"
76
60
  info "[#{job.id}] #{job_type} job for #{consumer} on #{topic} started"
77
61
 
78
62
  pop_tags
@@ -121,6 +105,8 @@ module Karafka
121
105
  error "Consumer on shutdown failed due to an error: #{error}"
122
106
  when 'consumer.tick.error'
123
107
  error "Consumer tick failed due to an error: #{error}"
108
+ when 'consumer.eofed.error'
109
+ error "Consumer eofed failed due to an error: #{error}"
124
110
  when 'worker.process.error'
125
111
  fatal "Worker processing failed due to an error: #{error}"
126
112
  when 'connection.listener.fetch_loop.error'
@@ -169,6 +155,18 @@ module Karafka
169
155
 
170
156
  Karafka.logger.pop_tags
171
157
  end
158
+
159
+ private
160
+
161
+ # Takes the job class and extracts the job type.
162
+ # @param job_class [Class] job class
163
+ # @return [String]
164
+ # @note It does not have to be thread-safe despite running in multiple threads because
165
+ # the assignment race condition is irrelevant here since the same value will be
166
+ # assigned.
167
+ def fetch_job_type(job_class)
168
+ @job_types_cache[job_class] ||= job_class.to_s.split('::').last
169
+ end
172
170
  end
173
171
  end
174
172
  end
@@ -82,10 +82,11 @@ module Karafka
82
82
  statistics = event[:statistics]
83
83
  consumer_group_id = event[:consumer_group_id]
84
84
 
85
- base_tags = default_tags + ["consumer_group:#{consumer_group_id}"]
85
+ tags = ["consumer_group:#{consumer_group_id}"]
86
+ tags.concat(default_tags)
86
87
 
87
88
  rd_kafka_metrics.each do |metric|
88
- report_metric(metric, statistics, base_tags)
89
+ report_metric(metric, statistics, tags)
89
90
  end
90
91
  end
91
92
 
@@ -93,13 +94,14 @@ module Karafka
93
94
  #
94
95
  # @param event [Karafka::Core::Monitoring::Event]
95
96
  def on_error_occurred(event)
96
- extra_tags = ["type:#{event[:type]}"]
97
+ tags = ["type:#{event[:type]}"]
98
+ tags.concat(default_tags)
97
99
 
98
100
  if event.payload[:caller].respond_to?(:messages)
99
- extra_tags += consumer_tags(event.payload[:caller])
101
+ tags.concat(consumer_tags(event.payload[:caller]))
100
102
  end
101
103
 
102
- count('error_occurred', 1, tags: default_tags + extra_tags)
104
+ count('error_occurred', 1, tags: tags)
103
105
  end
104
106
 
105
107
  # Reports how many messages we've polled and how much time did we spend on it
@@ -111,10 +113,11 @@ module Karafka
111
113
 
112
114
  consumer_group_id = event[:subscription_group].consumer_group.id
113
115
 
114
- extra_tags = ["consumer_group:#{consumer_group_id}"]
116
+ tags = ["consumer_group:#{consumer_group_id}"]
117
+ tags.concat(default_tags)
115
118
 
116
- histogram('listener.polling.time_taken', time_taken, tags: default_tags + extra_tags)
117
- histogram('listener.polling.messages', messages_count, tags: default_tags + extra_tags)
119
+ histogram('listener.polling.time_taken', time_taken, tags: tags)
120
+ histogram('listener.polling.messages', messages_count, tags: tags)
118
121
  end
119
122
 
120
123
  # Here we report majority of things related to processing as we have access to the
@@ -125,7 +128,8 @@ module Karafka
125
128
  messages = consumer.messages
126
129
  metadata = messages.metadata
127
130
 
128
- tags = default_tags + consumer_tags(consumer)
131
+ tags = consumer_tags(consumer)
132
+ tags.concat(default_tags)
129
133
 
130
134
  count('consumer.messages', messages.count, tags: tags)
131
135
  count('consumer.batches', 1, tags: tags)
@@ -146,7 +150,8 @@ module Karafka
146
150
  #
147
151
  # @param event [Karafka::Core::Monitoring::Event]
148
152
  def on_consumer_#{after}(event)
149
- tags = default_tags + consumer_tags(event.payload[:caller])
153
+ tags = consumer_tags(event.payload[:caller])
154
+ tags.concat(default_tags)
150
155
 
151
156
  count('consumer.#{name}', 1, tags: tags)
152
157
  end
@@ -158,9 +163,10 @@ module Karafka
158
163
  def on_worker_process(event)
159
164
  jq_stats = event[:jobs_queue].statistics
160
165
 
161
- gauge('worker.total_threads', Karafka::App.config.concurrency, tags: default_tags)
162
- histogram('worker.processing', jq_stats[:busy], tags: default_tags)
163
- histogram('worker.enqueued_jobs', jq_stats[:enqueued], tags: default_tags)
166
+ tags = default_tags
167
+ gauge('worker.total_threads', Karafka::App.config.concurrency, tags: tags)
168
+ histogram('worker.processing', jq_stats[:busy], tags: tags)
169
+ histogram('worker.enqueued_jobs', jq_stats[:enqueued], tags: tags)
164
170
  end
165
171
 
166
172
  # We report this metric before and after processing for higher accuracy
@@ -240,11 +246,14 @@ module Karafka
240
246
  # node ids
241
247
  next if broker_statistics['nodeid'] == -1
242
248
 
249
+ tags = ["broker:#{broker_statistics['nodename']}"]
250
+ tags.concat(base_tags)
251
+
243
252
  public_send(
244
253
  metric.type,
245
254
  metric.name,
246
255
  broker_statistics.dig(*metric.key_location),
247
- tags: base_tags + ["broker:#{broker_statistics['nodename']}"]
256
+ tags: tags
248
257
  )
249
258
  end
250
259
  when :topics
@@ -259,14 +268,14 @@ module Karafka
259
268
  next if partition_statistics['fetch_state'] == 'stopped'
260
269
  next if partition_statistics['fetch_state'] == 'none'
261
270
 
271
+ tags = ["topic:#{topic_name}", "partition:#{partition_name}"]
272
+ tags.concat(base_tags)
273
+
262
274
  public_send(
263
275
  metric.type,
264
276
  metric.name,
265
277
  partition_statistics.dig(*metric.key_location),
266
- tags: base_tags + [
267
- "topic:#{topic_name}",
268
- "partition:#{partition_name}"
269
- ]
278
+ tags: tags
270
279
  )
271
280
  end
272
281
  end
@@ -29,13 +29,13 @@ module Karafka
29
29
  @port = port
30
30
  end
31
31
 
32
- private
33
-
34
32
  # @return [Boolean] true if all good, false if we should tell k8s to kill this process
35
33
  def healthy?
36
34
  raise NotImplementedError, 'Implement in a subclass'
37
35
  end
38
36
 
37
+ private
38
+
39
39
  # Responds to a HTTP request with the process liveness status
40
40
  def respond
41
41
  client = @server.accept
@@ -26,6 +26,19 @@ module Karafka
26
26
  #
27
27
  # @note Please use `Kubernetes::SwarmLivenessListener` when operating in the swarm mode
28
28
  class LivenessListener < BaseListener
29
+ # When any of those occurs, it means something went wrong in a way that cannot be
30
+ # recovered. In such cases we should report that the consumer process is not healthy.
31
+ # - `fenced` - This instance has been fenced by a newer instance and will not do any
32
+ # processing at all never. Fencing most of the time means the instance.group.id has
33
+ # been reused without properly terminating the previous consumer process first
34
+ # - `fatal` - any fatal error that halts the processing forever
35
+ UNRECOVERABLE_RDKAFKA_ERRORS = [
36
+ :fenced, # -144
37
+ :fatal # -150
38
+ ].freeze
39
+
40
+ private_constant :UNRECOVERABLE_RDKAFKA_ERRORS
41
+
29
42
  # @param hostname [String, nil] hostname or nil to bind on all
30
43
  # @param port [Integer] TCP port on which we want to run our HTTP status server
31
44
  # @param consuming_ttl [Integer] time in ms after which we consider consumption hanging.
@@ -40,6 +53,11 @@ module Karafka
40
53
  consuming_ttl: 5 * 60 * 1_000,
41
54
  polling_ttl: 5 * 60 * 1_000
42
55
  )
56
+ # If this is set to true, it indicates unrecoverable error like fencing
57
+ # While fencing can be partial (for one of the SGs), we still should consider this
58
+ # as an undesired state for the whole process because it halts processing in a
59
+ # non-recoverable manner forever
60
+ @unrecoverable = false
43
61
  @polling_ttl = polling_ttl
44
62
  @consuming_ttl = consuming_ttl
45
63
  @mutex = Mutex.new
@@ -86,10 +104,19 @@ module Karafka
86
104
  RUBY
87
105
  end
88
106
 
89
- # @param _event [Karafka::Core::Monitoring::Event]
90
- def on_error_occurred(_event)
107
+ # @param event [Karafka::Core::Monitoring::Event]
108
+ def on_error_occurred(event)
91
109
  clear_consumption_tick
92
110
  clear_polling_tick
111
+
112
+ error = event[:error]
113
+
114
+ # We are only interested in the rdkafka errors
115
+ return unless error.is_a?(Rdkafka::RdkafkaError)
116
+ # We mark as unrecoverable only on certain errors that will not be fixed by retrying
117
+ return unless UNRECOVERABLE_RDKAFKA_ERRORS.include?(error.code)
118
+
119
+ @unrecoverable = true
93
120
  end
94
121
 
95
122
  # Deregister the polling tracker for given listener
@@ -112,6 +139,18 @@ module Karafka
112
139
  clear_polling_tick
113
140
  end
114
141
 
142
+ # Did we exceed any of the ttls
143
+ # @return [String] 204 string if ok, 500 otherwise
144
+ def healthy?
145
+ time = monotonic_now
146
+
147
+ return false if @unrecoverable
148
+ return false if @pollings.values.any? { |tick| (time - tick) > @polling_ttl }
149
+ return false if @consumptions.values.any? { |tick| (time - tick) > @consuming_ttl }
150
+
151
+ true
152
+ end
153
+
115
154
  private
116
155
 
117
156
  # Wraps the logic with a mutex
@@ -152,17 +191,6 @@ module Karafka
152
191
  @consumptions.delete(thread_id)
153
192
  end
154
193
  end
155
-
156
- # Did we exceed any of the ttls
157
- # @return [String] 204 string if ok, 500 otherwise
158
- def healthy?
159
- time = monotonic_now
160
-
161
- return false if @pollings.values.any? { |tick| (time - tick) > @polling_ttl }
162
- return false if @consumptions.values.any? { |tick| (time - tick) > @consuming_ttl }
163
-
164
- true
165
- end
166
194
  end
167
195
  end
168
196
  end
@@ -8,15 +8,9 @@ module Karafka
8
8
  # heavy-deserialization data without slowing down the whole application.
9
9
  class Message
10
10
  extend Forwardable
11
-
12
- class << self
13
- # @return [Object] general parser
14
- # @note We cache it here for performance reasons. It is 2.5x times faster than getting it
15
- # via the config chain.
16
- def parser
17
- @parser ||= App.config.internal.messages.parser
18
- end
19
- end
11
+ extend Helpers::ConfigImporter.new(
12
+ parser: %i[internal messages parser]
13
+ )
20
14
 
21
15
  attr_reader :metadata
22
16
  # raw payload needs to be mutable as we want to have option to change it in the parser
@@ -51,6 +45,12 @@ module Karafka
51
45
  @deserialized
52
46
  end
53
47
 
48
+ # @return [Boolean] true if the message has a key and raw payload is nil, it is a tombstone
49
+ # event. Otherwise it is not.
50
+ def tombstone?
51
+ !raw_key.nil? && @raw_payload.nil?
52
+ end
53
+
54
54
  private
55
55
 
56
56
  # @return [Object] deserialized data
@@ -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
@@ -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
@@ -28,14 +20,26 @@ module Karafka
28
20
  # each job.
29
21
  partitioner: nil,
30
22
  # Allows for usage of `:key` or `:partition_key`
31
- partition_key_type: :key
23
+ partition_key_type: :key,
24
+ # Topic to where this message should go when using scheduled messages. When defined,
25
+ # it will be used with `enqueue_at`. If not defined it will raise an error.
26
+ scheduled_messages_topic: nil,
27
+ # Allows for setting a callable producer since at the moment of defining the class,
28
+ # variants may not be available
29
+ #
30
+ # We do not initialize it with `-> { ::Karafka.producer }` so we do not have to call it
31
+ # each time for the defaults to preserve CPU cycles.
32
+ #
33
+ # We also do **not** cache the execution of this producer lambda because we want to
34
+ # support job args based producer selection
35
+ producer: nil
32
36
  }.freeze
33
37
 
34
38
  private_constant :DEFAULTS
35
39
 
36
40
  # @param job [ActiveJob::Base] job
37
41
  def dispatch(job)
38
- ::Karafka.producer.public_send(
42
+ producer(job).public_send(
39
43
  fetch_option(job, :dispatch_method, DEFAULTS),
40
44
  dispatch_details(job).merge!(
41
45
  topic: job.queue_name,
@@ -47,27 +51,71 @@ module Karafka
47
51
  # Bulk dispatches multiple jobs using the Rails 7.1+ API
48
52
  # @param jobs [Array<ActiveJob::Base>] jobs we want to dispatch
49
53
  def dispatch_many(jobs)
50
- dispatches = Hash.new { |hash, key| hash[key] = [] }
54
+ # First level is type of dispatch and second is the producer we want to use to dispatch
55
+ dispatches = Hash.new do |hash, key|
56
+ hash[key] = Hash.new do |hash2, key2|
57
+ hash2[key2] = []
58
+ end
59
+ end
51
60
 
52
61
  jobs.each do |job|
53
62
  d_method = fetch_option(job, :dispatch_many_method, DEFAULTS)
63
+ producer = producer(job)
54
64
 
55
- dispatches[d_method] << dispatch_details(job).merge!(
65
+ dispatches[d_method][producer] << dispatch_details(job).merge!(
56
66
  topic: job.queue_name,
57
67
  payload: ::ActiveSupport::JSON.encode(serialize_job(job))
58
68
  )
59
69
  end
60
70
 
61
- dispatches.each do |type, messages|
62
- ::Karafka.producer.public_send(
63
- type,
64
- messages
65
- )
71
+ dispatches.each do |d_method, producers|
72
+ producers.each do |producer, messages|
73
+ producer.public_send(
74
+ d_method,
75
+ messages
76
+ )
77
+ end
66
78
  end
67
79
  end
68
80
 
81
+ # Will enqueue a job to run in the future
82
+ #
83
+ # @param job [Object] job we want to enqueue
84
+ # @param timestamp [Time] time when job should run
85
+ def dispatch_at(job, timestamp)
86
+ target_message = dispatch_details(job).merge!(
87
+ topic: job.queue_name,
88
+ payload: ::ActiveSupport::JSON.encode(serialize_job(job))
89
+ )
90
+
91
+ proxy_message = Pro::ScheduledMessages.schedule(
92
+ message: target_message,
93
+ epoch: timestamp.to_i,
94
+ envelope: {
95
+ # Select the scheduled messages proxy topic
96
+ topic: fetch_option(job, :scheduled_messages_topic, DEFAULTS)
97
+ }
98
+ )
99
+
100
+ producer(job).public_send(
101
+ fetch_option(job, :dispatch_method, DEFAULTS),
102
+ proxy_message
103
+ )
104
+ end
105
+
69
106
  private
70
107
 
108
+ # Selects the producer based on options. If callable `:producer` is defined, it will use
109
+ # it. If not, will just use the `Karafka.producer`.
110
+ #
111
+ # @param job [ActiveJob::Base] job instance
112
+ # @return [WaterDrop::Producer, WaterDrop::Producer::Variant] producer or a variant
113
+ def producer(job)
114
+ dynamic_producer = fetch_option(job, :producer, DEFAULTS)
115
+
116
+ dynamic_producer ? dynamic_producer.call(job) : ::Karafka.producer
117
+ end
118
+
71
119
  # @param job [ActiveJob::Base] job instance
72
120
  # @return [Hash] hash with dispatch details to which we merge topic and payload
73
121
  def dispatch_details(job)
@@ -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
@@ -25,14 +17,24 @@ module Karafka
25
17
  ).fetch('en').fetch('validations').fetch('job_options')
26
18
  end
27
19
 
20
+ optional(:producer) { |val| val.nil? || val.respond_to?(:call) }
28
21
  optional(:partitioner) { |val| val.respond_to?(:call) }
29
22
  optional(:partition_key_type) { |val| %i[key partition_key partition].include?(val) }
23
+
24
+ # Whether this is a legit scheduled messages topic will be validated during the first
25
+ # dispatch, so we do not repeat validations here
26
+ optional(:scheduled_messages_topic) do |val|
27
+ (val.is_a?(String) || val.is_a?(Symbol)) &&
28
+ ::Karafka::Contracts::TOPIC_REGEXP.match?(val.to_s)
29
+ end
30
+
30
31
  optional(:dispatch_method) do |val|
31
32
  %i[
32
33
  produce_async
33
34
  produce_sync
34
35
  ].include?(val)
35
36
  end
37
+
36
38
  optional(:dispatch_many_method) do |val|
37
39
  %i[
38
40
  produce_many_async
@@ -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
@@ -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