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
@@ -120,9 +120,10 @@ module Karafka
120
120
  def build_kafka
121
121
  kafka = Setup::AttributesMap.consumer(@topics.first.kafka.dup)
122
122
 
123
+ inject_defaults(kafka)
123
124
  inject_group_instance_id(kafka)
125
+ inject_client_id(kafka)
124
126
 
125
- kafka[:'client.id'] ||= client_id
126
127
  kafka[:'group.id'] ||= @consumer_group.id
127
128
  kafka[:'auto.offset.reset'] ||= @topics.first.initial_offset
128
129
  # Karafka manages the offsets based on the processing state, thus we do not rely on the
@@ -132,6 +133,33 @@ module Karafka
132
133
  kafka
133
134
  end
134
135
 
136
+ # Injects (if needed) defaults
137
+ #
138
+ # @param kafka [Hash] kafka level config
139
+ def inject_defaults(kafka)
140
+ Setup::DefaultsInjector.consumer(kafka)
141
+ end
142
+
143
+ # Sets (if needed) the client.id attribute
144
+ #
145
+ # @param kafka [Hash] kafka level config
146
+ def inject_client_id(kafka)
147
+ # If client id is set directly on librdkafka level, we do nothing and just go with what
148
+ # end user has configured
149
+ return if kafka.key?(:'client.id')
150
+
151
+ # This mitigates an issue for multiplexing and potentially other cases when running
152
+ # multiple karafka processes on one machine, where librdkafka goes into an infinite
153
+ # loop when using cooperative-sticky and upscaling.
154
+ #
155
+ # @see https://github.com/confluentinc/librdkafka/issues/4783
156
+ kafka[:'client.id'] = if kafka[:'partition.assignment.strategy'] == 'cooperative-sticky'
157
+ "#{client_id}/#{Time.now.to_f}/#{SecureRandom.hex[0..9]}"
158
+ else
159
+ client_id
160
+ end
161
+ end
162
+
135
163
  # If we use static group memberships, there can be a case, where same instance id would
136
164
  # be set on many subscription groups as the group instance id from Karafka perspective is
137
165
  # set per config. Each instance even if they are subscribed to different topics needs to
@@ -54,6 +54,20 @@ module Karafka
54
54
  RUBY
55
55
  end
56
56
 
57
+ # Often users want to have the same basic cluster setup with small setting alterations
58
+ # This method allows us to do so by setting `inherit` to `true`. Whe inherit is enabled,
59
+ # settings will be merged with defaults.
60
+ #
61
+ # @param settings [Hash] kafka scope settings. If `:inherit` key is provided, it will
62
+ # instruct the assignment to merge with root level defaults
63
+ #
64
+ # @note It is set to `false` by default to preserve backwards compatibility
65
+ def kafka=(settings = {})
66
+ inherit = settings.delete(:inherit)
67
+
68
+ @kafka = inherit ? Karafka::App.config.kafka.merge(settings) : settings
69
+ end
70
+
57
71
  # @return [String] name of subscription that will go to librdkafka
58
72
  def subscription_name
59
73
  name
@@ -81,7 +95,16 @@ module Karafka
81
95
  # Allows to disable topic by invoking this method and setting it to `false`.
82
96
  # @param active [Boolean] should this topic be consumed or not
83
97
  def active(active)
84
- @active = active
98
+ # Do not allow for active overrides. Basically if this is set on the topic level, defaults
99
+ # will not overwrite it and this is desired. Otherwise because of the fact that this is
100
+ # not a full feature config but just a flag, default value would always overwrite the
101
+ # per-topic config since defaults application happens after the topic config block
102
+ unless @active_assigned
103
+ @active = active
104
+ @active_assigned = true
105
+ end
106
+
107
+ @active
85
108
  end
86
109
 
87
110
  # @return [Class] consumer class that we should use
@@ -3,17 +3,18 @@
3
3
  module Karafka
4
4
  # Class used to run the Karafka listeners in separate threads
5
5
  class Runner
6
- def initialize
7
- @manager = App.config.internal.connection.manager
8
- @conductor = App.config.internal.connection.conductor
9
- end
6
+ include Helpers::ConfigImporter.new(
7
+ manager: %i[internal connection manager],
8
+ conductor: %i[internal connection conductor],
9
+ jobs_queue_class: %i[internal processing jobs_queue_class]
10
+ )
10
11
 
11
12
  # Starts listening on all the listeners asynchronously and handles the jobs queue closing
12
13
  # after listeners are done with their work.
13
14
  def call
14
15
  # Despite possibility of having several independent listeners, we aim to have one queue for
15
16
  # jobs across and one workers poll for that
16
- jobs_queue = App.config.internal.processing.jobs_queue_class.new
17
+ jobs_queue = jobs_queue_class.new
17
18
 
18
19
  workers = Processing::WorkersBatch.new(jobs_queue)
19
20
  listeners = Connection::ListenersBatch.new(jobs_queue)
@@ -23,7 +24,7 @@ module Karafka
23
24
  Karafka::App.run!
24
25
 
25
26
  # Register all the listeners so they can be started and managed
26
- @manager.register(listeners)
27
+ manager.register(listeners)
27
28
 
28
29
  workers.each_with_index { |worker, i| worker.async_call("karafka.worker##{i}") }
29
30
 
@@ -32,10 +33,10 @@ module Karafka
32
33
  Karafka::Server.listeners = listeners
33
34
  Karafka::Server.jobs_queue = jobs_queue
34
35
 
35
- until @manager.done?
36
- @conductor.wait
36
+ until manager.done?
37
+ conductor.wait
37
38
 
38
- @manager.control
39
+ manager.control
39
40
  end
40
41
 
41
42
  # We close the jobs queue only when no listener threads are working.
@@ -3,6 +3,12 @@
3
3
  module Karafka
4
4
  # Karafka consuming server class
5
5
  class Server
6
+ # How long should we wait on the listeners forceful shutdown when they are stuck beyond the
7
+ # shutdown timeout before forcing a bypass
8
+ FORCEFUL_SHUTDOWN_WAIT = 5
9
+
10
+ private_constant :FORCEFUL_SHUTDOWN_WAIT
11
+
6
12
  class << self
7
13
  # Set of consuming threads. Each consumer thread contains a single consumer
8
14
  attr_accessor :listeners
@@ -13,6 +19,17 @@ module Karafka
13
19
  # Jobs queue
14
20
  attr_accessor :jobs_queue
15
21
 
22
+ # Mode in which the Karafka server is executed. It can be:
23
+ #
24
+ # - :standalone - regular karafka consumer process
25
+ # - :embedded - embedded in a different process and not supervised
26
+ # - :supervisor - swarm supervisor process
27
+ # - :swarm - one of swarm processes
28
+ #
29
+ # Sometimes it is important to know in what mode we operate, especially from UI perspective
30
+ # as not everything is possible when operating in non-standalone mode, etc.
31
+ attr_accessor :execution_mode
32
+
16
33
  # Method which runs app
17
34
  def run
18
35
  self.listeners = []
@@ -105,9 +122,23 @@ module Karafka
105
122
  # We're done waiting, lets kill them!
106
123
  workers.each(&:terminate)
107
124
  listeners.active.each(&:terminate)
125
+
108
126
  # We always need to shutdown clients to make sure we do not force the GC to close consumer.
109
127
  # This can cause memory leaks and crashes.
110
- listeners.each(&:shutdown)
128
+ # We run it in a separate thread in case this would hang and we ignore it after the time
129
+ # we assigned to it and force shutdown as we prefer to stop the process rather than wait
130
+ # indefinitely even with risk of VM crash as this is a last resort.
131
+ Thread.new do
132
+ listeners.each(&:shutdown)
133
+ rescue StandardError => e
134
+ # If anything wrong happened during shutdown, we also want to record it
135
+ Karafka.monitor.instrument(
136
+ 'error.occurred',
137
+ caller: self,
138
+ error: e,
139
+ type: 'app.forceful_stopping.error'
140
+ )
141
+ end.join(FORCEFUL_SHUTDOWN_WAIT)
111
142
 
112
143
  # We also do not forcefully terminate everything when running in the embedded mode,
113
144
  # otherwise we would overwrite the shutdown process of the process that started Karafka
@@ -151,5 +182,10 @@ module Karafka
151
182
  config.internal.process
152
183
  end
153
184
  end
185
+
186
+ # Always start with standalone so there always is a value for the execution mode.
187
+ # This is overwritten quickly during boot, but just in case someone would reach it prior to
188
+ # booting, we want to have the default value.
189
+ self.execution_mode = :standalone
154
190
  end
155
191
  end
@@ -38,6 +38,7 @@ module Karafka
38
38
  default_topic_conf
39
39
  enable.auto.commit
40
40
  enable.auto.offset.store
41
+ enable.metrics.push
41
42
  enable.partition.eof
42
43
  enable.random.seed
43
44
  enable.sasl.oauthbearer.unsecure.jwt
@@ -89,6 +90,8 @@ module Karafka
89
90
  reconnect.backoff.max.ms
90
91
  reconnect.backoff.ms
91
92
  resolve_cb
93
+ retry.backoff.max.ms
94
+ retry.backoff.ms
92
95
  sasl.kerberos.keytab
93
96
  sasl.kerberos.kinit.cmd
94
97
  sasl.kerberos.min.time.before.relogin
@@ -153,6 +156,7 @@ module Karafka
153
156
  # List of rdkafka producer accepted attributes
154
157
  PRODUCER = %i[
155
158
  acks
159
+ allow.auto.create.topics
156
160
  api.version.fallback.ms
157
161
  api.version.request
158
162
  api.version.request.timeout.ms
@@ -181,6 +185,7 @@ module Karafka
181
185
  dr_msg_cb
182
186
  enable.gapless.guarantee
183
187
  enable.idempotence
188
+ enable.metrics.push
184
189
  enable.random.seed
185
190
  enable.sasl.oauthbearer.unsecure.jwt
186
191
  enable.ssl.certificate.verification
@@ -289,7 +294,12 @@ module Karafka
289
294
  ].freeze
290
295
 
291
296
  # Location of the file with rdkafka settings list
292
- SOURCE = 'https://raw.githubusercontent.com/edenhill/librdkafka/master/CONFIGURATION.md'
297
+ SOURCE = <<~SOURCE.delete("\n").gsub(/\s+/, '/')
298
+ https://raw.githubusercontent.com
299
+ confluentinc/librdkafka
300
+ v#{Rdkafka::LIBRDKAFKA_VERSION}
301
+ CONFIGURATION.md
302
+ SOURCE
293
303
 
294
304
  private_constant :SOURCE
295
305
 
@@ -337,9 +347,6 @@ module Karafka
337
347
  end
338
348
  end
339
349
 
340
- # This can be removed when 0.13 librdkafka is released
341
- attributes[:producer].delete_if { |val| val == 'allow.auto.create.topics' }
342
-
343
350
  attributes.transform_values!(&:sort)
344
351
  attributes.each_value { |vals| vals.map!(&:to_sym) }
345
352
  attributes
@@ -14,34 +14,6 @@ module Karafka
14
14
  class Config
15
15
  extend ::Karafka::Core::Configurable
16
16
 
17
- # Defaults for kafka settings, that will be overwritten only if not present already
18
- KAFKA_DEFAULTS = {
19
- # We emit the statistics by default, so all the instrumentation and web-ui work out of
20
- # the box, without requiring users to take any extra actions aside from enabling.
21
- 'statistics.interval.ms': 5_000,
22
- 'client.software.name': 'karafka',
23
- 'client.software.version': [
24
- "v#{Karafka::VERSION}",
25
- "rdkafka-ruby-v#{Rdkafka::VERSION}",
26
- "librdkafka-v#{Rdkafka::LIBRDKAFKA_VERSION}"
27
- ].join('-')
28
- }.freeze
29
-
30
- # Contains settings that should not be used in production but make life easier in dev
31
- KAFKA_DEV_DEFAULTS = {
32
- # Will create non-existing topics automatically.
33
- # Note that the broker needs to be configured with `auto.create.topics.enable=true`
34
- # While it is not recommended in prod, it simplifies work in dev
35
- 'allow.auto.create.topics': 'true',
36
- # We refresh the cluster state often as newly created topics in dev may not be detected
37
- # fast enough. Fast enough means within reasonable time to provide decent user experience
38
- # While it's only a one time thing for new topics, it can still be irritating to have to
39
- # restart the process.
40
- 'topic.metadata.refresh.interval.ms': 5_000
41
- }.freeze
42
-
43
- private_constant :KAFKA_DEFAULTS, :KAFKA_DEV_DEFAULTS
44
-
45
17
  # Available settings
46
18
 
47
19
  # Namespace for Pro version related license management. If you use LGPL, no need to worry
@@ -96,6 +68,11 @@ module Karafka
96
68
  setting :strict_topics_namespacing, default: true
97
69
  # option [String] default consumer group name for implicit routing
98
70
  setting :group_id, default: 'app'
71
+ # option [Boolean] when set to true, it will validate as part of the routing validation, that
72
+ # all topics and DLQ topics (even not active) have the declarative topics definitions.
73
+ # Really useful when you want to ensure that all topics in routing are managed via
74
+ # declaratives.
75
+ setting :strict_declarative_topics, default: false
99
76
 
100
77
  setting :oauth do
101
78
  # option [false, #call] Listener for using oauth bearer. This listener will be able to
@@ -231,6 +208,9 @@ module Karafka
231
208
  setting :manager, default: Connection::Manager.new
232
209
  # Controls frequency of connections management checks
233
210
  setting :conductor, default: Connection::Conductor.new
211
+ # How long should we wait before a critical listener recovery
212
+ # Too short may cause endless rebalance loops
213
+ setting :reset_backoff, default: 60_000
234
214
 
235
215
  # Settings that are altered by our client proxy layer
236
216
  setting :proxy do
@@ -310,6 +290,9 @@ module Karafka
310
290
  setting :expansions_selector, default: Processing::ExpansionsSelector.new
311
291
  # option [Class] executor class
312
292
  setting :executor_class, default: Processing::Executor
293
+ # option worker_job_call_wrapper [Proc, false] callable object that will be used to wrap
294
+ # the worker execution of a job or false if no wrapper needed
295
+ setting :worker_job_call_wrapper, default: false
313
296
  end
314
297
 
315
298
  # Things related to operating on messages
@@ -350,7 +333,6 @@ module Karafka
350
333
  Pro::Loader.pre_setup_all(config) if Karafka.pro?
351
334
 
352
335
  configure(&block)
353
- merge_kafka_defaults!(config)
354
336
 
355
337
  Contracts::Config.new.validate!(config.to_h)
356
338
 
@@ -374,29 +356,6 @@ module Karafka
374
356
 
375
357
  private
376
358
 
377
- # Propagates the kafka setting defaults unless they are already present
378
- # This makes it easier to set some values that users usually don't change but still allows
379
- # them to overwrite the whole hash if they want to
380
- # @param config [Karafka::Core::Configurable::Node] config of this producer
381
- def merge_kafka_defaults!(config)
382
- KAFKA_DEFAULTS.each do |key, value|
383
- next if config.kafka.key?(key)
384
-
385
- config.kafka[key] = value
386
- end
387
-
388
- # Use Karafka client_id as kafka client id if not set
389
- config.kafka[:'client.id'] ||= config.client_id
390
-
391
- return if Karafka::App.env.production?
392
-
393
- KAFKA_DEV_DEFAULTS.each do |key, value|
394
- next if config.kafka.key?(key)
395
-
396
- config.kafka[key] = value
397
- end
398
- end
399
-
400
359
  # Sets up all the components that are based on the user configuration
401
360
  # @note At the moment it is only WaterDrop
402
361
  def configure_components
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Setup
5
+ # Injector that enriches each Kafka cluster with needed defaults. User may use more than one
6
+ # cluster and define them on a per-topic basis. We use this when we build the final config
7
+ # per subscription group.
8
+ module DefaultsInjector
9
+ # Defaults for kafka settings, that will be overwritten only if not present already
10
+ CONSUMER_KAFKA_DEFAULTS = {
11
+ # We emit the statistics by default, so all the instrumentation and web-ui work out of
12
+ # the box, without requiring users to take any extra actions aside from enabling.
13
+ 'statistics.interval.ms': 5_000,
14
+ 'client.software.name': 'karafka',
15
+ # Same as librdkafka default, we inject it nonetheless to have it always available as
16
+ # some features may use this value for computation and it is better to ensure, we do
17
+ # always have it
18
+ 'max.poll.interval.ms': 300_000,
19
+ 'client.software.version': [
20
+ "v#{Karafka::VERSION}",
21
+ "rdkafka-ruby-v#{Rdkafka::VERSION}",
22
+ "librdkafka-v#{Rdkafka::LIBRDKAFKA_VERSION}"
23
+ ].join('-')
24
+ }.freeze
25
+
26
+ # Contains settings that should not be used in production but make life easier in dev
27
+ CONSUMER_KAFKA_DEV_DEFAULTS = {
28
+ # Will create non-existing topics automatically.
29
+ # Note that the broker needs to be configured with `auto.create.topics.enable=true`
30
+ # While it is not recommended in prod, it simplifies work in dev
31
+ 'allow.auto.create.topics': 'true',
32
+ # We refresh the cluster state often as newly created topics in dev may not be detected
33
+ # fast enough. Fast enough means within reasonable time to provide decent user experience
34
+ # While it's only a one time thing for new topics, it can still be irritating to have to
35
+ # restart the process.
36
+ 'topic.metadata.refresh.interval.ms': 5_000
37
+ }.freeze
38
+
39
+ private_constant :CONSUMER_KAFKA_DEFAULTS, :CONSUMER_KAFKA_DEV_DEFAULTS
40
+
41
+ class << self
42
+ # Propagates the kafka setting defaults unless they are already present for consumer config
43
+ # This makes it easier to set some values that users usually don't change but still allows
44
+ # them to overwrite the whole hash if they want to
45
+ # @param kafka_config [Hash] kafka scoped config
46
+ def consumer(kafka_config)
47
+ CONSUMER_KAFKA_DEFAULTS.each do |key, value|
48
+ next if kafka_config.key?(key)
49
+
50
+ kafka_config[key] = value
51
+ end
52
+
53
+ return if Karafka::App.env.production?
54
+
55
+ CONSUMER_KAFKA_DEV_DEFAULTS.each do |key, value|
56
+ next if kafka_config.key?(key)
57
+
58
+ kafka_config[key] = value
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -68,6 +68,8 @@ module Karafka
68
68
  monitor.subscribe(liveness_listener)
69
69
  monitor.instrument('swarm.node.after_fork', caller: self)
70
70
 
71
+ Karafka::Process.tags.add(:execution_mode, 'mode:swarm')
72
+ Server.execution_mode = :swarm
71
73
  Server.run
72
74
 
73
75
  @writer.close
@@ -20,7 +20,9 @@ module Karafka
20
20
  shutdown_timeout: %i[shutdown_timeout],
21
21
  supervision_sleep: %i[internal supervision_sleep],
22
22
  forceful_exit_code: %i[internal forceful_exit_code],
23
- process: %i[internal process]
23
+ process: %i[internal process],
24
+ cli_contract: %i[internal cli contract],
25
+ activity_manager: %i[internal routing activity_manager]
24
26
  )
25
27
 
26
28
  # How long extra should we wait on shutdown before forceful termination
@@ -39,6 +41,9 @@ module Karafka
39
41
 
40
42
  # Creates needed number of forks, installs signals and starts supervision
41
43
  def run
44
+ # Validate the CLI provided options the same way as we do for the regular server
45
+ cli_contract.validate!(activity_manager.to_h)
46
+
42
47
  # Close producer just in case. While it should not be used, we do not want even a
43
48
  # theoretical case since librdkafka is not thread-safe.
44
49
  # We close it prior to forking just to make sure, there is no issue with initialized
@@ -67,7 +72,11 @@ module Karafka
67
72
  lock
68
73
  control
69
74
  end
70
- # If anything went wrong, signal this and die
75
+
76
+ # If the cli contract validation failed reraise immediately and stop the process
77
+ rescue Karafka::Errors::InvalidConfigurationError => e
78
+ raise e
79
+ # If anything went wrong during supervision, signal this and die
71
80
  # Supervisor is meant to be thin and not cause any issues. If you encounter this case
72
81
  # please report it as it should be considered critical
73
82
  rescue StandardError => e
@@ -59,7 +59,7 @@ class KarafkaApp < Karafka::App
59
59
  )
60
60
  )
61
61
 
62
- # You can subscribe to all consumer related errors and record/track then that way
62
+ # You can subscribe to all consumer related errors and record/track them that way
63
63
  #
64
64
  # Karafka.monitor.subscribe 'error.occurred' do |event|
65
65
  # type = event[:type]
@@ -68,7 +68,7 @@ class KarafkaApp < Karafka::App
68
68
  # ErrorTracker.send_error(error, type, details)
69
69
  # end
70
70
 
71
- # You can subscribe to all producer related errors and record/track then that way
71
+ # You can subscribe to all producer related errors and record/track them that way
72
72
  # Please note, that producer and consumer have their own notifications pipeline so you need to
73
73
  # setup error tracking independently for each of them
74
74
  #
@@ -3,5 +3,5 @@
3
3
  # Main module namespace
4
4
  module Karafka
5
5
  # Current Karafka version
6
- VERSION = '2.4.0'
6
+ VERSION = '2.4.18'
7
7
  end
data/lib/karafka.rb CHANGED
@@ -49,17 +49,35 @@ module Karafka
49
49
  @monitor ||= App.config.monitor
50
50
  end
51
51
 
52
- # @return [String] root path of this gem
52
+ # @return [Pathname] root path of this gem
53
53
  def gem_root
54
54
  Pathname.new(File.expand_path('..', __dir__))
55
55
  end
56
56
 
57
- # @return [String] Karafka app root path (user application path)
57
+ # @return [Pathname] Karafka app root path (user application path)
58
58
  def root
59
- Pathname.new(ENV['KARAFKA_ROOT_DIR'] || File.dirname(ENV['BUNDLE_GEMFILE']))
59
+ return @root if @root
60
+
61
+ # If user points to a different root explicitly, use it
62
+ if ENV['KARAFKA_ROOT_DIR']
63
+ @root = Pathname.new(ENV['KARAFKA_ROOT_DIR'])
64
+
65
+ return @root
66
+ end
67
+
68
+ # By default we infer the project root from bundler.
69
+ # We cannot use the BUNDLE_GEMFILE env directly because it may be altered by things like
70
+ # ruby-lsp. Instead we always fallback to the most outer Gemfile. In most of the cases, it
71
+ # won't matter but in case of some automatic setup alterations like ruby-lsp, the location
72
+ # from which the project starts may not match the original Gemfile.
73
+ @root = Pathname.new(
74
+ File.dirname(
75
+ Bundler.with_unbundled_env { Bundler.default_gemfile }
76
+ )
77
+ )
60
78
  end
61
79
 
62
- # @return [String] path to Karafka gem root core
80
+ # @return [Pathname] path to Karafka gem root core
63
81
  def core_root
64
82
  Pathname.new(File.expand_path('karafka', __dir__))
65
83
  end
@@ -71,11 +89,23 @@ module Karafka
71
89
 
72
90
  # @return [Boolean] Do we run within/with Rails. We use this to initialize Railtie and proxy
73
91
  # the console invocation to Rails
92
+ #
93
+ # @note We allow users to disable Rails require because having Rails in the Gemfile does not
94
+ # always mean user wants to have it required. User may want to run Karafka without Rails
95
+ # even when having both in the same Gemfile.
74
96
  def rails?
75
97
  return @rails if instance_variable_defined?('@rails')
76
98
 
77
- # Do not load Rails again if already loaded
78
- Object.const_defined?('Rails::Railtie') || require('rails')
99
+ @rails = Object.const_defined?('Rails::Railtie')
100
+
101
+ # If Rails exists we set it immediately based on its presence and return
102
+ return @rails if @rails
103
+
104
+ # If rails is not present and user wants us not to force-load it, we return
105
+ return @rails if ENV['KARAFKA_REQUIRE_RAILS'] == 'false'
106
+
107
+ # If we should try to require it, we try and if no error, it means its there
108
+ require('rails')
79
109
 
80
110
  @rails = true
81
111
  rescue LoadError
@@ -92,7 +122,17 @@ module Karafka
92
122
  # KARAFKA_BOOT_FILE='/home/app_path/app.rb'
93
123
  # Karafka.boot_file #=> '/home/app_path/app.rb'
94
124
  def boot_file
95
- Pathname.new(ENV['KARAFKA_BOOT_FILE'] || File.join(Karafka.root, 'karafka.rb'))
125
+ boot_file = Pathname.new(ENV['KARAFKA_BOOT_FILE'] || File.join(Karafka.root, 'karafka.rb'))
126
+
127
+ return boot_file if boot_file.absolute?
128
+ return boot_file if boot_file.to_s == 'false'
129
+
130
+ Pathname.new(
131
+ File.expand_path(
132
+ boot_file,
133
+ Karafka.root
134
+ )
135
+ )
96
136
  end
97
137
 
98
138
  # We need to be able to overwrite both monitor and logger after the configuration in case they
data.tar.gz.sig CHANGED
Binary file