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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +26 -34
- data/.github/workflows/ci.yml +18 -6
- data/.ruby-version +1 -1
- data/CHANGELOG.md +146 -1
- data/Gemfile +10 -5
- data/Gemfile.lock +60 -39
- data/LICENSE +8 -3
- data/bin/integrations +13 -1
- data/certs/cert.pem +26 -0
- data/config/locales/errors.yml +18 -2
- data/config/locales/pro_errors.yml +44 -0
- data/docker-compose.yml +1 -3
- data/karafka.gemspec +6 -4
- data/lib/active_job/queue_adapters/karafka_adapter.rb +18 -7
- data/lib/karafka/active_job/dispatcher.rb +13 -0
- data/lib/karafka/active_job/job_extensions.rb +3 -0
- data/lib/karafka/admin.rb +86 -0
- data/lib/karafka/app.rb +17 -0
- data/lib/karafka/base_consumer.rb +130 -19
- data/lib/karafka/cli/base.rb +24 -8
- data/lib/karafka/cli/install.rb +2 -1
- data/lib/karafka/cli/server.rb +1 -0
- data/lib/karafka/cli/swarm.rb +1 -0
- data/lib/karafka/cli/topics/align.rb +12 -2
- data/lib/karafka/cli/topics/plan.rb +54 -6
- data/lib/karafka/cli/topics.rb +45 -18
- data/lib/karafka/connection/client.rb +102 -35
- data/lib/karafka/connection/listener.rb +48 -11
- data/lib/karafka/connection/messages_buffer.rb +19 -6
- data/lib/karafka/connection/proxy.rb +3 -0
- data/lib/karafka/connection/raw_messages_buffer.rb +43 -9
- data/lib/karafka/connection/rebalance_manager.rb +24 -13
- data/lib/karafka/contracts/config.rb +4 -0
- data/lib/karafka/contracts/consumer_group.rb +17 -0
- data/lib/karafka/contracts/routing.rb +59 -0
- data/lib/karafka/contracts/topic.rb +14 -0
- data/lib/karafka/embedded.rb +46 -3
- data/lib/karafka/errors.rb +3 -2
- data/lib/karafka/helpers/async.rb +11 -2
- data/lib/karafka/helpers/config_importer.rb +13 -0
- data/lib/karafka/instrumentation/assignments_tracker.rb +7 -2
- data/lib/karafka/instrumentation/logger_listener.rb +45 -4
- data/lib/karafka/instrumentation/notifications.rb +12 -0
- data/lib/karafka/instrumentation/vendors/appsignal/client.rb +32 -11
- data/lib/karafka/instrumentation/vendors/appsignal/errors_listener.rb +1 -1
- data/lib/karafka/instrumentation/vendors/appsignal/metrics_listener.rb +3 -1
- data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +17 -19
- data/lib/karafka/instrumentation/vendors/datadog/metrics_listener.rb +27 -18
- data/lib/karafka/instrumentation/vendors/kubernetes/base_listener.rb +2 -2
- data/lib/karafka/instrumentation/vendors/kubernetes/liveness_listener.rb +41 -13
- data/lib/karafka/messages/message.rb +9 -9
- data/lib/karafka/pro/active_job/consumer.rb +2 -10
- data/lib/karafka/pro/active_job/dispatcher.rb +67 -19
- data/lib/karafka/pro/active_job/job_options_contract.rb +12 -10
- data/lib/karafka/pro/base_consumer.rb +2 -10
- data/lib/karafka/pro/cleaner/errors.rb +2 -10
- data/lib/karafka/pro/cleaner/messages/message.rb +14 -12
- data/lib/karafka/pro/cleaner/messages/messages.rb +2 -10
- data/lib/karafka/pro/cleaner/messages/metadata.rb +41 -0
- data/lib/karafka/pro/cleaner.rb +3 -10
- data/lib/karafka/pro/connection/manager.rb +6 -10
- data/lib/karafka/pro/connection/multiplexing/listener.rb +2 -10
- data/lib/karafka/pro/contracts/base.rb +2 -10
- data/lib/karafka/pro/contracts/server_cli_options.rb +2 -10
- data/lib/karafka/pro/encryption/cipher.rb +2 -10
- data/lib/karafka/pro/encryption/contracts/config.rb +2 -10
- data/lib/karafka/pro/encryption/errors.rb +2 -10
- data/lib/karafka/pro/encryption/messages/middleware.rb +2 -10
- data/lib/karafka/pro/encryption/messages/parser.rb +2 -10
- data/lib/karafka/pro/encryption/setup/config.rb +2 -10
- data/lib/karafka/pro/encryption.rb +2 -10
- data/lib/karafka/pro/instrumentation/performance_tracker.rb +2 -10
- data/lib/karafka/pro/iterator/expander.rb +2 -10
- data/lib/karafka/pro/iterator/tpl_builder.rb +2 -10
- data/lib/karafka/pro/iterator.rb +2 -10
- data/lib/karafka/pro/loader.rb +5 -11
- data/lib/karafka/pro/processing/adaptive_iterator/consumer.rb +54 -0
- data/lib/karafka/pro/processing/adaptive_iterator/tracker.rb +67 -0
- data/lib/karafka/pro/processing/collapser.rb +2 -10
- data/lib/karafka/pro/processing/coordinator.rb +2 -10
- data/lib/karafka/pro/processing/coordinators/errors_tracker.rb +2 -10
- data/lib/karafka/pro/processing/coordinators/filters_applier.rb +19 -10
- data/lib/karafka/pro/processing/coordinators/virtual_offset_manager.rb +2 -10
- data/lib/karafka/pro/processing/executor.rb +2 -10
- data/lib/karafka/pro/processing/expansions_selector.rb +3 -10
- data/lib/karafka/pro/processing/filters/base.rb +14 -10
- data/lib/karafka/pro/processing/filters/delayer.rb +4 -12
- data/lib/karafka/pro/processing/filters/expirer.rb +2 -10
- data/lib/karafka/pro/processing/filters/inline_insights_delayer.rb +2 -10
- data/lib/karafka/pro/processing/filters/throttler.rb +2 -10
- data/lib/karafka/pro/processing/filters/virtual_limiter.rb +2 -10
- data/lib/karafka/pro/processing/jobs/consume_non_blocking.rb +4 -10
- data/lib/karafka/pro/processing/jobs/eofed_non_blocking.rb +26 -0
- data/lib/karafka/pro/processing/jobs/periodic.rb +4 -10
- data/lib/karafka/pro/processing/jobs/periodic_non_blocking.rb +4 -10
- data/lib/karafka/pro/processing/jobs/revoked_non_blocking.rb +4 -10
- data/lib/karafka/pro/processing/jobs_builder.rb +14 -10
- data/lib/karafka/pro/processing/jobs_queue.rb +2 -10
- data/lib/karafka/pro/processing/offset_metadata/consumer.rb +2 -10
- data/lib/karafka/pro/processing/offset_metadata/fetcher.rb +2 -10
- data/lib/karafka/pro/processing/offset_metadata/listener.rb +2 -10
- data/lib/karafka/pro/processing/partitioner.rb +35 -24
- data/lib/karafka/pro/processing/periodic_job/consumer.rb +2 -10
- data/lib/karafka/pro/processing/piping/consumer.rb +2 -10
- data/lib/karafka/pro/processing/schedulers/base.rb +2 -10
- data/lib/karafka/pro/processing/schedulers/default.rb +3 -10
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom.rb +3 -11
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom_vp.rb +3 -11
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom.rb +2 -10
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom.rb +3 -11
- data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom_vp.rb +3 -11
- data/lib/karafka/pro/processing/strategies/aj/dlq_mom.rb +2 -10
- data/lib/karafka/pro/processing/strategies/aj/dlq_mom_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom.rb +2 -10
- data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom_vp.rb +3 -11
- data/lib/karafka/pro/processing/strategies/aj/ftr_mom.rb +2 -10
- data/lib/karafka/pro/processing/strategies/aj/ftr_mom_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/aj/lrj_mom.rb +2 -10
- data/lib/karafka/pro/processing/strategies/aj/lrj_mom_vp.rb +5 -13
- data/lib/karafka/pro/processing/strategies/aj/mom.rb +2 -10
- data/lib/karafka/pro/processing/strategies/aj/mom_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/base.rb +2 -10
- data/lib/karafka/pro/processing/strategies/default.rb +140 -58
- data/lib/karafka/pro/processing/strategies/dlq/default.rb +23 -15
- data/lib/karafka/pro/processing/strategies/dlq/ftr.rb +2 -10
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj.rb +3 -11
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom.rb +7 -11
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/dlq/ftr_mom.rb +19 -11
- data/lib/karafka/pro/processing/strategies/dlq/ftr_mom_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/dlq/ftr_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/dlq/lrj.rb +3 -11
- data/lib/karafka/pro/processing/strategies/dlq/lrj_mom.rb +19 -11
- data/lib/karafka/pro/processing/strategies/dlq/lrj_mom_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/dlq/lrj_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/dlq/mom.rb +24 -16
- data/lib/karafka/pro/processing/strategies/dlq/mom_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/dlq/vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/ftr/default.rb +17 -12
- data/lib/karafka/pro/processing/strategies/ftr/vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/lrj/default.rb +5 -13
- data/lib/karafka/pro/processing/strategies/lrj/ftr.rb +3 -11
- data/lib/karafka/pro/processing/strategies/lrj/ftr_mom.rb +2 -10
- data/lib/karafka/pro/processing/strategies/lrj/ftr_mom_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/lrj/ftr_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/lrj/mom.rb +4 -12
- data/lib/karafka/pro/processing/strategies/lrj/mom_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/lrj/vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/mom/default.rb +2 -10
- data/lib/karafka/pro/processing/strategies/mom/ftr.rb +2 -10
- data/lib/karafka/pro/processing/strategies/mom/ftr_vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/mom/vp.rb +2 -10
- data/lib/karafka/pro/processing/strategies/vp/default.rb +5 -10
- data/lib/karafka/pro/processing/strategies.rb +2 -10
- data/lib/karafka/pro/processing/strategy_selector.rb +2 -10
- data/lib/karafka/pro/processing/subscription_groups_coordinator.rb +2 -10
- data/lib/karafka/pro/recurring_tasks/consumer.rb +97 -0
- data/lib/karafka/pro/recurring_tasks/contracts/config.rb +45 -0
- data/lib/karafka/pro/recurring_tasks/contracts/task.rb +33 -0
- data/lib/karafka/pro/recurring_tasks/deserializer.rb +27 -0
- data/lib/karafka/pro/recurring_tasks/dispatcher.rb +79 -0
- data/lib/karafka/pro/recurring_tasks/errors.rb +26 -0
- data/lib/karafka/pro/recurring_tasks/executor.rb +144 -0
- data/lib/karafka/pro/recurring_tasks/listener.rb +30 -0
- data/lib/karafka/pro/recurring_tasks/matcher.rb +30 -0
- data/lib/karafka/pro/recurring_tasks/schedule.rb +55 -0
- data/lib/karafka/pro/recurring_tasks/serializer.rb +105 -0
- data/lib/karafka/pro/recurring_tasks/setup/config.rb +44 -0
- data/lib/karafka/pro/recurring_tasks/task.rb +143 -0
- data/lib/karafka/pro/recurring_tasks.rb +79 -0
- data/lib/karafka/pro/routing/features/active_job/builder.rb +2 -10
- data/lib/karafka/pro/routing/features/active_job.rb +2 -10
- data/lib/karafka/pro/routing/features/adaptive_iterator/config.rb +26 -0
- data/lib/karafka/pro/routing/features/adaptive_iterator/contracts/topic.rb +66 -0
- data/lib/karafka/pro/routing/features/adaptive_iterator/topic.rb +54 -0
- data/lib/karafka/pro/routing/features/adaptive_iterator.rb +23 -0
- data/lib/karafka/pro/routing/features/base.rb +2 -10
- data/lib/karafka/pro/routing/features/dead_letter_queue/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/dead_letter_queue/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/dead_letter_queue.rb +2 -10
- data/lib/karafka/pro/routing/features/delaying/config.rb +2 -10
- data/lib/karafka/pro/routing/features/delaying/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/delaying/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/delaying.rb +2 -10
- data/lib/karafka/pro/routing/features/direct_assignments/config.rb +2 -10
- data/lib/karafka/pro/routing/features/direct_assignments/contracts/consumer_group.rb +2 -10
- data/lib/karafka/pro/routing/features/direct_assignments/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/direct_assignments/subscription_group.rb +2 -10
- data/lib/karafka/pro/routing/features/direct_assignments/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/direct_assignments.rb +2 -10
- data/lib/karafka/pro/routing/features/expiring/config.rb +2 -10
- data/lib/karafka/pro/routing/features/expiring/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/expiring/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/expiring.rb +2 -10
- data/lib/karafka/pro/routing/features/filtering/config.rb +2 -10
- data/lib/karafka/pro/routing/features/filtering/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/filtering/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/filtering.rb +2 -10
- data/lib/karafka/pro/routing/features/inline_insights/config.rb +2 -10
- data/lib/karafka/pro/routing/features/inline_insights/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/inline_insights/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/inline_insights.rb +2 -10
- data/lib/karafka/pro/routing/features/long_running_job/config.rb +2 -10
- data/lib/karafka/pro/routing/features/long_running_job/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/long_running_job/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/long_running_job.rb +2 -10
- data/lib/karafka/pro/routing/features/multiplexing/config.rb +2 -10
- data/lib/karafka/pro/routing/features/multiplexing/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/multiplexing/patches/contracts/consumer_group.rb +2 -10
- data/lib/karafka/pro/routing/features/multiplexing/proxy.rb +2 -10
- data/lib/karafka/pro/routing/features/multiplexing/subscription_group.rb +2 -10
- data/lib/karafka/pro/routing/features/multiplexing/subscription_groups_builder.rb +2 -10
- data/lib/karafka/pro/routing/features/multiplexing.rb +2 -10
- data/lib/karafka/pro/routing/features/non_blocking_job/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/non_blocking_job.rb +2 -10
- data/lib/karafka/pro/routing/features/offset_metadata/config.rb +2 -10
- data/lib/karafka/pro/routing/features/offset_metadata/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/offset_metadata/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/offset_metadata.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns/builder.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns/config.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns/consumer_group.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns/contracts/consumer_group.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns/contracts/pattern.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns/detector.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns/pattern.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns/patterns.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns/topics.rb +2 -10
- data/lib/karafka/pro/routing/features/patterns.rb +2 -10
- data/lib/karafka/pro/routing/features/pausing/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/pausing/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/pausing.rb +2 -10
- data/lib/karafka/pro/routing/features/periodic_job/config.rb +2 -10
- data/lib/karafka/pro/routing/features/periodic_job/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/periodic_job/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/periodic_job.rb +2 -10
- data/lib/karafka/pro/routing/features/recurring_tasks/builder.rb +123 -0
- data/lib/karafka/pro/routing/features/recurring_tasks/config.rb +20 -0
- data/lib/karafka/pro/routing/features/recurring_tasks/contracts/topic.rb +32 -0
- data/lib/karafka/pro/routing/features/recurring_tasks/proxy.rb +19 -0
- data/lib/karafka/pro/routing/features/recurring_tasks/topic.rb +36 -0
- data/lib/karafka/pro/routing/features/recurring_tasks.rb +17 -0
- data/lib/karafka/pro/routing/features/scheduled_messages/builder.rb +123 -0
- data/lib/karafka/pro/routing/features/scheduled_messages/config.rb +20 -0
- data/lib/karafka/pro/routing/features/scheduled_messages/contracts/topic.rb +32 -0
- data/lib/karafka/pro/routing/features/scheduled_messages/proxy.rb +19 -0
- data/lib/karafka/pro/routing/features/scheduled_messages/topic.rb +36 -0
- data/lib/karafka/pro/routing/features/scheduled_messages.rb +16 -0
- data/lib/karafka/pro/routing/features/swarm/config.rb +2 -10
- data/lib/karafka/pro/routing/features/swarm/contracts/routing.rb +2 -10
- data/lib/karafka/pro/routing/features/swarm/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/swarm/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/swarm.rb +2 -10
- data/lib/karafka/pro/routing/features/throttling/config.rb +2 -10
- data/lib/karafka/pro/routing/features/throttling/contracts/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/throttling/topic.rb +2 -10
- data/lib/karafka/pro/routing/features/throttling.rb +2 -10
- data/lib/karafka/pro/routing/features/virtual_partitions/config.rb +3 -10
- data/lib/karafka/pro/routing/features/virtual_partitions/contracts/topic.rb +3 -10
- data/lib/karafka/pro/routing/features/virtual_partitions/topic.rb +10 -12
- data/lib/karafka/pro/routing/features/virtual_partitions.rb +2 -10
- data/lib/karafka/pro/scheduled_messages/consumer.rb +177 -0
- data/lib/karafka/pro/scheduled_messages/contracts/config.rb +48 -0
- data/lib/karafka/pro/scheduled_messages/contracts/message.rb +88 -0
- data/lib/karafka/pro/scheduled_messages/daily_buffer.rb +71 -0
- data/lib/karafka/pro/scheduled_messages/day.rb +37 -0
- data/lib/karafka/pro/scheduled_messages/deserializers/headers.rb +38 -0
- data/lib/karafka/pro/scheduled_messages/deserializers/payload.rb +27 -0
- data/lib/karafka/pro/scheduled_messages/dispatcher.rb +114 -0
- data/lib/karafka/pro/scheduled_messages/errors.rb +20 -0
- data/lib/karafka/pro/scheduled_messages/max_epoch.rb +33 -0
- data/lib/karafka/pro/scheduled_messages/proxy.rb +177 -0
- data/lib/karafka/pro/scheduled_messages/schema_validator.rb +29 -0
- data/lib/karafka/pro/scheduled_messages/serializer.rb +47 -0
- data/lib/karafka/pro/scheduled_messages/setup/config.rb +52 -0
- data/lib/karafka/pro/scheduled_messages/state.rb +54 -0
- data/lib/karafka/pro/scheduled_messages/tracker.rb +56 -0
- data/lib/karafka/pro/scheduled_messages.rb +59 -0
- data/lib/karafka/pro/swarm/liveness_listener.rb +2 -10
- data/lib/karafka/processing/coordinator.rb +14 -0
- data/lib/karafka/processing/executor.rb +29 -1
- data/lib/karafka/processing/jobs/base.rb +13 -0
- data/lib/karafka/processing/jobs/consume.rb +2 -0
- data/lib/karafka/processing/jobs/eofed.rb +29 -0
- data/lib/karafka/processing/jobs/idle.rb +2 -0
- data/lib/karafka/processing/jobs/revoked.rb +2 -0
- data/lib/karafka/processing/jobs/shutdown.rb +2 -0
- data/lib/karafka/processing/jobs_builder.rb +6 -0
- data/lib/karafka/processing/schedulers/default.rb +1 -0
- data/lib/karafka/processing/strategies/aj_dlq_mom.rb +1 -1
- data/lib/karafka/processing/strategies/default.rb +45 -13
- data/lib/karafka/processing/strategies/dlq.rb +19 -5
- data/lib/karafka/processing/strategies/dlq_mom.rb +27 -8
- data/lib/karafka/processing/worker.rb +26 -13
- data/lib/karafka/railtie.rb +11 -42
- data/lib/karafka/routing/builder.rb +19 -1
- data/lib/karafka/routing/consumer_group.rb +9 -14
- data/lib/karafka/routing/features/dead_letter_queue/config.rb +3 -0
- data/lib/karafka/routing/features/dead_letter_queue/contracts/topic.rb +1 -0
- data/lib/karafka/routing/features/dead_letter_queue/topic.rb +7 -2
- data/lib/karafka/routing/features/eofed/config.rb +15 -0
- data/lib/karafka/routing/features/eofed/contracts/topic.rb +39 -0
- data/lib/karafka/routing/features/eofed/topic.rb +31 -0
- data/lib/karafka/routing/features/eofed.rb +14 -0
- data/lib/karafka/routing/subscription_group.rb +29 -1
- data/lib/karafka/routing/topic.rb +24 -1
- data/lib/karafka/runner.rb +10 -9
- data/lib/karafka/server.rb +37 -1
- data/lib/karafka/setup/attributes_map.rb +11 -4
- data/lib/karafka/setup/config.rb +11 -52
- data/lib/karafka/setup/defaults_injector.rb +64 -0
- data/lib/karafka/swarm/node.rb +2 -0
- data/lib/karafka/swarm/supervisor.rb +11 -2
- data/lib/karafka/templates/karafka.rb.erb +2 -2
- data/lib/karafka/version.rb +1 -1
- data/lib/karafka.rb +47 -7
- data.tar.gz.sig +0 -0
- metadata +116 -33
- metadata.gz.sig +0 -0
- data/certs/cert_chain.pem +0 -26
|
@@ -5,6 +5,8 @@ module Karafka
|
|
|
5
5
|
module Jobs
|
|
6
6
|
# Job that runs on each active consumer upon process shutdown (one job per consumer).
|
|
7
7
|
class Shutdown < Base
|
|
8
|
+
self.action = :shutdown
|
|
9
|
+
|
|
8
10
|
# @param executor [Karafka::Processing::Executor] executor that is suppose to run a given
|
|
9
11
|
# job on an active consumer
|
|
10
12
|
# @return [Shutdown]
|
|
@@ -12,6 +12,12 @@ module Karafka
|
|
|
12
12
|
Jobs::Consume.new(executor, messages)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
+
# @param executor [Karafka::Processing::Executor]
|
|
16
|
+
# @return [Karafka::Processing::Jobs::Eofed] eofed job
|
|
17
|
+
def eofed(executor)
|
|
18
|
+
Jobs::Eofed.new(executor)
|
|
19
|
+
end
|
|
20
|
+
|
|
15
21
|
# @param executor [Karafka::Processing::Executor]
|
|
16
22
|
# @return [Karafka::Processing::Jobs::Revoked] revocation job
|
|
17
23
|
def revoked(executor)
|
|
@@ -24,6 +24,7 @@ module Karafka
|
|
|
24
24
|
alias on_schedule_revocation on_schedule_consumption
|
|
25
25
|
alias on_schedule_shutdown on_schedule_consumption
|
|
26
26
|
alias on_schedule_idle on_schedule_consumption
|
|
27
|
+
alias on_schedule_eofed on_schedule_consumption
|
|
27
28
|
|
|
28
29
|
# This scheduler does not have anything to manage as it is a pass through and has no state
|
|
29
30
|
def on_manage
|
|
@@ -35,7 +35,7 @@ module Karafka
|
|
|
35
35
|
# since AJ consumer commits the offset after each job, we also know that the
|
|
36
36
|
# previous job was successful
|
|
37
37
|
mark_dispatched_to_dlq(skippable_message)
|
|
38
|
-
pause(
|
|
38
|
+
pause(seek_offset, nil, false)
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
end
|
|
@@ -17,19 +17,30 @@ module Karafka
|
|
|
17
17
|
%i[
|
|
18
18
|
consume
|
|
19
19
|
idle
|
|
20
|
+
eofed
|
|
20
21
|
revoked
|
|
21
22
|
shutdown
|
|
22
23
|
].each do |action|
|
|
23
24
|
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
24
25
|
# No actions needed for the standard flow here
|
|
25
26
|
def handle_before_schedule_#{action}
|
|
26
|
-
|
|
27
|
+
monitor.instrument('consumer.before_schedule_#{action}', caller: self)
|
|
27
28
|
|
|
28
29
|
nil
|
|
29
30
|
end
|
|
30
31
|
RUBY
|
|
31
32
|
end
|
|
32
33
|
|
|
34
|
+
# Runs the post-creation, post-assignment code
|
|
35
|
+
# @note It runs in the listener loop. Should **not** be used for anything heavy or
|
|
36
|
+
# with any potential errors. Mostly for initialization of states, etc.
|
|
37
|
+
def handle_initialized
|
|
38
|
+
monitor.instrument('consumer.initialize', caller: self)
|
|
39
|
+
monitor.instrument('consumer.initialized', caller: self) do
|
|
40
|
+
initialized
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
33
44
|
# Marks message as consumed in an async way.
|
|
34
45
|
#
|
|
35
46
|
# @param message [Messages::Message] last successfully processed message.
|
|
@@ -43,13 +54,13 @@ module Karafka
|
|
|
43
54
|
def mark_as_consumed(message)
|
|
44
55
|
# seek offset can be nil only in case `#seek` was invoked with offset reset request
|
|
45
56
|
# In case like this we ignore marking
|
|
46
|
-
return true if
|
|
57
|
+
return true if seek_offset.nil?
|
|
47
58
|
# Ignore earlier offsets than the one we already committed
|
|
48
|
-
return true if
|
|
59
|
+
return true if seek_offset > message.offset
|
|
49
60
|
return false if revoked?
|
|
50
61
|
return revoked? unless client.mark_as_consumed(message)
|
|
51
62
|
|
|
52
|
-
|
|
63
|
+
self.seek_offset = message.offset + 1
|
|
53
64
|
|
|
54
65
|
true
|
|
55
66
|
end
|
|
@@ -62,14 +73,14 @@ module Karafka
|
|
|
62
73
|
def mark_as_consumed!(message)
|
|
63
74
|
# seek offset can be nil only in case `#seek` was invoked with offset reset request
|
|
64
75
|
# In case like this we ignore marking
|
|
65
|
-
return true if
|
|
76
|
+
return true if seek_offset.nil?
|
|
66
77
|
# Ignore earlier offsets than the one we already committed
|
|
67
|
-
return true if
|
|
78
|
+
return true if seek_offset > message.offset
|
|
68
79
|
return false if revoked?
|
|
69
80
|
|
|
70
81
|
return revoked? unless client.mark_as_consumed!(message)
|
|
71
82
|
|
|
72
|
-
|
|
83
|
+
self.seek_offset = message.offset + 1
|
|
73
84
|
|
|
74
85
|
true
|
|
75
86
|
end
|
|
@@ -104,10 +115,21 @@ module Karafka
|
|
|
104
115
|
coordinator.pause_tracker.increment
|
|
105
116
|
end
|
|
106
117
|
|
|
118
|
+
# Runs the wrapping to execute appropriate action wrapped with the wrapper method code
|
|
119
|
+
#
|
|
120
|
+
# @param action [Symbol]
|
|
121
|
+
# @param block [Proc]
|
|
122
|
+
def handle_wrap(action, &block)
|
|
123
|
+
monitor.instrument('consumer.wrap', caller: self)
|
|
124
|
+
monitor.instrument('consumer.wrapped', caller: self) do
|
|
125
|
+
wrap(action, &block)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
107
129
|
# Run the user consumption code
|
|
108
130
|
def handle_consume
|
|
109
|
-
|
|
110
|
-
|
|
131
|
+
monitor.instrument('consumer.consume', caller: self)
|
|
132
|
+
monitor.instrument('consumer.consumed', caller: self) do
|
|
111
133
|
consume
|
|
112
134
|
end
|
|
113
135
|
|
|
@@ -151,6 +173,16 @@ module Karafka
|
|
|
151
173
|
coordinator.decrement(:idle)
|
|
152
174
|
end
|
|
153
175
|
|
|
176
|
+
# Runs the consumer `#eofed` method with reporting
|
|
177
|
+
def handle_eofed
|
|
178
|
+
monitor.instrument('consumer.eof', caller: self)
|
|
179
|
+
monitor.instrument('consumer.eofed', caller: self) do
|
|
180
|
+
eofed
|
|
181
|
+
end
|
|
182
|
+
ensure
|
|
183
|
+
coordinator.decrement(:eofed)
|
|
184
|
+
end
|
|
185
|
+
|
|
154
186
|
# We need to always un-pause the processing in case we have lost a given partition.
|
|
155
187
|
# Otherwise the underlying librdkafka would not know we may want to continue processing and
|
|
156
188
|
# the pause could in theory last forever
|
|
@@ -159,8 +191,8 @@ module Karafka
|
|
|
159
191
|
|
|
160
192
|
coordinator.revoke
|
|
161
193
|
|
|
162
|
-
|
|
163
|
-
|
|
194
|
+
monitor.instrument('consumer.revoke', caller: self)
|
|
195
|
+
monitor.instrument('consumer.revoked', caller: self) do
|
|
164
196
|
revoked
|
|
165
197
|
end
|
|
166
198
|
ensure
|
|
@@ -169,8 +201,8 @@ module Karafka
|
|
|
169
201
|
|
|
170
202
|
# Runs the shutdown code
|
|
171
203
|
def handle_shutdown
|
|
172
|
-
|
|
173
|
-
|
|
204
|
+
monitor.instrument('consumer.shutting_down', caller: self)
|
|
205
|
+
monitor.instrument('consumer.shutdown', caller: self) do
|
|
174
206
|
shutdown
|
|
175
207
|
end
|
|
176
208
|
ensure
|
|
@@ -76,12 +76,16 @@ module Karafka
|
|
|
76
76
|
dispatch_to_dlq(skippable_message)
|
|
77
77
|
|
|
78
78
|
# We mark the broken message as consumed and move on
|
|
79
|
-
|
|
79
|
+
if mark_after_dispatch?
|
|
80
|
+
mark_dispatched_to_dlq(skippable_message)
|
|
80
81
|
|
|
81
|
-
|
|
82
|
+
return if revoked?
|
|
83
|
+
else
|
|
84
|
+
self.seek_offset = skippable_message.offset + 1
|
|
85
|
+
end
|
|
82
86
|
|
|
83
87
|
# We pause to backoff once just in case.
|
|
84
|
-
pause(
|
|
88
|
+
pause(seek_offset, nil, false)
|
|
85
89
|
end
|
|
86
90
|
end
|
|
87
91
|
|
|
@@ -91,7 +95,7 @@ module Karafka
|
|
|
91
95
|
# information if this message was from marked offset or figured out via mom flow
|
|
92
96
|
def find_skippable_message
|
|
93
97
|
skippable_message = messages.find do |msg|
|
|
94
|
-
coordinator.marked? && msg.offset ==
|
|
98
|
+
coordinator.marked? && msg.offset == seek_offset
|
|
95
99
|
end
|
|
96
100
|
|
|
97
101
|
# If we don't have the message matching the last comitted offset, it means that
|
|
@@ -113,13 +117,23 @@ module Karafka
|
|
|
113
117
|
)
|
|
114
118
|
|
|
115
119
|
# Notify about dispatch on the events bus
|
|
116
|
-
|
|
120
|
+
monitor.instrument(
|
|
117
121
|
'dead_letter_queue.dispatched',
|
|
118
122
|
caller: self,
|
|
119
123
|
message: skippable_message
|
|
120
124
|
)
|
|
121
125
|
end
|
|
122
126
|
|
|
127
|
+
# @return [Boolean] should we mark given message as consumed after dispatch. For default
|
|
128
|
+
# non MOM strategies if user did not explicitly tell us not to, we mark it. Default is
|
|
129
|
+
# `nil`, which means `true` in this case. If user provided alternative value, we go
|
|
130
|
+
# with it.
|
|
131
|
+
def mark_after_dispatch?
|
|
132
|
+
return true if topic.dead_letter_queue.mark_after_dispatch.nil?
|
|
133
|
+
|
|
134
|
+
topic.dead_letter_queue.mark_after_dispatch
|
|
135
|
+
end
|
|
136
|
+
|
|
123
137
|
# Marks message that went to DLQ (if applicable) based on the requested method
|
|
124
138
|
# @param skippable_message [Karafka::Messages::Message]
|
|
125
139
|
def mark_dispatched_to_dlq(skippable_message)
|
|
@@ -33,16 +33,35 @@ module Karafka
|
|
|
33
33
|
|
|
34
34
|
dispatch_to_dlq(skippable_message)
|
|
35
35
|
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
# We mark the broken message as consumed and move on
|
|
37
|
+
if mark_after_dispatch?
|
|
38
|
+
mark_dispatched_to_dlq(skippable_message)
|
|
39
|
+
|
|
40
|
+
return if revoked?
|
|
41
|
+
else
|
|
42
|
+
# Save the next offset we want to go with after moving given message to DLQ
|
|
43
|
+
# Without this, we would not be able to move forward and we would end up
|
|
44
|
+
# in an infinite loop trying to un-pause from the message we've already processed
|
|
45
|
+
# Of course, since it's a MoM a rebalance or kill, will move it back as no
|
|
46
|
+
# offsets are being committed
|
|
47
|
+
self.seek_offset = skippable_message.offset + 1
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
pause(seek_offset, nil, false)
|
|
44
51
|
end
|
|
45
52
|
end
|
|
53
|
+
|
|
54
|
+
# @return [Boolean] should we mark given message as consumed after dispatch. For
|
|
55
|
+
# MOM strategies if user did not explicitly tell us to mark, we do not mark. Default is
|
|
56
|
+
# `nil`, which means `false` in this case. If user provided alternative value, we go
|
|
57
|
+
# with it.
|
|
58
|
+
#
|
|
59
|
+
# @note Please note, this is the opposite behavior than in case of AOM strategies.
|
|
60
|
+
def mark_after_dispatch?
|
|
61
|
+
return false if topic.dead_letter_queue.mark_after_dispatch.nil?
|
|
62
|
+
|
|
63
|
+
topic.dead_letter_queue.mark_after_dispatch
|
|
64
|
+
end
|
|
46
65
|
end
|
|
47
66
|
end
|
|
48
67
|
end
|
|
@@ -18,6 +18,10 @@ module Karafka
|
|
|
18
18
|
# not user code but need to run after user code base is executed.
|
|
19
19
|
class Worker
|
|
20
20
|
include Helpers::Async
|
|
21
|
+
include Helpers::ConfigImporter.new(
|
|
22
|
+
worker_job_call_wrapper: %i[internal processing worker_job_call_wrapper],
|
|
23
|
+
monitor: %i[monitor]
|
|
24
|
+
)
|
|
21
25
|
|
|
22
26
|
# @return [String] id of this worker
|
|
23
27
|
attr_reader :id
|
|
@@ -27,6 +31,7 @@ module Karafka
|
|
|
27
31
|
def initialize(jobs_queue)
|
|
28
32
|
@id = SecureRandom.hex(6)
|
|
29
33
|
@jobs_queue = jobs_queue
|
|
34
|
+
@non_wrapped_flow = worker_job_call_wrapper == false
|
|
30
35
|
end
|
|
31
36
|
|
|
32
37
|
private
|
|
@@ -49,22 +54,30 @@ module Karafka
|
|
|
49
54
|
instrument_details = { caller: self, job: job, jobs_queue: @jobs_queue }
|
|
50
55
|
|
|
51
56
|
if job
|
|
52
|
-
|
|
57
|
+
job.wrap do
|
|
58
|
+
monitor.instrument('worker.process', instrument_details)
|
|
53
59
|
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
monitor.instrument('worker.processed', instrument_details) do
|
|
61
|
+
job.before_call
|
|
56
62
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
# If a job is marked as non blocking, we can run a tick in the job queue and if there
|
|
64
|
+
# are no other blocking factors, the job queue will be unlocked.
|
|
65
|
+
# If this does not run, all the things will be blocking and job queue won't allow to
|
|
66
|
+
# pass it until done.
|
|
67
|
+
@jobs_queue.tick(job.group_id) if job.non_blocking?
|
|
62
68
|
|
|
63
|
-
|
|
69
|
+
if @non_wrapped_flow
|
|
70
|
+
job.call
|
|
71
|
+
else
|
|
72
|
+
worker_job_call_wrapper.wrap do
|
|
73
|
+
job.call
|
|
74
|
+
end
|
|
75
|
+
end
|
|
64
76
|
|
|
65
|
-
|
|
77
|
+
job.after_call
|
|
66
78
|
|
|
67
|
-
|
|
79
|
+
true
|
|
80
|
+
end
|
|
68
81
|
end
|
|
69
82
|
else
|
|
70
83
|
false
|
|
@@ -73,7 +86,7 @@ module Karafka
|
|
|
73
86
|
# rubocop:disable Lint/RescueException
|
|
74
87
|
rescue Exception => e
|
|
75
88
|
# rubocop:enable Lint/RescueException
|
|
76
|
-
|
|
89
|
+
monitor.instrument(
|
|
77
90
|
'error.occurred',
|
|
78
91
|
caller: self,
|
|
79
92
|
job: job,
|
|
@@ -89,7 +102,7 @@ module Karafka
|
|
|
89
102
|
end
|
|
90
103
|
|
|
91
104
|
# Always publish info, that we completed all the work despite its result
|
|
92
|
-
|
|
105
|
+
monitor.instrument('worker.completed', instrument_details)
|
|
93
106
|
end
|
|
94
107
|
end
|
|
95
108
|
end
|
data/lib/karafka/railtie.rb
CHANGED
|
@@ -65,48 +65,6 @@ if Karafka.rails?
|
|
|
65
65
|
app.config.autoload_paths += %w[app/consumers]
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
initializer 'karafka.configure_rails_code_reloader' do
|
|
69
|
-
# There are components that won't work with older Rails version, so we check it and
|
|
70
|
-
# provide a failover
|
|
71
|
-
rails6plus = Rails.gem_version >= Gem::Version.new('6.0.0')
|
|
72
|
-
|
|
73
|
-
next unless Rails.env.development?
|
|
74
|
-
next unless ENV.key?('KARAFKA_CLI')
|
|
75
|
-
next unless rails6plus
|
|
76
|
-
|
|
77
|
-
# We can have many listeners, but it does not matter in which we will reload the code
|
|
78
|
-
# as long as all the consumers will be re-created as Rails reload is thread-safe
|
|
79
|
-
::Karafka::App.monitor.subscribe('connection.listener.fetch_loop') do
|
|
80
|
-
# If consumer persistence is enabled, no reason to reload because we will still keep
|
|
81
|
-
# old consumer instances in memory.
|
|
82
|
-
next if Karafka::App.config.consumer_persistence
|
|
83
|
-
# Reload code each time there is a change in the code
|
|
84
|
-
next unless Rails.application.reloaders.any?(&:updated?)
|
|
85
|
-
|
|
86
|
-
Rails.application.reloader.reload!
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
initializer 'karafka.release_active_record_connections' do
|
|
91
|
-
rails7plus = Rails.gem_version >= Gem::Version.new('7.0.0')
|
|
92
|
-
|
|
93
|
-
ActiveSupport.on_load(:active_record) do
|
|
94
|
-
::Karafka::App.monitor.subscribe('worker.completed') do
|
|
95
|
-
# Always release the connection after processing is done. Otherwise thread may hang
|
|
96
|
-
# blocking the reload and further processing
|
|
97
|
-
# @see https://github.com/rails/rails/issues/44183
|
|
98
|
-
#
|
|
99
|
-
# The change technically happens in 7.1 but 7.0 already supports this so we can make
|
|
100
|
-
# a proper change for 7.0+
|
|
101
|
-
if rails7plus
|
|
102
|
-
ActiveRecord::Base.connection_handler.clear_active_connections!
|
|
103
|
-
else
|
|
104
|
-
ActiveRecord::Base.clear_active_connections!
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
68
|
initializer 'karafka.require_karafka_boot_file' do |app|
|
|
111
69
|
rails6plus = Rails.gem_version >= Gem::Version.new('6.0.0')
|
|
112
70
|
|
|
@@ -136,6 +94,17 @@ if Karafka.rails?
|
|
|
136
94
|
end
|
|
137
95
|
end
|
|
138
96
|
end
|
|
97
|
+
|
|
98
|
+
initializer 'karafka.configure_worker_external_executor' do |app|
|
|
99
|
+
app.config.after_initialize do
|
|
100
|
+
app_config = Karafka::App.config
|
|
101
|
+
|
|
102
|
+
# We need to wrap execution of the core user code with a wrapper in case of Rails, so
|
|
103
|
+
# the auto-reload works as expected
|
|
104
|
+
worker_job_call_wrapper = app_config.consumer_persistence ? app.executor : app.reloader
|
|
105
|
+
app_config.internal.processing.worker_job_call_wrapper = worker_job_call_wrapper
|
|
106
|
+
end
|
|
107
|
+
end
|
|
139
108
|
end
|
|
140
109
|
end
|
|
141
110
|
end
|
|
@@ -48,6 +48,10 @@ module Karafka
|
|
|
48
48
|
|
|
49
49
|
instance_eval(&block)
|
|
50
50
|
|
|
51
|
+
# Ensures high-level routing details consistency
|
|
52
|
+
# Contains checks that require knowledge about all the consumer groups to operate
|
|
53
|
+
Contracts::Routing.new.validate!(map(&:to_h))
|
|
54
|
+
|
|
51
55
|
each do |consumer_group|
|
|
52
56
|
# Validate consumer group settings
|
|
53
57
|
Contracts::ConsumerGroup.new.validate!(consumer_group.to_h)
|
|
@@ -63,6 +67,20 @@ module Karafka
|
|
|
63
67
|
end
|
|
64
68
|
end
|
|
65
69
|
|
|
70
|
+
# Clear out the drawn routes.
|
|
71
|
+
alias array_clear clear
|
|
72
|
+
private :array_clear
|
|
73
|
+
|
|
74
|
+
# Clear routes and draw them again with the given block. Helpful for testing purposes.
|
|
75
|
+
# @param block [Proc] block we will evaluate within the builder context
|
|
76
|
+
def redraw(&block)
|
|
77
|
+
@mutex.synchronize do
|
|
78
|
+
@draws.clear
|
|
79
|
+
array_clear
|
|
80
|
+
end
|
|
81
|
+
draw(&block)
|
|
82
|
+
end
|
|
83
|
+
|
|
66
84
|
# @return [Array<Karafka::Routing::ConsumerGroup>] only active consumer groups that
|
|
67
85
|
# we want to use. Since Karafka supports multi-process setup, we need to be able
|
|
68
86
|
# to pick only those consumer groups that should be active in our given process context
|
|
@@ -75,7 +93,7 @@ module Karafka
|
|
|
75
93
|
@mutex.synchronize do
|
|
76
94
|
@defaults = EMPTY_DEFAULTS
|
|
77
95
|
@draws.clear
|
|
78
|
-
|
|
96
|
+
array_clear
|
|
79
97
|
end
|
|
80
98
|
end
|
|
81
99
|
|
|
@@ -8,6 +8,12 @@ module Karafka
|
|
|
8
8
|
# @note A single consumer group represents Kafka consumer group, but it may not match 1:1 with
|
|
9
9
|
# subscription groups. There can be more subscription groups than consumer groups
|
|
10
10
|
class ConsumerGroup
|
|
11
|
+
include Helpers::ConfigImporter.new(
|
|
12
|
+
activity_manager: %i[internal routing activity_manager],
|
|
13
|
+
builder: %i[internal routing builder],
|
|
14
|
+
subscription_groups_builder: %i[internal routing subscription_groups_builder]
|
|
15
|
+
)
|
|
16
|
+
|
|
11
17
|
attr_reader :id, :topics, :name
|
|
12
18
|
|
|
13
19
|
# This is a "virtual" attribute that is not building subscription groups.
|
|
@@ -32,7 +38,7 @@ module Karafka
|
|
|
32
38
|
|
|
33
39
|
# @return [Boolean] true if this consumer group should be active in our current process
|
|
34
40
|
def active?
|
|
35
|
-
|
|
41
|
+
activity_manager.active?(:consumer_groups, name)
|
|
36
42
|
end
|
|
37
43
|
|
|
38
44
|
# Builds a topic representation inside of a current consumer group route
|
|
@@ -43,7 +49,7 @@ module Karafka
|
|
|
43
49
|
topic = Topic.new(name, self)
|
|
44
50
|
@topics << Proxy.new(
|
|
45
51
|
topic,
|
|
46
|
-
|
|
52
|
+
builder.defaults,
|
|
47
53
|
&block
|
|
48
54
|
).target
|
|
49
55
|
built_topic = @topics.last
|
|
@@ -72,11 +78,7 @@ module Karafka
|
|
|
72
78
|
# @return [Array<Routing::SubscriptionGroup>] all the subscription groups build based on
|
|
73
79
|
# the consumer group topics
|
|
74
80
|
def subscription_groups
|
|
75
|
-
@subscription_groups ||=
|
|
76
|
-
.internal
|
|
77
|
-
.routing
|
|
78
|
-
.subscription_groups_builder
|
|
79
|
-
.call(topics)
|
|
81
|
+
@subscription_groups ||= subscription_groups_builder.call(topics)
|
|
80
82
|
end
|
|
81
83
|
|
|
82
84
|
# Hashed version of consumer group that can be used for validation purposes
|
|
@@ -88,13 +90,6 @@ module Karafka
|
|
|
88
90
|
id: id
|
|
89
91
|
}.freeze
|
|
90
92
|
end
|
|
91
|
-
|
|
92
|
-
private
|
|
93
|
-
|
|
94
|
-
# @return [Karafka::Core::Configurable::Node] root node config
|
|
95
|
-
def config
|
|
96
|
-
::Karafka::App.config
|
|
97
|
-
end
|
|
98
93
|
end
|
|
99
94
|
end
|
|
100
95
|
end
|
|
@@ -21,6 +21,9 @@ module Karafka
|
|
|
21
21
|
:dispatch_method,
|
|
22
22
|
# Should we use `#mark_as_consumed` or `#mark_as_consumed!` (in flows that mark)
|
|
23
23
|
:marking_method,
|
|
24
|
+
# Should we mark as consumed after dispatch or not. True for most cases, except MOM where
|
|
25
|
+
# it is on user to decide (false by default)
|
|
26
|
+
:mark_after_dispatch,
|
|
24
27
|
# Initialize with kwargs
|
|
25
28
|
keyword_init: true
|
|
26
29
|
) do
|
|
@@ -21,6 +21,7 @@ module Karafka
|
|
|
21
21
|
required(:independent) { |val| [true, false].include?(val) }
|
|
22
22
|
required(:max_retries) { |val| val.is_a?(Integer) && val >= 0 }
|
|
23
23
|
required(:transactional) { |val| [true, false].include?(val) }
|
|
24
|
+
required(:mark_after_dispatch) { |val| [true, false, nil].include?(val) }
|
|
24
25
|
|
|
25
26
|
required(:dispatch_method) do |val|
|
|
26
27
|
%i[produce_async produce_sync].include?(val)
|
|
@@ -22,6 +22,9 @@ module Karafka
|
|
|
22
22
|
# whether dispatch on dlq should be sync or async (async by default)
|
|
23
23
|
# @param marking_method [Symbol] `:mark_as_consumed` or `:mark_as_consumed!`. Describes
|
|
24
24
|
# whether marking on DLQ should be async or sync (async by default)
|
|
25
|
+
# @param mark_after_dispatch [Boolean, nil] Should we mark after dispatch. `nil` means
|
|
26
|
+
# that the default strategy approach to marking will be used. `true` or `false`
|
|
27
|
+
# overwrites the default
|
|
25
28
|
# @return [Config] defined config
|
|
26
29
|
def dead_letter_queue(
|
|
27
30
|
max_retries: DEFAULT_MAX_RETRIES,
|
|
@@ -29,7 +32,8 @@ module Karafka
|
|
|
29
32
|
independent: false,
|
|
30
33
|
transactional: true,
|
|
31
34
|
dispatch_method: :produce_async,
|
|
32
|
-
marking_method: :mark_as_consumed
|
|
35
|
+
marking_method: :mark_as_consumed,
|
|
36
|
+
mark_after_dispatch: nil
|
|
33
37
|
)
|
|
34
38
|
@dead_letter_queue ||= Config.new(
|
|
35
39
|
active: !topic.nil?,
|
|
@@ -38,7 +42,8 @@ module Karafka
|
|
|
38
42
|
independent: independent,
|
|
39
43
|
transactional: transactional,
|
|
40
44
|
dispatch_method: dispatch_method,
|
|
41
|
-
marking_method: marking_method
|
|
45
|
+
marking_method: marking_method,
|
|
46
|
+
mark_after_dispatch: mark_after_dispatch
|
|
42
47
|
)
|
|
43
48
|
end
|
|
44
49
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Karafka
|
|
4
|
+
module Routing
|
|
5
|
+
module Features
|
|
6
|
+
class Eofed < Base
|
|
7
|
+
# Config of this feature
|
|
8
|
+
Config = Struct.new(
|
|
9
|
+
:active,
|
|
10
|
+
keyword_init: true
|
|
11
|
+
) { alias_method :active?, :active }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Karafka
|
|
4
|
+
module Routing
|
|
5
|
+
module Features
|
|
6
|
+
class Eofed < Base
|
|
7
|
+
# Eofed related contracts namespace
|
|
8
|
+
module Contracts
|
|
9
|
+
# Contract for eofed topic setup
|
|
10
|
+
class Topic < Karafka::Contracts::Base
|
|
11
|
+
configure do |config|
|
|
12
|
+
config.error_messages = YAML.safe_load(
|
|
13
|
+
File.read(
|
|
14
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'errors.yml')
|
|
15
|
+
)
|
|
16
|
+
).fetch('en').fetch('validations').fetch('topic')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
nested :eofed do
|
|
20
|
+
required(:active) { |val| [true, false].include?(val) }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
virtual do |data, errors|
|
|
24
|
+
next unless errors.empty?
|
|
25
|
+
|
|
26
|
+
eofed = data[:eofed]
|
|
27
|
+
|
|
28
|
+
next unless eofed[:active]
|
|
29
|
+
|
|
30
|
+
next if data[:kafka][:'enable.partition.eof']
|
|
31
|
+
|
|
32
|
+
[[%i[eofed kafka], :enable]]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Karafka
|
|
4
|
+
module Routing
|
|
5
|
+
module Features
|
|
6
|
+
class Eofed < Base
|
|
7
|
+
# Routing topic eofed API
|
|
8
|
+
module Topic
|
|
9
|
+
# @param active [Boolean] should the `#eofed` job run on eof
|
|
10
|
+
def eofed(active = false)
|
|
11
|
+
@eofed ||= Config.new(
|
|
12
|
+
active: active
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @return [Boolean] Are `#eofed` jobs active
|
|
17
|
+
def eofed?
|
|
18
|
+
eofed.active?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return [Hash] topic setup hash
|
|
22
|
+
def to_h
|
|
23
|
+
super.merge(
|
|
24
|
+
eofed: eofed.to_h
|
|
25
|
+
).freeze
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Karafka
|
|
4
|
+
module Routing
|
|
5
|
+
module Features
|
|
6
|
+
# Namespace for feature allowing to enable the `#eofed` jobs.
|
|
7
|
+
# We do not enable it always because users may only be interested in fast eofed yielding
|
|
8
|
+
# without running the `#eofed` operation at all. This safes on empty cycles of running
|
|
9
|
+
# pointless empty jobs.
|
|
10
|
+
class Eofed < Base
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|