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,97 @@
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 RecurringTasks
9
+ # Consumer responsible for management of the recurring tasks and their execution
10
+ # There are some assumptions made here that always need to be satisfied:
11
+ # - we only run schedules that are of same or newer version
12
+ # - we always mark as consumed in such a way, that the first message received after
13
+ # assignment (if any) is a state
14
+ class Consumer < ::Karafka::BaseConsumer
15
+ # @param args [Array] all arguments accepted by the consumer
16
+ def initialize(*args)
17
+ super
18
+ @executor = Executor.new
19
+ end
20
+
21
+ def consume
22
+ # There is nothing we can do if we operate on a newer schedule. In such cases we should
23
+ # just wait and re-raise error hoping someone will notice or that this will be
24
+ # reassigned to a process with newer schedule
25
+ raise(Errors::IncompatibleScheduleError) if @executor.incompatible?
26
+
27
+ messages.each do |message|
28
+ payload = message.payload
29
+ type = payload[:type]
30
+
31
+ case type
32
+ when 'schedule'
33
+ # If we're replaying data, we need to record the most recent stored state, so we
34
+ # can use this data to fully initialize the scheduler
35
+ @executor.update_state(payload) if @executor.replaying?
36
+
37
+ # If this is first message we cannot mark it on the previous offset
38
+ next if message.offset.zero?
39
+
40
+ # We always mark as consumed in such a way, that when replaying, we start from a
41
+ # schedule state message. This makes it easier to recover.
42
+ mark_as_consumed Karafka::Messages::Seek.new(
43
+ topic.name,
44
+ partition,
45
+ message.offset - 1
46
+ )
47
+ when 'command'
48
+ @executor.apply_command(payload)
49
+
50
+ next if @executor.replaying?
51
+
52
+ # Execute on each incoming command to have nice latency but only after replaying
53
+ # During replaying we should not execute because there may be more state changes
54
+ # that collectively have a different outcome
55
+ @executor.call
56
+ else
57
+ raise ::Karafka::Errors::UnsupportedCaseError, type
58
+ end
59
+ end
60
+
61
+ eofed if eofed?
62
+ end
63
+
64
+ # Starts the final replay process if we reached eof during replaying
65
+ def eofed
66
+ # We only mark as replayed if we were replaying in the first place
67
+ # If already replayed, nothing to do
68
+ return unless @executor.replaying?
69
+
70
+ @executor.replay
71
+ end
72
+
73
+ # Runs the cron execution if all good.
74
+ def tick
75
+ # Do nothing until we fully recover the correct state
76
+ return if @executor.replaying?
77
+
78
+ # If the state is incompatible, we can only raise an error.
79
+ # We do it here and in the `#consume` so the pause-retry kicks in basically reporting
80
+ # on this issue once every minute. That way user should not miss this.
81
+ # We use seek to move so we can achieve a pause of 60 seconds in between consecutive
82
+ # errors instead of on each tick because it is much more frequent.
83
+ if @executor.incompatible?
84
+ if messages.empty?
85
+ raise Errors::IncompatibleScheduleError
86
+ else
87
+ return seek(messages.last.offset - 1)
88
+ end
89
+ end
90
+
91
+ # If all good and compatible we can execute the recurring tasks
92
+ @executor.call
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,45 @@
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 RecurringTasks
9
+ # Recurring Tasks related contracts
10
+ module Contracts
11
+ # Makes sure, all the expected config is defined as it should be
12
+ class Config < ::Karafka::Contracts::Base
13
+ configure do |config|
14
+ config.error_messages = YAML.safe_load(
15
+ File.read(
16
+ File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
17
+ )
18
+ ).fetch('en').fetch('validations').fetch('config')
19
+ end
20
+
21
+ nested(:recurring_tasks) do
22
+ required(:consumer_class) { |val| val < ::Karafka::BaseConsumer }
23
+ required(:deserializer) { |val| !val.nil? }
24
+ required(:logging) { |val| [true, false].include?(val) }
25
+ # Do not allow to run more often than every 5 seconds
26
+ required(:interval) { |val| val.is_a?(Integer) && val >= 1_000 }
27
+ required(:group_id) do |val|
28
+ val.is_a?(String) && Karafka::Contracts::TOPIC_REGEXP.match?(val)
29
+ end
30
+
31
+ nested(:topics) do
32
+ required(:schedules) do |val|
33
+ val.is_a?(String) && Karafka::Contracts::TOPIC_REGEXP.match?(val)
34
+ end
35
+
36
+ required(:logs) do |val|
37
+ val.is_a?(String) && Karafka::Contracts::TOPIC_REGEXP.match?(val)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,33 @@
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 RecurringTasks
9
+ # Recurring Tasks related contracts
10
+ module Contracts
11
+ # Ensures that task details are as expected
12
+ class Task < ::Karafka::Contracts::Base
13
+ configure do |config|
14
+ config.error_messages = YAML.safe_load(
15
+ File.read(
16
+ File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
17
+ )
18
+ ).fetch('en').fetch('validations').fetch('recurring_tasks')
19
+ end
20
+
21
+ # Regexp to ensure all tasks ids are URL safe
22
+ ID_REGEXP = /\A[a-zA-Z0-9_-]{1,}\z/
23
+
24
+ required(:id) { |val| val.is_a?(String) && val.match?(ID_REGEXP) }
25
+ required(:cron) { |val| val.is_a?(String) && val.length.positive? }
26
+ required(:enabled) { |val| [true, false].include?(val) }
27
+ required(:changed) { |val| [true, false].include?(val) }
28
+ required(:previous_time) { |val| val.is_a?(Numeric) || val.is_a?(Time) }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
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 RecurringTasks
9
+ # Recurring Tasks data deserializer. We compress data ourselves because we cannot rely on
10
+ # any external optional features like certain compression types, etc. By doing this that way
11
+ # we can ensure we have full control over the compression.
12
+ #
13
+ # @note We use `symbolize_names` because we want to use the same convention of hash building
14
+ # for producing, consuming and displaying related data as in other places.
15
+ class Deserializer
16
+ # @param message [::Karafka::Messages::Message]
17
+ # @return [Hash] deserialized data
18
+ def call(message)
19
+ ::JSON.parse(
20
+ Zlib::Inflate.inflate(message.raw_payload),
21
+ symbolize_names: true
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,79 @@
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 RecurringTasks
9
+ # Dispatches appropriate recurring tasks related messages to expected topics
10
+ class Dispatcher
11
+ class << self
12
+ # Snapshots to Kafka current schedule state
13
+ def schedule
14
+ produce(
15
+ topics.schedules,
16
+ 'state:schedule',
17
+ serializer.schedule(::Karafka::Pro::RecurringTasks.schedule)
18
+ )
19
+ end
20
+
21
+ # Dispatches the command request
22
+ #
23
+ # @param name [String, Symbol] name of the command we want to deal with in the process
24
+ # @param task_id [String] id of the process. We use name instead of id only
25
+ # because in the web ui we work with the full name and it is easier. Since
26
+ def command(name, task_id)
27
+ produce(
28
+ topics.schedules,
29
+ "command:#{name}:#{task_id}",
30
+ serializer.command(name, task_id)
31
+ )
32
+ end
33
+
34
+ # Dispatches the task execution log record
35
+ # @param event [Karafka::Core::Monitoring::Event]
36
+ def log(event)
37
+ produce(
38
+ topics.logs,
39
+ event[:task].id,
40
+ serializer.log(event)
41
+ )
42
+ end
43
+
44
+ private
45
+
46
+ # @return [::WaterDrop::Producer] web ui producer
47
+ def producer
48
+ ::Karafka::App.config.recurring_tasks.producer
49
+ end
50
+
51
+ # @return [String] consumers commands topic
52
+ def topics
53
+ ::Karafka::App.config.recurring_tasks.topics
54
+ end
55
+
56
+ # @return [Serializer]
57
+ def serializer
58
+ Serializer.new
59
+ end
60
+
61
+ # Converts payload to json, compresses it and dispatches to Kafka
62
+ #
63
+ # @param topic [String] target topic
64
+ # @param key [String]
65
+ # @param payload [Hash] hash with payload
66
+ def produce(topic, key, payload)
67
+ producer.produce_async(
68
+ topic: topic,
69
+ key: key,
70
+ partition: 0,
71
+ payload: payload,
72
+ headers: { 'zlib' => 'true' }
73
+ )
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,26 @@
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 RecurringTasks
9
+ # Recurring Tasks related errors
10
+ module Errors
11
+ # Base for all the recurring tasks errors
12
+ BaseError = Class.new(::Karafka::Errors::BaseError)
13
+
14
+ # Raised when older cron manager version is trying to work with newer schema
15
+ IncompatibleSchemaError = Class.new(BaseError)
16
+
17
+ # Raised if you use versioned schedule and an existing schedule from Kafka was picked up
18
+ # by a process with older schedule version.
19
+ # This is a safe-guard to protect against a cases where there would be a temporary
20
+ # reassignment of newer schedule data into older process during deployment. It should go
21
+ # away once all processes are rolled.
22
+ IncompatibleScheduleError = Class.new(BaseError)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,144 @@
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 RecurringTasks
9
+ # Executor is responsible for management of the state of recurring tasks schedule and
10
+ # is the heart of recurring tasks. It coordinates the replaying process as well as
11
+ # tracking of data on changes.
12
+ class Executor
13
+ # Task commands we support and that can be triggered on tasks (if matched)
14
+ COMMANDS = %w[
15
+ disable
16
+ enable
17
+ trigger
18
+ ].freeze
19
+
20
+ def initialize
21
+ @replaying = true
22
+ @incompatible = false
23
+ @catchup_commands = []
24
+ @catchup_schedule = nil
25
+ @matcher = Matcher.new
26
+ end
27
+
28
+ # @return [Boolean] are we in the replaying phase or not (false means, regular operations)
29
+ def replaying?
30
+ @replaying
31
+ end
32
+
33
+ # @return [Boolean] Is the current process schedule incompatible (older) than the one
34
+ # that we have in memory
35
+ def incompatible?
36
+ @incompatible
37
+ end
38
+
39
+ # Applies given command to task (or many tasks) by running the command on tasks that match
40
+ # @param command_hash [Hash] deserialized command data
41
+ def apply_command(command_hash)
42
+ cmd_name = command_hash[:command][:name]
43
+
44
+ raise(Karafka::Errors::UnsupportedCaseError, cmd_name) unless COMMANDS.include?(cmd_name)
45
+
46
+ schedule.each do |task|
47
+ next unless @matcher.matches?(task, command_hash)
48
+
49
+ task.public_send(cmd_name)
50
+ end
51
+ end
52
+
53
+ # Updates the catchup state
54
+ # @param schedule_hash [Hash] deserialized schedule hash hash
55
+ def update_state(schedule_hash)
56
+ @catchup_schedule = schedule_hash
57
+ end
58
+
59
+ # Once all previous data is accumulated runs the catchup process to establish current
60
+ # state of the recurring tasks schedule execution.
61
+ #
62
+ # It includes applying any requested commands as well as synchronizing execution details
63
+ # for existing schedule and making sure all is loaded correctly.
64
+ def replay
65
+ # Ensure replaying happens only once
66
+ return unless @replaying
67
+
68
+ @replaying = false
69
+
70
+ # When there is nothing to replay and synchronize, we can just save the state and
71
+ # proceed
72
+ if @catchup_commands.empty? && @catchup_schedule.nil?
73
+ snapshot
74
+
75
+ return
76
+ end
77
+
78
+ # If the schedule version we have in Kafka is higher than ours, we cannot proceed
79
+ # This prevents us from applying older changes to a new schedule
80
+ if @catchup_schedule[:schedule_version] > schedule.version
81
+ @incompatible = true
82
+
83
+ return
84
+ end
85
+
86
+ # Now we can synchronize the in-memory state based on the last state stored in Kafka
87
+ schedule.each do |task|
88
+ stored_task = @catchup_schedule[:tasks][task.id.to_sym]
89
+
90
+ next unless stored_task
91
+
92
+ stored_previous_time = stored_task[:previous_time]
93
+ task.previous_time = stored_previous_time.zero? ? 0 : Time.at(stored_previous_time)
94
+
95
+ stored_task[:enabled] ? task.enable : task.disable
96
+ end
97
+
98
+ @catchup_commands.each do |cmd|
99
+ apply_command(cmd)
100
+ end
101
+
102
+ # We make sure to save in Kafka once more once everything is up to date
103
+ snapshot
104
+
105
+ @catchup_schedule = nil
106
+ @catchup_commands = []
107
+ end
108
+
109
+ # Run all tasks that should run at a given time and if any tasks were changed in any way
110
+ # or executed, stores the most recent state back to Kafka
111
+ def call
112
+ changed = false
113
+
114
+ schedule.each do |task|
115
+ changed = true if task.changed?
116
+
117
+ unless task.call?
118
+ task.clear
119
+
120
+ next
121
+ end
122
+
123
+ changed = true
124
+ task.call
125
+ end
126
+
127
+ snapshot if changed
128
+ end
129
+
130
+ private
131
+
132
+ # @return [Karafka::Pro::RecurringTasks::Schedule] current in-memory schedule
133
+ def schedule
134
+ ::Karafka::Pro::RecurringTasks.schedule
135
+ end
136
+
137
+ # Dispatches the current schedule state to Kafka
138
+ def snapshot
139
+ Dispatcher.schedule
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,30 @@
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 RecurringTasks
9
+ # Listener we use to track execution of recurring tasks and publish those events into the
10
+ # recurring tasks log table
11
+ class Listener
12
+ # @param event [Karafka::Core::Monitoring::Event] task execution event
13
+ def on_recurring_tasks_task_executed(event)
14
+ Dispatcher.log(event)
15
+ end
16
+
17
+ # @param event [Karafka::Core::Monitoring::Event] error that occurred
18
+ # @note We do nothing with other errors. We only want to log and dispatch information about
19
+ # the recurring tasks errors. The general Web UI error tracking may also work but those
20
+ # are independent. It is not to replace the Web UI tracking but to just log failed
21
+ # executions in the same way as successful but just with the failure as an outcome.
22
+ def on_error_occurred(event)
23
+ return unless event[:type] == 'recurring_tasks.task.execute.error'
24
+
25
+ Dispatcher.log(event)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
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 RecurringTasks
9
+ # Matcher used to check if given command can be applied to a given task.
10
+ class Matcher
11
+ # @param task [Karafka::Pro::RecurringTasks::Task]
12
+ # @param payload [Hash] command message payload
13
+ # @return [Boolean] is this message dedicated to current process and is actionable
14
+ def matches?(task, payload)
15
+ # We only match commands
16
+ return false unless payload[:type] == 'command'
17
+
18
+ # * is a wildcard to match all for batch commands
19
+ return false unless payload[:task][:id] == '*' || payload[:task][:id] == task.id
20
+
21
+ # Ignore messages that have different schema. This can happen in the middle of
22
+ # upgrades of the framework. We ignore this not to risk compatibility issues
23
+ return false unless payload[:schema_version] == Serializer::SCHEMA_VERSION
24
+
25
+ true
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,55 @@
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 RecurringTasks
9
+ # Represents the current code-context schedule with defined tasks and their cron execution
10
+ # details. Single schedule includes all the information about all the tasks that we have
11
+ # defined and to be executed in a given moment in time.
12
+ class Schedule
13
+ # @return [String]
14
+ attr_reader :version
15
+
16
+ # @return [Hash<String, Task>]
17
+ attr_reader :tasks
18
+
19
+ # @param version [String] schedule version. In case of usage of versioning it is used to
20
+ # ensure, that older still active processes do not intercept the assignment to run older
21
+ # version of the scheduler. It is important to make sure, that this string is comparable.
22
+ def initialize(version:)
23
+ @version = version
24
+ @tasks = {}
25
+ end
26
+
27
+ # Adds task into the tasks accumulator
28
+ # @param task [Task]
29
+ # @note In case of multiple tasks with the same id, it will overwrite
30
+ def <<(task)
31
+ @tasks[task.id] = task
32
+ end
33
+
34
+ # Iterates over tasks yielding them one after another
35
+ # @param block [Proc] block that will be executed with each task
36
+ def each(&block)
37
+ @tasks.each_value(&block)
38
+ end
39
+
40
+ # @param id [String] id of a particular recurring task
41
+ # @return [Task, nil] task with a given id or nil if not found
42
+ def find(id)
43
+ @tasks[id]
44
+ end
45
+
46
+ # Allows us to have a nice DSL for defining schedules
47
+ # @param args [Array] attributes accepted by the task initializer
48
+ # @param block [Proc] block to execute
49
+ def schedule(**args, &block)
50
+ self << Task.new(**args, &block)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,105 @@
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 RecurringTasks
9
+ # Converts schedule command and log details into data we can dispatch to Kafka.
10
+ class Serializer
11
+ # Current recurring tasks related schema structure
12
+ SCHEMA_VERSION = '1.0'
13
+
14
+ # @param schedule [Karafka::Pro::RecurringTasks::Schedule] schedule to serialize
15
+ # @return [String] serialized and compressed current schedule data with its tasks and their
16
+ # current state.
17
+ def schedule(schedule)
18
+ tasks = {}
19
+
20
+ schedule.each do |task|
21
+ tasks[task.id] = {
22
+ id: task.id,
23
+ cron: task.cron.original,
24
+ previous_time: task.previous_time.to_i,
25
+ next_time: task.next_time.to_i,
26
+ enabled: task.enabled?
27
+ }
28
+ end
29
+
30
+ data = {
31
+ schema_version: SCHEMA_VERSION,
32
+ schedule_version: schedule.version,
33
+ dispatched_at: Time.now.to_f,
34
+ type: 'schedule',
35
+ tasks: tasks
36
+ }
37
+
38
+ compress(
39
+ serialize(data)
40
+ )
41
+ end
42
+
43
+ # @param command_name [String] command name
44
+ # @param task_id [String] task id or '*' to match all.
45
+ # @return [String] serialized and compressed command data
46
+ def command(command_name, task_id)
47
+ data = {
48
+ schema_version: SCHEMA_VERSION,
49
+ schedule_version: ::Karafka::Pro::RecurringTasks.schedule.version,
50
+ dispatched_at: Time.now.to_f,
51
+ type: 'command',
52
+ command: {
53
+ name: command_name
54
+ },
55
+ task: {
56
+ id: task_id
57
+ }
58
+ }
59
+
60
+ compress(
61
+ serialize(data)
62
+ )
63
+ end
64
+
65
+ # @param event [Karafka::Core::Monitoring::Event] recurring task dispatch event
66
+ # @return [String] serialized and compressed event log data
67
+ def log(event)
68
+ task = event[:task]
69
+
70
+ data = {
71
+ schema_version: SCHEMA_VERSION,
72
+ schedule_version: ::Karafka::Pro::RecurringTasks.schedule.version,
73
+ dispatched_at: Time.now.to_f,
74
+ type: 'log',
75
+ task: {
76
+ id: task.id,
77
+ time_taken: event.payload[:time] || -1,
78
+ result: event.payload.key?(:error) ? 'failure' : 'success'
79
+ }
80
+ }
81
+
82
+ compress(
83
+ serialize(data)
84
+ )
85
+ end
86
+
87
+ private
88
+
89
+ # @param hash [Hash] hash to cast to json
90
+ # @return [String] json hash
91
+ def serialize(hash)
92
+ hash.to_json
93
+ end
94
+
95
+ # Compresses the provided data
96
+ #
97
+ # @param data [String] data to compress
98
+ # @return [String] compressed data
99
+ def compress(data)
100
+ Zlib::Deflate.deflate(data)
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end