karafka 1.4.12 → 2.2.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +10 -9
- data/.github/workflows/ci.yml +169 -31
- data/.rspec +4 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +716 -607
- data/CONTRIBUTING.md +10 -19
- data/Gemfile +7 -0
- data/Gemfile.lock +69 -92
- data/LICENSE +17 -0
- data/LICENSE-COMM +89 -0
- data/LICENSE-LGPL +165 -0
- data/README.md +48 -47
- data/bin/benchmarks +99 -0
- data/bin/create_token +22 -0
- data/bin/integrations +310 -0
- data/bin/karafka +5 -14
- data/bin/record_rss +50 -0
- data/bin/rspecs +6 -0
- data/bin/scenario +29 -0
- data/bin/stress_many +13 -0
- data/bin/stress_one +13 -0
- data/bin/verify_license_integrity +37 -0
- data/bin/wait_for_kafka +24 -0
- data/certs/cert_chain.pem +26 -0
- data/certs/karafka-pro.pem +11 -0
- data/config/locales/errors.yml +97 -0
- data/config/locales/pro_errors.yml +59 -0
- data/docker-compose.yml +19 -11
- data/karafka.gemspec +26 -22
- data/lib/active_job/karafka.rb +17 -0
- data/lib/active_job/queue_adapters/karafka_adapter.rb +32 -0
- data/lib/karafka/active_job/consumer.rb +49 -0
- data/lib/karafka/active_job/current_attributes/loading.rb +36 -0
- data/lib/karafka/active_job/current_attributes/persistence.rb +28 -0
- data/lib/karafka/active_job/current_attributes.rb +42 -0
- data/lib/karafka/active_job/dispatcher.rb +69 -0
- data/lib/karafka/active_job/job_extensions.rb +34 -0
- data/lib/karafka/active_job/job_options_contract.rb +32 -0
- data/lib/karafka/admin.rb +313 -0
- data/lib/karafka/app.rb +47 -23
- data/lib/karafka/base_consumer.rb +260 -29
- data/lib/karafka/cli/base.rb +67 -36
- data/lib/karafka/cli/console.rb +18 -12
- data/lib/karafka/cli/help.rb +24 -0
- data/lib/karafka/cli/info.rb +47 -12
- data/lib/karafka/cli/install.rb +23 -14
- data/lib/karafka/cli/server.rb +101 -44
- data/lib/karafka/cli/topics.rb +146 -0
- data/lib/karafka/cli.rb +24 -27
- data/lib/karafka/connection/client.rb +553 -90
- data/lib/karafka/connection/consumer_group_coordinator.rb +48 -0
- data/lib/karafka/connection/listener.rb +294 -38
- data/lib/karafka/connection/listeners_batch.rb +40 -0
- data/lib/karafka/connection/messages_buffer.rb +84 -0
- data/lib/karafka/connection/pauses_manager.rb +46 -0
- data/lib/karafka/connection/proxy.rb +98 -0
- data/lib/karafka/connection/raw_messages_buffer.rb +101 -0
- data/lib/karafka/connection/rebalance_manager.rb +105 -0
- data/lib/karafka/contracts/base.rb +17 -0
- data/lib/karafka/contracts/config.rb +130 -11
- data/lib/karafka/contracts/consumer_group.rb +32 -187
- data/lib/karafka/contracts/server_cli_options.rb +80 -19
- data/lib/karafka/contracts/topic.rb +65 -0
- data/lib/karafka/contracts.rb +1 -1
- data/lib/karafka/embedded.rb +36 -0
- data/lib/karafka/env.rb +46 -0
- data/lib/karafka/errors.rb +37 -21
- data/lib/karafka/helpers/async.rb +33 -0
- data/lib/karafka/helpers/colorize.rb +26 -0
- data/lib/karafka/helpers/multi_delegator.rb +2 -2
- data/lib/karafka/instrumentation/callbacks/error.rb +39 -0
- data/lib/karafka/instrumentation/callbacks/rebalance.rb +64 -0
- data/lib/karafka/instrumentation/callbacks/statistics.rb +51 -0
- data/lib/karafka/instrumentation/logger_listener.rb +303 -0
- data/lib/karafka/instrumentation/monitor.rb +13 -61
- data/lib/karafka/instrumentation/notifications.rb +79 -0
- data/lib/karafka/instrumentation/proctitle_listener.rb +7 -16
- data/lib/karafka/instrumentation/vendors/appsignal/base.rb +30 -0
- data/lib/karafka/instrumentation/vendors/appsignal/client.rb +122 -0
- data/lib/karafka/instrumentation/vendors/appsignal/dashboard.json +222 -0
- data/lib/karafka/instrumentation/vendors/appsignal/errors_listener.rb +30 -0
- data/lib/karafka/instrumentation/vendors/appsignal/metrics_listener.rb +331 -0
- data/lib/karafka/instrumentation/vendors/datadog/dashboard.json +1 -0
- data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +155 -0
- data/lib/karafka/instrumentation/vendors/datadog/metrics_listener.rb +264 -0
- data/lib/karafka/instrumentation/vendors/kubernetes/liveness_listener.rb +176 -0
- data/lib/karafka/licenser.rb +78 -0
- data/lib/karafka/messages/batch_metadata.rb +52 -0
- data/lib/karafka/messages/builders/batch_metadata.rb +60 -0
- data/lib/karafka/messages/builders/message.rb +40 -0
- data/lib/karafka/messages/builders/messages.rb +36 -0
- data/lib/karafka/{params/params.rb → messages/message.rb} +20 -13
- data/lib/karafka/messages/messages.rb +71 -0
- data/lib/karafka/{params → messages}/metadata.rb +4 -6
- data/lib/karafka/messages/parser.rb +14 -0
- data/lib/karafka/messages/seek.rb +12 -0
- data/lib/karafka/patches/rdkafka/bindings.rb +122 -0
- data/lib/karafka/patches/rdkafka/opaque.rb +36 -0
- data/lib/karafka/pro/active_job/consumer.rb +47 -0
- data/lib/karafka/pro/active_job/dispatcher.rb +86 -0
- data/lib/karafka/pro/active_job/job_options_contract.rb +45 -0
- data/lib/karafka/pro/cleaner/errors.rb +27 -0
- data/lib/karafka/pro/cleaner/messages/message.rb +46 -0
- data/lib/karafka/pro/cleaner/messages/messages.rb +42 -0
- data/lib/karafka/pro/cleaner.rb +41 -0
- data/lib/karafka/pro/contracts/base.rb +23 -0
- data/lib/karafka/pro/contracts/server_cli_options.rb +111 -0
- data/lib/karafka/pro/encryption/cipher.rb +58 -0
- data/lib/karafka/pro/encryption/contracts/config.rb +79 -0
- data/lib/karafka/pro/encryption/errors.rb +27 -0
- data/lib/karafka/pro/encryption/messages/middleware.rb +46 -0
- data/lib/karafka/pro/encryption/messages/parser.rb +56 -0
- data/lib/karafka/pro/encryption/setup/config.rb +48 -0
- data/lib/karafka/pro/encryption.rb +47 -0
- data/lib/karafka/pro/iterator/expander.rb +95 -0
- data/lib/karafka/pro/iterator/tpl_builder.rb +155 -0
- data/lib/karafka/pro/iterator.rb +170 -0
- data/lib/karafka/pro/loader.rb +106 -0
- data/lib/karafka/pro/performance_tracker.rb +84 -0
- data/lib/karafka/pro/processing/collapser.rb +62 -0
- data/lib/karafka/pro/processing/coordinator.rb +147 -0
- data/lib/karafka/pro/processing/filters/base.rb +61 -0
- data/lib/karafka/pro/processing/filters/delayer.rb +70 -0
- data/lib/karafka/pro/processing/filters/expirer.rb +51 -0
- data/lib/karafka/pro/processing/filters/inline_insights_delayer.rb +78 -0
- data/lib/karafka/pro/processing/filters/throttler.rb +84 -0
- data/lib/karafka/pro/processing/filters/virtual_limiter.rb +52 -0
- data/lib/karafka/pro/processing/filters_applier.rb +105 -0
- data/lib/karafka/pro/processing/jobs/consume_non_blocking.rb +39 -0
- data/lib/karafka/pro/processing/jobs/revoked_non_blocking.rb +37 -0
- data/lib/karafka/pro/processing/jobs_builder.rb +50 -0
- data/lib/karafka/pro/processing/partitioner.rb +69 -0
- data/lib/karafka/pro/processing/scheduler.rb +75 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom.rb +70 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom_vp.rb +76 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom.rb +72 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom_vp.rb +76 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom.rb +66 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom_vp.rb +70 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_mom.rb +64 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_mom_vp.rb +69 -0
- data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom.rb +38 -0
- data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom_vp.rb +66 -0
- data/lib/karafka/pro/processing/strategies/aj/ftr_mom.rb +38 -0
- data/lib/karafka/pro/processing/strategies/aj/ftr_mom_vp.rb +58 -0
- data/lib/karafka/pro/processing/strategies/aj/lrj_mom.rb +37 -0
- data/lib/karafka/pro/processing/strategies/aj/lrj_mom_vp.rb +82 -0
- data/lib/karafka/pro/processing/strategies/aj/mom.rb +36 -0
- data/lib/karafka/pro/processing/strategies/aj/mom_vp.rb +52 -0
- data/lib/karafka/pro/processing/strategies/base.rb +26 -0
- data/lib/karafka/pro/processing/strategies/default.rb +105 -0
- data/lib/karafka/pro/processing/strategies/dlq/default.rb +137 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr.rb +61 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj.rb +75 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom.rb +71 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom_vp.rb +43 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_vp.rb +41 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_mom.rb +69 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_mom_vp.rb +41 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_vp.rb +40 -0
- data/lib/karafka/pro/processing/strategies/dlq/lrj.rb +64 -0
- data/lib/karafka/pro/processing/strategies/dlq/lrj_mom.rb +65 -0
- data/lib/karafka/pro/processing/strategies/dlq/lrj_mom_vp.rb +36 -0
- data/lib/karafka/pro/processing/strategies/dlq/lrj_vp.rb +39 -0
- data/lib/karafka/pro/processing/strategies/dlq/mom.rb +68 -0
- data/lib/karafka/pro/processing/strategies/dlq/mom_vp.rb +37 -0
- data/lib/karafka/pro/processing/strategies/dlq/vp.rb +40 -0
- data/lib/karafka/pro/processing/strategies/ftr/default.rb +111 -0
- data/lib/karafka/pro/processing/strategies/ftr/vp.rb +40 -0
- data/lib/karafka/pro/processing/strategies/lrj/default.rb +85 -0
- data/lib/karafka/pro/processing/strategies/lrj/ftr.rb +69 -0
- data/lib/karafka/pro/processing/strategies/lrj/ftr_mom.rb +67 -0
- data/lib/karafka/pro/processing/strategies/lrj/ftr_mom_vp.rb +40 -0
- data/lib/karafka/pro/processing/strategies/lrj/ftr_vp.rb +39 -0
- data/lib/karafka/pro/processing/strategies/lrj/mom.rb +77 -0
- data/lib/karafka/pro/processing/strategies/lrj/mom_vp.rb +38 -0
- data/lib/karafka/pro/processing/strategies/lrj/vp.rb +36 -0
- data/lib/karafka/pro/processing/strategies/mom/default.rb +46 -0
- data/lib/karafka/pro/processing/strategies/mom/ftr.rb +53 -0
- data/lib/karafka/pro/processing/strategies/mom/ftr_vp.rb +37 -0
- data/lib/karafka/pro/processing/strategies/mom/vp.rb +35 -0
- data/lib/karafka/pro/processing/strategies/vp/default.rb +124 -0
- data/lib/karafka/pro/processing/strategies.rb +22 -0
- data/lib/karafka/pro/processing/strategy_selector.rb +84 -0
- data/lib/karafka/pro/processing/virtual_offset_manager.rb +147 -0
- data/lib/karafka/pro/routing/features/active_job/builder.rb +45 -0
- data/lib/karafka/pro/routing/features/active_job.rb +26 -0
- data/lib/karafka/pro/routing/features/base.rb +24 -0
- data/lib/karafka/pro/routing/features/dead_letter_queue/contracts/topic.rb +53 -0
- data/lib/karafka/pro/routing/features/dead_letter_queue.rb +27 -0
- data/lib/karafka/pro/routing/features/delaying/config.rb +27 -0
- data/lib/karafka/pro/routing/features/delaying/contracts/topic.rb +41 -0
- data/lib/karafka/pro/routing/features/delaying/topic.rb +59 -0
- data/lib/karafka/pro/routing/features/delaying.rb +29 -0
- data/lib/karafka/pro/routing/features/expiring/config.rb +27 -0
- data/lib/karafka/pro/routing/features/expiring/contracts/topic.rb +41 -0
- data/lib/karafka/pro/routing/features/expiring/topic.rb +59 -0
- data/lib/karafka/pro/routing/features/expiring.rb +27 -0
- data/lib/karafka/pro/routing/features/filtering/config.rb +40 -0
- data/lib/karafka/pro/routing/features/filtering/contracts/topic.rb +44 -0
- data/lib/karafka/pro/routing/features/filtering/topic.rb +51 -0
- data/lib/karafka/pro/routing/features/filtering.rb +27 -0
- data/lib/karafka/pro/routing/features/inline_insights/config.rb +32 -0
- data/lib/karafka/pro/routing/features/inline_insights/contracts/topic.rb +41 -0
- data/lib/karafka/pro/routing/features/inline_insights/topic.rb +52 -0
- data/lib/karafka/pro/routing/features/inline_insights.rb +26 -0
- data/lib/karafka/pro/routing/features/long_running_job/config.rb +28 -0
- data/lib/karafka/pro/routing/features/long_running_job/contracts/topic.rb +40 -0
- data/lib/karafka/pro/routing/features/long_running_job/topic.rb +42 -0
- data/lib/karafka/pro/routing/features/long_running_job.rb +28 -0
- data/lib/karafka/pro/routing/features/patterns/builder.rb +38 -0
- data/lib/karafka/pro/routing/features/patterns/config.rb +54 -0
- data/lib/karafka/pro/routing/features/patterns/consumer_group.rb +72 -0
- data/lib/karafka/pro/routing/features/patterns/contracts/consumer_group.rb +62 -0
- data/lib/karafka/pro/routing/features/patterns/contracts/pattern.rb +46 -0
- data/lib/karafka/pro/routing/features/patterns/contracts/topic.rb +41 -0
- data/lib/karafka/pro/routing/features/patterns/detector.rb +71 -0
- data/lib/karafka/pro/routing/features/patterns/pattern.rb +95 -0
- data/lib/karafka/pro/routing/features/patterns/patterns.rb +35 -0
- data/lib/karafka/pro/routing/features/patterns/topic.rb +50 -0
- data/lib/karafka/pro/routing/features/patterns/topics.rb +53 -0
- data/lib/karafka/pro/routing/features/patterns.rb +33 -0
- data/lib/karafka/pro/routing/features/pausing/contracts/topic.rb +51 -0
- data/lib/karafka/pro/routing/features/pausing/topic.rb +44 -0
- data/lib/karafka/pro/routing/features/pausing.rb +25 -0
- data/lib/karafka/pro/routing/features/throttling/config.rb +32 -0
- data/lib/karafka/pro/routing/features/throttling/contracts/topic.rb +44 -0
- data/lib/karafka/pro/routing/features/throttling/topic.rb +69 -0
- data/lib/karafka/pro/routing/features/throttling.rb +30 -0
- data/lib/karafka/pro/routing/features/virtual_partitions/config.rb +30 -0
- data/lib/karafka/pro/routing/features/virtual_partitions/contracts/topic.rb +55 -0
- data/lib/karafka/pro/routing/features/virtual_partitions/topic.rb +56 -0
- data/lib/karafka/pro/routing/features/virtual_partitions.rb +27 -0
- data/lib/karafka/pro.rb +13 -0
- data/lib/karafka/process.rb +24 -8
- data/lib/karafka/processing/coordinator.rb +181 -0
- data/lib/karafka/processing/coordinators_buffer.rb +62 -0
- data/lib/karafka/processing/executor.rb +155 -0
- data/lib/karafka/processing/executors_buffer.rb +72 -0
- data/lib/karafka/processing/expansions_selector.rb +22 -0
- data/lib/karafka/processing/inline_insights/consumer.rb +41 -0
- data/lib/karafka/processing/inline_insights/listener.rb +19 -0
- data/lib/karafka/processing/inline_insights/tracker.rb +128 -0
- data/lib/karafka/processing/jobs/base.rb +55 -0
- data/lib/karafka/processing/jobs/consume.rb +45 -0
- data/lib/karafka/processing/jobs/idle.rb +24 -0
- data/lib/karafka/processing/jobs/revoked.rb +22 -0
- data/lib/karafka/processing/jobs/shutdown.rb +23 -0
- data/lib/karafka/processing/jobs_builder.rb +28 -0
- data/lib/karafka/processing/jobs_queue.rb +150 -0
- data/lib/karafka/processing/partitioner.rb +24 -0
- data/lib/karafka/processing/result.rb +42 -0
- data/lib/karafka/processing/scheduler.rb +22 -0
- data/lib/karafka/processing/strategies/aj_dlq_mom.rb +44 -0
- data/lib/karafka/processing/strategies/aj_mom.rb +21 -0
- data/lib/karafka/processing/strategies/base.rb +52 -0
- data/lib/karafka/processing/strategies/default.rb +158 -0
- data/lib/karafka/processing/strategies/dlq.rb +88 -0
- data/lib/karafka/processing/strategies/dlq_mom.rb +49 -0
- data/lib/karafka/processing/strategies/mom.rb +29 -0
- data/lib/karafka/processing/strategy_selector.rb +47 -0
- data/lib/karafka/processing/worker.rb +93 -0
- data/lib/karafka/processing/workers_batch.rb +27 -0
- data/lib/karafka/railtie.rb +141 -0
- data/lib/karafka/routing/activity_manager.rb +84 -0
- data/lib/karafka/routing/builder.rb +45 -19
- data/lib/karafka/routing/consumer_group.rb +56 -20
- data/lib/karafka/routing/consumer_mapper.rb +1 -12
- data/lib/karafka/routing/features/active_job/builder.rb +33 -0
- data/lib/karafka/routing/features/active_job/config.rb +15 -0
- data/lib/karafka/routing/features/active_job/contracts/topic.rb +44 -0
- data/lib/karafka/routing/features/active_job/proxy.rb +14 -0
- data/lib/karafka/routing/features/active_job/topic.rb +33 -0
- data/lib/karafka/routing/features/active_job.rb +13 -0
- data/lib/karafka/routing/features/base/expander.rb +59 -0
- data/lib/karafka/routing/features/base.rb +71 -0
- data/lib/karafka/routing/features/dead_letter_queue/config.rb +19 -0
- data/lib/karafka/routing/features/dead_letter_queue/contracts/topic.rb +46 -0
- data/lib/karafka/routing/features/dead_letter_queue/topic.rb +41 -0
- data/lib/karafka/routing/features/dead_letter_queue.rb +16 -0
- data/lib/karafka/routing/features/declaratives/config.rb +18 -0
- data/lib/karafka/routing/features/declaratives/contracts/topic.rb +33 -0
- data/lib/karafka/routing/features/declaratives/topic.rb +44 -0
- data/lib/karafka/routing/features/declaratives.rb +14 -0
- data/lib/karafka/routing/features/inline_insights/config.rb +15 -0
- data/lib/karafka/routing/features/inline_insights/contracts/topic.rb +27 -0
- data/lib/karafka/routing/features/inline_insights/topic.rb +31 -0
- data/lib/karafka/routing/features/inline_insights.rb +40 -0
- data/lib/karafka/routing/features/manual_offset_management/config.rb +15 -0
- data/lib/karafka/routing/features/manual_offset_management/contracts/topic.rb +27 -0
- data/lib/karafka/routing/features/manual_offset_management/topic.rb +35 -0
- data/lib/karafka/routing/features/manual_offset_management.rb +18 -0
- data/lib/karafka/routing/proxy.rb +22 -21
- data/lib/karafka/routing/router.rb +24 -10
- data/lib/karafka/routing/subscription_group.rb +110 -0
- data/lib/karafka/routing/subscription_groups_builder.rb +65 -0
- data/lib/karafka/routing/topic.rb +87 -24
- data/lib/karafka/routing/topics.rb +46 -0
- data/lib/karafka/runner.rb +52 -0
- data/lib/karafka/serialization/json/deserializer.rb +7 -15
- data/lib/karafka/server.rb +113 -37
- data/lib/karafka/setup/attributes_map.rb +348 -0
- data/lib/karafka/setup/config.rb +256 -175
- data/lib/karafka/status.rb +54 -7
- data/lib/karafka/templates/example_consumer.rb.erb +16 -0
- data/lib/karafka/templates/karafka.rb.erb +33 -55
- data/lib/karafka/time_trackers/base.rb +14 -0
- data/lib/karafka/time_trackers/pause.rb +122 -0
- data/lib/karafka/time_trackers/poll.rb +69 -0
- data/lib/karafka/version.rb +1 -1
- data/lib/karafka.rb +91 -17
- data/renovate.json +9 -0
- data.tar.gz.sig +0 -0
- metadata +330 -168
- metadata.gz.sig +0 -0
- data/MIT-LICENCE +0 -18
- data/certs/mensfeld.pem +0 -25
- data/config/errors.yml +0 -41
- data/lib/karafka/assignment_strategies/round_robin.rb +0 -13
- data/lib/karafka/attributes_map.rb +0 -63
- data/lib/karafka/backends/inline.rb +0 -16
- data/lib/karafka/base_responder.rb +0 -226
- data/lib/karafka/cli/flow.rb +0 -48
- data/lib/karafka/cli/missingno.rb +0 -19
- data/lib/karafka/code_reloader.rb +0 -67
- data/lib/karafka/connection/api_adapter.rb +0 -158
- data/lib/karafka/connection/batch_delegator.rb +0 -55
- data/lib/karafka/connection/builder.rb +0 -23
- data/lib/karafka/connection/message_delegator.rb +0 -36
- data/lib/karafka/consumers/batch_metadata.rb +0 -10
- data/lib/karafka/consumers/callbacks.rb +0 -71
- data/lib/karafka/consumers/includer.rb +0 -64
- data/lib/karafka/consumers/responders.rb +0 -24
- data/lib/karafka/consumers/single_params.rb +0 -15
- data/lib/karafka/contracts/consumer_group_topic.rb +0 -19
- data/lib/karafka/contracts/responder_usage.rb +0 -54
- data/lib/karafka/fetcher.rb +0 -42
- data/lib/karafka/helpers/class_matcher.rb +0 -88
- data/lib/karafka/helpers/config_retriever.rb +0 -46
- data/lib/karafka/helpers/inflector.rb +0 -26
- data/lib/karafka/instrumentation/stdout_listener.rb +0 -140
- data/lib/karafka/params/batch_metadata.rb +0 -26
- data/lib/karafka/params/builders/batch_metadata.rb +0 -30
- data/lib/karafka/params/builders/params.rb +0 -38
- data/lib/karafka/params/builders/params_batch.rb +0 -25
- data/lib/karafka/params/params_batch.rb +0 -60
- data/lib/karafka/patches/ruby_kafka.rb +0 -47
- data/lib/karafka/persistence/client.rb +0 -29
- data/lib/karafka/persistence/consumers.rb +0 -45
- data/lib/karafka/persistence/topics.rb +0 -48
- data/lib/karafka/responders/builder.rb +0 -36
- data/lib/karafka/responders/topic.rb +0 -55
- data/lib/karafka/routing/topic_mapper.rb +0 -53
- data/lib/karafka/serialization/json/serializer.rb +0 -31
- data/lib/karafka/setup/configurators/water_drop.rb +0 -36
- data/lib/karafka/templates/application_responder.rb.erb +0 -11
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Processing
|
5
|
+
module Strategies
|
6
|
+
# When using manual offset management, we do not mark as consumed after successful processing
|
7
|
+
module Mom
|
8
|
+
include Default
|
9
|
+
|
10
|
+
# Apply strategy when only manual offset management is turned on
|
11
|
+
FEATURES = %i[
|
12
|
+
manual_offset_management
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
# When manual offset management is on, we do not mark anything as consumed automatically
|
16
|
+
# and we rely on the user to figure things out
|
17
|
+
def handle_after_consume
|
18
|
+
return if revoked?
|
19
|
+
|
20
|
+
if coordinator.success?
|
21
|
+
coordinator.pause_tracker.reset
|
22
|
+
else
|
23
|
+
retry_after_pause
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Processing
|
5
|
+
# Selector of appropriate processing strategy matching topic combinations
|
6
|
+
class StrategySelector
|
7
|
+
attr_reader :strategies
|
8
|
+
|
9
|
+
# Features we support in the OSS offering.
|
10
|
+
SUPPORTED_FEATURES = %i[
|
11
|
+
active_job
|
12
|
+
manual_offset_management
|
13
|
+
dead_letter_queue
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
# We load them once for performance reasons not to do too many lookups
|
18
|
+
@strategies = find_all
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param topic [Karafka::Routing::Topic] topic with settings based on which we find strategy
|
22
|
+
# @return [Module] module with proper strategy
|
23
|
+
def find(topic)
|
24
|
+
feature_set = SUPPORTED_FEATURES.map do |feature_name|
|
25
|
+
topic.public_send("#{feature_name}?") ? feature_name : nil
|
26
|
+
end
|
27
|
+
|
28
|
+
feature_set.compact!
|
29
|
+
|
30
|
+
@strategies.find do |strategy|
|
31
|
+
strategy::FEATURES.sort == feature_set.sort
|
32
|
+
end || raise(Errors::StrategyNotFoundError, topic.name)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# @return [Array<Module>] available strategies
|
38
|
+
def find_all
|
39
|
+
Strategies
|
40
|
+
.constants
|
41
|
+
.delete_if { |k| k == :Base }
|
42
|
+
.map { |k| Strategies.const_get(k) }
|
43
|
+
.uniq
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Processing
|
5
|
+
# Workers are used to run jobs in separate threads.
|
6
|
+
# Workers are the main processing units of the Karafka framework.
|
7
|
+
#
|
8
|
+
# Each job runs in three stages:
|
9
|
+
# - prepare - here we can run any code that we would need to run blocking before we allow
|
10
|
+
# the job to run fully async (non blocking). This will always run in a blocking
|
11
|
+
# way and can be used to make sure all the resources and external dependencies
|
12
|
+
# are satisfied before going async.
|
13
|
+
#
|
14
|
+
# - call - actual processing logic that can run sync or async
|
15
|
+
#
|
16
|
+
# - teardown - it should include any code that we want to run after we executed the user
|
17
|
+
# code. This can be used to unlock certain resources or do other things that are
|
18
|
+
# not user code but need to run after user code base is executed.
|
19
|
+
class Worker
|
20
|
+
include Helpers::Async
|
21
|
+
|
22
|
+
# @return [String] id of this worker
|
23
|
+
attr_reader :id
|
24
|
+
|
25
|
+
# @param jobs_queue [JobsQueue]
|
26
|
+
# @return [Worker]
|
27
|
+
def initialize(jobs_queue)
|
28
|
+
@id = SecureRandom.hex(6)
|
29
|
+
@jobs_queue = jobs_queue
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# Runs processing of jobs in a loop
|
35
|
+
# Stops when queue is closed.
|
36
|
+
def call
|
37
|
+
loop { break unless process }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Fetches a single job, processes it and marks as completed.
|
41
|
+
#
|
42
|
+
# @note We do not have error handling here, as no errors should propagate this far. If they
|
43
|
+
# do, it is a critical error and should bubble up.
|
44
|
+
#
|
45
|
+
# @note Upon closing the jobs queue, worker will close it's thread
|
46
|
+
def process
|
47
|
+
job = @jobs_queue.pop
|
48
|
+
|
49
|
+
instrument_details = { caller: self, job: job, jobs_queue: @jobs_queue }
|
50
|
+
|
51
|
+
if job
|
52
|
+
Karafka.monitor.instrument('worker.process', instrument_details)
|
53
|
+
|
54
|
+
Karafka.monitor.instrument('worker.processed', instrument_details) do
|
55
|
+
job.before_call
|
56
|
+
|
57
|
+
# If a job is marked as non blocking, we can run a tick in the job queue and if there
|
58
|
+
# are no other blocking factors, the job queue will be unlocked.
|
59
|
+
# If this does not run, all the things will be blocking and job queue won't allow to
|
60
|
+
# pass it until done.
|
61
|
+
@jobs_queue.tick(job.group_id) if job.non_blocking?
|
62
|
+
|
63
|
+
job.call
|
64
|
+
|
65
|
+
job.after_call
|
66
|
+
|
67
|
+
true
|
68
|
+
end
|
69
|
+
else
|
70
|
+
false
|
71
|
+
end
|
72
|
+
# We signal critical exceptions, notify and do not allow worker to fail
|
73
|
+
# rubocop:disable Lint/RescueException
|
74
|
+
rescue Exception => e
|
75
|
+
# rubocop:enable Lint/RescueException
|
76
|
+
Karafka.monitor.instrument(
|
77
|
+
'error.occurred',
|
78
|
+
caller: self,
|
79
|
+
job: job,
|
80
|
+
jobs_queue: @jobs_queue,
|
81
|
+
error: e,
|
82
|
+
type: 'worker.process.error'
|
83
|
+
)
|
84
|
+
ensure
|
85
|
+
# job can be nil when the queue is being closed
|
86
|
+
@jobs_queue.complete(job) if job
|
87
|
+
|
88
|
+
# Always publish info, that we completed all the work despite its result
|
89
|
+
Karafka.monitor.instrument('worker.completed', instrument_details)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Processing
|
5
|
+
# Abstraction layer around workers batch.
|
6
|
+
class WorkersBatch
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
# @param jobs_queue [JobsQueue]
|
10
|
+
# @return [WorkersBatch]
|
11
|
+
def initialize(jobs_queue)
|
12
|
+
@batch = Array.new(App.config.concurrency) { Processing::Worker.new(jobs_queue) }
|
13
|
+
end
|
14
|
+
|
15
|
+
# Iterates over available workers and yields each worker
|
16
|
+
# @param block [Proc] block we want to run
|
17
|
+
def each(&block)
|
18
|
+
@batch.each(&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Integer] number of workers in the batch
|
22
|
+
def size
|
23
|
+
@batch.size
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This file contains Railtie for auto-configuration
|
4
|
+
|
5
|
+
unless Karafka.rails?
|
6
|
+
# Without defining this in any way, Zeitwerk ain't happy so we do it that way
|
7
|
+
module Karafka
|
8
|
+
class Railtie
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
if Karafka.rails?
|
14
|
+
# Load ActiveJob adapter
|
15
|
+
require 'active_job/karafka'
|
16
|
+
|
17
|
+
# Setup env if configured (may be configured later by .net, etc)
|
18
|
+
ENV['KARAFKA_ENV'] ||= ENV['RAILS_ENV'] if ENV.key?('RAILS_ENV')
|
19
|
+
|
20
|
+
module Karafka
|
21
|
+
# Railtie for setting up Rails integration
|
22
|
+
class Railtie < Rails::Railtie
|
23
|
+
railtie_name :karafka
|
24
|
+
|
25
|
+
initializer 'karafka.active_job_integration' do
|
26
|
+
ActiveSupport.on_load(:active_job) do
|
27
|
+
# Extend ActiveJob with some Karafka specific ActiveJob magic
|
28
|
+
extend ::Karafka::ActiveJob::JobExtensions
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# This lines will make Karafka print to stdout like puma or unicorn when we run karafka
|
33
|
+
# server + will support code reloading with each fetched loop. We do it only for karafka
|
34
|
+
# based commands as Rails processes and console will have it enabled already
|
35
|
+
initializer 'karafka.configure_rails_logger' do
|
36
|
+
# Make Karafka uses Rails logger
|
37
|
+
::Karafka::App.config.logger = Rails.logger
|
38
|
+
|
39
|
+
next unless Rails.env.development?
|
40
|
+
next unless ENV.key?('KARAFKA_CLI')
|
41
|
+
# If we are already publishing to STDOUT, no need to add it again.
|
42
|
+
# If added again, would print stuff twice
|
43
|
+
next if ActiveSupport::Logger.logger_outputs_to?(Rails.logger, $stdout)
|
44
|
+
|
45
|
+
stdout_logger = ActiveSupport::Logger.new($stdout)
|
46
|
+
# Inherit the logger level from Rails, otherwise would always run with the debug level
|
47
|
+
stdout_logger.level = Rails.logger.level
|
48
|
+
|
49
|
+
rails71plus = Rails.gem_version >= Gem::Version.new('7.1.0')
|
50
|
+
|
51
|
+
# Rails 7.1 replaced the broadcast module with a broadcast logger
|
52
|
+
if rails71plus
|
53
|
+
Rails.logger.broadcast_to(stdout_logger)
|
54
|
+
else
|
55
|
+
Rails.logger.extend(
|
56
|
+
ActiveSupport::Logger.broadcast(
|
57
|
+
stdout_logger
|
58
|
+
)
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
initializer 'karafka.configure_rails_auto_load_paths' do |app|
|
64
|
+
# Consumers should autoload by default in the Rails app so they are visible
|
65
|
+
app.config.autoload_paths += %w[app/consumers]
|
66
|
+
end
|
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
|
+
initializer 'karafka.require_karafka_boot_file' do |app|
|
111
|
+
rails6plus = Rails.gem_version >= Gem::Version.new('6.0.0')
|
112
|
+
|
113
|
+
# If the boot file location is set to "false", we should not raise an exception and we
|
114
|
+
# should just not load karafka stuff. Setting this explicitly to false indicates, that
|
115
|
+
# karafka is part of the supply chain but it is not a first class citizen of a given
|
116
|
+
# system (may be just a dependency of a dependency), thus railtie should not kick in to
|
117
|
+
# load the non-existing boot file
|
118
|
+
next if Karafka.boot_file.to_s == 'false'
|
119
|
+
|
120
|
+
karafka_boot_file = Rails.root.join(Karafka.boot_file.to_s).to_s
|
121
|
+
|
122
|
+
# Provide more comprehensive error for when no boot file
|
123
|
+
unless File.exist?(karafka_boot_file)
|
124
|
+
raise(Karafka::Errors::MissingBootFileError, karafka_boot_file)
|
125
|
+
end
|
126
|
+
|
127
|
+
if rails6plus
|
128
|
+
app.reloader.to_prepare do
|
129
|
+
# Load Karafka boot file, so it can be used in Rails server context
|
130
|
+
require karafka_boot_file
|
131
|
+
end
|
132
|
+
else
|
133
|
+
# Load Karafka main setup for older Rails versions
|
134
|
+
app.config.after_initialize do
|
135
|
+
require karafka_boot_file
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Routing
|
5
|
+
# Allows us to get track of which consumer groups, subscription groups and topics are enabled
|
6
|
+
# or disabled via CLI
|
7
|
+
class ActivityManager
|
8
|
+
# Supported types of inclusions and exclusions
|
9
|
+
SUPPORTED_TYPES = %i[
|
10
|
+
consumer_groups
|
11
|
+
subscription_groups
|
12
|
+
topics
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@included = Hash.new { |h, k| h[k] = [] }
|
17
|
+
@excluded = Hash.new { |h, k| h[k] = [] }
|
18
|
+
end
|
19
|
+
|
20
|
+
# Adds resource to included/active
|
21
|
+
# @param type [Symbol] type for inclusion
|
22
|
+
# @param name [String] name of the element
|
23
|
+
def include(type, name)
|
24
|
+
validate!(type)
|
25
|
+
|
26
|
+
@included[type] << name
|
27
|
+
end
|
28
|
+
|
29
|
+
# Adds resource to excluded
|
30
|
+
# @param type [Symbol] type for inclusion
|
31
|
+
# @param name [String] name of the element
|
32
|
+
def exclude(type, name)
|
33
|
+
validate!(type)
|
34
|
+
|
35
|
+
@excluded[type] << name
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param type [Symbol] type for inclusion
|
39
|
+
# @param name [String] name of the element
|
40
|
+
# @return [Boolean] is the given resource active or not
|
41
|
+
def active?(type, name)
|
42
|
+
validate!(type)
|
43
|
+
|
44
|
+
included = @included[type]
|
45
|
+
excluded = @excluded[type]
|
46
|
+
|
47
|
+
# If nothing defined, all active by default
|
48
|
+
return true if included.empty? && excluded.empty?
|
49
|
+
# Inclusion supersedes exclusion in case someone wrote both
|
50
|
+
return true if !included.empty? && included.include?(name)
|
51
|
+
|
52
|
+
# If there are exclusions but our is not excluded and no inclusions or included, it's ok
|
53
|
+
!excluded.empty? &&
|
54
|
+
!excluded.include?(name) &&
|
55
|
+
(included.empty? || included.include?(name))
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Hash] accumulated data in a hash for validations
|
59
|
+
def to_h
|
60
|
+
(
|
61
|
+
SUPPORTED_TYPES.map { |type| ["include_#{type}".to_sym, @included[type]] } +
|
62
|
+
SUPPORTED_TYPES.map { |type| ["exclude_#{type}".to_sym, @excluded[type]] }
|
63
|
+
).to_h
|
64
|
+
end
|
65
|
+
|
66
|
+
# Clears the manager
|
67
|
+
def clear
|
68
|
+
@included.clear
|
69
|
+
@excluded.clear
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
# Checks if the type we want to register is supported
|
75
|
+
#
|
76
|
+
# @param type [Symbol] type for inclusion
|
77
|
+
def validate!(type)
|
78
|
+
return if SUPPORTED_TYPES.include?(type)
|
79
|
+
|
80
|
+
raise(::Karafka::Errors::UnsupportedCaseError, type)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -10,14 +10,15 @@ module Karafka
|
|
10
10
|
# end
|
11
11
|
# end
|
12
12
|
class Builder < Concurrent::Array
|
13
|
-
#
|
14
|
-
|
13
|
+
# Empty default per-topic config
|
14
|
+
EMPTY_DEFAULTS = ->(_) {}.freeze
|
15
15
|
|
16
|
-
private_constant :
|
16
|
+
private_constant :EMPTY_DEFAULTS
|
17
17
|
|
18
18
|
def initialize
|
19
|
-
super
|
20
19
|
@draws = Concurrent::Array.new
|
20
|
+
@defaults = EMPTY_DEFAULTS
|
21
|
+
super
|
21
22
|
end
|
22
23
|
|
23
24
|
# Used to draw routes for Karafka
|
@@ -38,11 +39,16 @@ module Karafka
|
|
38
39
|
instance_eval(&block)
|
39
40
|
|
40
41
|
each do |consumer_group|
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
# Validate consumer group settings
|
43
|
+
Contracts::ConsumerGroup.new.validate!(consumer_group.to_h)
|
44
|
+
|
45
|
+
# and then its topics settings
|
46
|
+
consumer_group.topics.each do |topic|
|
47
|
+
Contracts::Topic.new.validate!(topic.to_h)
|
48
|
+
end
|
44
49
|
|
45
|
-
|
50
|
+
# Initialize subscription groups after all the routing is done
|
51
|
+
consumer_group.subscription_groups
|
46
52
|
end
|
47
53
|
end
|
48
54
|
|
@@ -55,17 +61,17 @@ module Karafka
|
|
55
61
|
|
56
62
|
# Clears the builder and the draws memory
|
57
63
|
def clear
|
64
|
+
@defaults = EMPTY_DEFAULTS
|
58
65
|
@draws.clear
|
59
66
|
super
|
60
67
|
end
|
61
68
|
|
62
|
-
#
|
63
|
-
# @
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
draws.each { |block| draw(&block) }
|
69
|
+
# @param block [Proc] block with per-topic evaluated defaults
|
70
|
+
# @return [Proc] defaults that should be evaluated per topic
|
71
|
+
def defaults(&block)
|
72
|
+
return @defaults unless block
|
73
|
+
|
74
|
+
@defaults = block
|
69
75
|
end
|
70
76
|
|
71
77
|
private
|
@@ -74,15 +80,35 @@ module Karafka
|
|
74
80
|
# @param group_id [String, Symbol] name for consumer group
|
75
81
|
# @param block [Proc] proc that should be executed in the proxy context
|
76
82
|
def consumer_group(group_id, &block)
|
77
|
-
consumer_group =
|
78
|
-
|
83
|
+
consumer_group = find { |cg| cg.name == group_id.to_s }
|
84
|
+
|
85
|
+
if consumer_group
|
86
|
+
Proxy.new(consumer_group, &block).target
|
87
|
+
else
|
88
|
+
consumer_group = ConsumerGroup.new(group_id.to_s)
|
89
|
+
self << Proxy.new(consumer_group, &block).target
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Handles the simple routing case where we create one consumer group and allow for further
|
94
|
+
# subscription group customization
|
95
|
+
# @param subscription_group_name [String, Symbol] subscription group id. When not provided,
|
96
|
+
# a random uuid will be used
|
97
|
+
# @param block [Proc] further topics definitions
|
98
|
+
def subscription_group(subscription_group_name = SubscriptionGroup.id, &block)
|
99
|
+
consumer_group('app') do
|
100
|
+
target.public_send(:subscription_group=, subscription_group_name.to_s, &block)
|
101
|
+
end
|
79
102
|
end
|
80
103
|
|
104
|
+
# In case we use simple style of routing, all topics will be assigned to the same consumer
|
105
|
+
# group that will be based on the client_id
|
106
|
+
#
|
81
107
|
# @param topic_name [String, Symbol] name of a topic from which we want to consumer
|
82
108
|
# @param block [Proc] proc we want to evaluate in the topic context
|
83
109
|
def topic(topic_name, &block)
|
84
|
-
consumer_group(
|
85
|
-
topic(topic_name, &block)
|
110
|
+
consumer_group('app') do
|
111
|
+
topic(topic_name, &block)
|
86
112
|
end
|
87
113
|
end
|
88
114
|
end
|
@@ -5,28 +5,33 @@ module Karafka
|
|
5
5
|
# Object used to describe a single consumer group that is going to subscribe to
|
6
6
|
# given topics
|
7
7
|
# It is a part of Karafka's DSL
|
8
|
+
# @note A single consumer group represents Kafka consumer group, but it may not match 1:1 with
|
9
|
+
# subscription groups. There can be more subscription groups than consumer groups
|
8
10
|
class ConsumerGroup
|
9
|
-
|
11
|
+
attr_reader :id, :topics, :name
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
# This is a "virtual" attribute that is not building subscription groups.
|
14
|
+
# It allows us to store the "current" subscription group defined in the routing
|
15
|
+
# This subscription group id is then injected into topics, so we can compute the subscription
|
16
|
+
# groups
|
17
|
+
attr_accessor :current_subscription_group_name
|
16
18
|
|
17
19
|
# @param name [String, Symbol] raw name of this consumer group. Raw means, that it does not
|
18
20
|
# yet have an application client_id namespace, this will be added here by default.
|
19
21
|
# We add it to make a multi-system development easier for people that don't use
|
20
22
|
# kafka and don't understand the concept of consumer groups.
|
21
23
|
def initialize(name)
|
22
|
-
@name = name
|
23
|
-
@id =
|
24
|
-
@topics = []
|
24
|
+
@name = name.to_s
|
25
|
+
@id = config.consumer_mapper.call(name)
|
26
|
+
@topics = Topics.new([])
|
27
|
+
# Initialize the subscription group so there's always a value for it, since even if not
|
28
|
+
# defined directly, a subscription group will be created
|
29
|
+
@current_subscription_group_name = SubscriptionGroup.id
|
25
30
|
end
|
26
31
|
|
27
32
|
# @return [Boolean] true if this consumer group should be active in our current process
|
28
33
|
def active?
|
29
|
-
|
34
|
+
config.internal.routing.activity_manager.active?(:consumer_groups, name)
|
30
35
|
end
|
31
36
|
|
32
37
|
# Builds a topic representation inside of a current consumer group route
|
@@ -35,28 +40,59 @@ module Karafka
|
|
35
40
|
# @return [Karafka::Routing::Topic] newly built topic instance
|
36
41
|
def topic=(name, &block)
|
37
42
|
topic = Topic.new(name, self)
|
38
|
-
@topics << Proxy.new(
|
39
|
-
|
43
|
+
@topics << Proxy.new(
|
44
|
+
topic,
|
45
|
+
config.internal.routing.builder.defaults,
|
46
|
+
&block
|
47
|
+
).target
|
48
|
+
built_topic = @topics.last
|
49
|
+
# We overwrite it conditionally in case it was not set by the user inline in the topic
|
50
|
+
# block definition
|
51
|
+
built_topic.subscription_group_name ||= current_subscription_group_name
|
52
|
+
built_topic
|
40
53
|
end
|
41
54
|
|
42
|
-
|
43
|
-
|
55
|
+
# Assigns the current subscription group id based on the defined one and allows for further
|
56
|
+
# topic definition
|
57
|
+
# @param name [String, Symbol] name of the current subscription group
|
58
|
+
# @param block [Proc] block that may include topics definitions
|
59
|
+
def subscription_group=(name = SubscriptionGroup.id, &block)
|
60
|
+
# We cast it here, so the routing supports symbol based but that's anyhow later on
|
61
|
+
# validated as a string
|
62
|
+
@current_subscription_group_name = name.to_s
|
63
|
+
|
64
|
+
Proxy.new(self, &block)
|
65
|
+
|
66
|
+
# We need to reset the current subscription group after it is used, so it won't leak
|
67
|
+
# outside to other topics that would be defined without a defined subscription group
|
68
|
+
@current_subscription_group_name = SubscriptionGroup.id
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Array<Routing::SubscriptionGroup>] all the subscription groups build based on
|
72
|
+
# the consumer group topics
|
73
|
+
def subscription_groups
|
74
|
+
@subscription_groups ||= config
|
75
|
+
.internal
|
76
|
+
.routing
|
77
|
+
.subscription_groups_builder
|
78
|
+
.call(topics)
|
44
79
|
end
|
45
80
|
|
46
81
|
# Hashed version of consumer group that can be used for validation purposes
|
47
82
|
# @return [Hash] hash with consumer group attributes including serialized to hash
|
48
83
|
# topics inside of it.
|
49
84
|
def to_h
|
50
|
-
|
85
|
+
{
|
51
86
|
topics: topics.map(&:to_h),
|
52
87
|
id: id
|
53
|
-
}
|
88
|
+
}.freeze
|
89
|
+
end
|
54
90
|
|
55
|
-
|
56
|
-
result[attribute] = public_send(attribute)
|
57
|
-
end
|
91
|
+
private
|
58
92
|
|
59
|
-
|
93
|
+
# @return [Karafka::Core::Configurable::Node] root node config
|
94
|
+
def config
|
95
|
+
::Karafka::App.config
|
60
96
|
end
|
61
97
|
end
|
62
98
|
end
|
@@ -12,22 +12,11 @@ module Karafka
|
|
12
12
|
# raw_consumer_group_name
|
13
13
|
# end
|
14
14
|
# end
|
15
|
-
#
|
16
|
-
# @example Mapper for replacing "_" with "." in topic names
|
17
|
-
# class MyMapper
|
18
|
-
# def call(raw_consumer_group_name)
|
19
|
-
# [
|
20
|
-
# Karafka::Helpers::Inflector.map(Karafka::App.config.client_id.to_s),
|
21
|
-
# raw_consumer_group_name
|
22
|
-
# ].join('_').gsub('_', '.')
|
23
|
-
# end
|
24
|
-
# end
|
25
15
|
class ConsumerMapper
|
26
16
|
# @param raw_consumer_group_name [String, Symbol] string or symbolized consumer group name
|
27
17
|
# @return [String] remapped final consumer group name
|
28
18
|
def call(raw_consumer_group_name)
|
29
|
-
|
30
|
-
"#{client_name}_#{raw_consumer_group_name}"
|
19
|
+
"#{Karafka::App.config.client_id}_#{raw_consumer_group_name}"
|
31
20
|
end
|
32
21
|
end
|
33
22
|
end
|