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,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Routing
|
5
|
+
module Features
|
6
|
+
class ManualOffsetManagement < Base
|
7
|
+
# This feature validation contracts
|
8
|
+
module Contracts
|
9
|
+
# Rules around manual offset management settings
|
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 :manual_offset_management do
|
20
|
+
required(:active) { |val| [true, false].include?(val) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Routing
|
5
|
+
module Features
|
6
|
+
class ManualOffsetManagement < Base
|
7
|
+
# Topic extensions to be able to manage manual offset management settings
|
8
|
+
module Topic
|
9
|
+
# @param active [Boolean] should we stop managing the offset in Karafka and make the user
|
10
|
+
# responsible for marking messages as consumed.
|
11
|
+
# @return [Config] defined config
|
12
|
+
#
|
13
|
+
# @note Since this feature supports only one setting (active), we can use the old API
|
14
|
+
# where the boolean would be an argument
|
15
|
+
def manual_offset_management(active = false)
|
16
|
+
@manual_offset_management ||= Config.new(active: active)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Boolean] is manual offset management enabled for a given topic
|
20
|
+
def manual_offset_management?
|
21
|
+
manual_offset_management.active?
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Hash] topic with all its native configuration options plus manual offset
|
25
|
+
# management namespace settings
|
26
|
+
def to_h
|
27
|
+
super.merge(
|
28
|
+
manual_offset_management: manual_offset_management.to_h
|
29
|
+
).freeze
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Routing
|
5
|
+
module Features
|
6
|
+
# All the things needed to be able to manage manual offset management from the routing
|
7
|
+
# perspective.
|
8
|
+
#
|
9
|
+
# Manual offset management allows users to completely disable automatic management of the
|
10
|
+
# offset. This can be used for implementing long-living window operations and other things
|
11
|
+
# where we do not want to commit the offset with each batch.
|
12
|
+
#
|
13
|
+
# Not all the Karafka and Karafka Pro features may be compatible with this feature being on.
|
14
|
+
class ManualOffsetManagement < Base
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -7,39 +7,40 @@ module Karafka
|
|
7
7
|
class Proxy
|
8
8
|
attr_reader :target
|
9
9
|
|
10
|
-
# We should proxy only non ? and = methods as we want to have a regular dsl
|
11
|
-
IGNORED_POSTFIXES = %w[
|
12
|
-
?
|
13
|
-
=
|
14
|
-
!
|
15
|
-
].freeze
|
16
|
-
|
17
|
-
private_constant :IGNORED_POSTFIXES
|
18
|
-
|
19
10
|
# @param target [Object] target object to which we proxy any DSL call
|
11
|
+
# @param defaults [Proc] defaults for target that should be applicable after the proper
|
12
|
+
# proxy context (if needed)
|
20
13
|
# @param block [Proc] block that we want to evaluate in the proxy context
|
21
|
-
def initialize(target, &block)
|
14
|
+
def initialize(target, defaults = ->(_) {}, &block)
|
22
15
|
@target = target
|
23
16
|
instance_eval(&block)
|
17
|
+
instance_eval(&defaults)
|
24
18
|
end
|
25
19
|
|
26
|
-
#
|
27
|
-
|
28
|
-
# @param arguments [Array] array with it's arguments
|
29
|
-
# @param block [Proc] block provided to the method
|
30
|
-
def method_missing(method_name, *arguments, &block)
|
31
|
-
return super unless respond_to_missing?(method_name)
|
20
|
+
# Ruby 2.7.0 to 2.7.2 do not have arg forwarding, so we fallback to the old way
|
21
|
+
arg_forwarding = RUBY_VERSION < '3.0' ? '*args, &block' : '...'
|
32
22
|
|
33
|
-
|
34
|
-
|
23
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
24
|
+
# Translates the no "=" DSL of routing into elements assignments on target
|
25
|
+
# @param method_name [Symbol] name of the missing method
|
26
|
+
def method_missing(method_name, #{arg_forwarding})
|
27
|
+
return super unless respond_to_missing?(method_name)
|
28
|
+
|
29
|
+
if @target.respond_to?(:"\#{method_name}=")
|
30
|
+
@target.public_send(:"\#{method_name}=", #{arg_forwarding})
|
31
|
+
else
|
32
|
+
@target.public_send(method_name, #{arg_forwarding})
|
33
|
+
end
|
34
|
+
end
|
35
|
+
RUBY
|
35
36
|
|
36
37
|
# Tells whether or not a given element exists on the target
|
37
38
|
# @param method_name [Symbol] name of the missing method
|
38
39
|
# @param include_private [Boolean] should we include private in the check as well
|
39
40
|
def respond_to_missing?(method_name, include_private = false)
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
@target.respond_to?(:"#{method_name}=", include_private) ||
|
42
|
+
@target.respond_to?(method_name, include_private) ||
|
43
|
+
super
|
43
44
|
end
|
44
45
|
end
|
45
46
|
end
|
@@ -7,23 +7,37 @@ module Karafka
|
|
7
7
|
# @note Since Kafka does not provide namespaces or modules for topics, they all have "flat"
|
8
8
|
# structure so all the routes are being stored in a single level array
|
9
9
|
module Router
|
10
|
-
#
|
11
|
-
# @param
|
12
|
-
#
|
13
|
-
|
14
|
-
# @raise [Karafka::Topic::NonMatchingTopicError] raised if topic name does not match
|
15
|
-
# any route defined by user using routes.draw
|
16
|
-
def find(topic_id)
|
10
|
+
# Finds first reference of a given topic based on provided lookup attribute
|
11
|
+
# @param lookup [Hash<Symbol, String>] hash with attribute - value key pairs
|
12
|
+
# @return [Karafka::Routing::Topic, nil] proper route details or nil if not found
|
13
|
+
def find_by(lookup)
|
17
14
|
App.consumer_groups.each do |consumer_group|
|
18
15
|
consumer_group.topics.each do |topic|
|
19
|
-
return topic if
|
16
|
+
return topic if lookup.all? do |attribute, value|
|
17
|
+
topic.public_send(attribute) == value
|
18
|
+
end
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
23
|
-
|
22
|
+
nil
|
24
23
|
end
|
25
24
|
|
26
|
-
|
25
|
+
# Finds the topic by name (in any consumer group) and if not present, will built a new
|
26
|
+
# representation of the topic with the defaults and default deserializer.
|
27
|
+
#
|
28
|
+
# This is used in places where we may operate on topics that are not part of the routing
|
29
|
+
# but we want to do something on them (display data, iterate over, etc)
|
30
|
+
# @param name [String] name of the topic we are looking for
|
31
|
+
# @return [Karafka::Routing::Topic]
|
32
|
+
#
|
33
|
+
# @note Please note, that in case of a new topic, it will have a newly built consumer group
|
34
|
+
# as well, that is not part of the routing.
|
35
|
+
def find_or_initialize_by_name(name)
|
36
|
+
find_by(name: name) || Topic.new(name, ConsumerGroup.new(name))
|
37
|
+
end
|
38
|
+
|
39
|
+
module_function :find_by
|
40
|
+
module_function :find_or_initialize_by_name
|
27
41
|
end
|
28
42
|
end
|
29
43
|
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Routing
|
5
|
+
# Object representing a set of single consumer group topics that can be subscribed together
|
6
|
+
# with one connection.
|
7
|
+
#
|
8
|
+
# @note One subscription group will always belong to one consumer group, but one consumer
|
9
|
+
# group can have multiple subscription groups.
|
10
|
+
class SubscriptionGroup
|
11
|
+
attr_reader :id, :name, :topics, :kafka, :consumer_group
|
12
|
+
|
13
|
+
# Numeric for counting groups
|
14
|
+
GROUP_COUNT = Concurrent::AtomicFixnum.new
|
15
|
+
|
16
|
+
private_constant :GROUP_COUNT
|
17
|
+
|
18
|
+
class << self
|
19
|
+
# Generates new subscription group id that will be used in case of anonymous subscription
|
20
|
+
# groups
|
21
|
+
# @return [String] hex(6) compatible reproducible id
|
22
|
+
def id
|
23
|
+
::Digest::MD5.hexdigest(
|
24
|
+
GROUP_COUNT.increment.to_s
|
25
|
+
)[0..11]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param position [Integer] position of this subscription group in all the subscriptions
|
30
|
+
# groups array. We need to have this value for sake of static group memberships, where
|
31
|
+
# we need a "in-between" restarts unique identifier
|
32
|
+
# @param topics [Karafka::Routing::Topics] all the topics that share the same key settings
|
33
|
+
# @return [SubscriptionGroup] built subscription group
|
34
|
+
def initialize(position, topics)
|
35
|
+
@name = topics.first.subscription_group_name
|
36
|
+
@consumer_group = topics.first.consumer_group
|
37
|
+
# We include the consumer group id here because we want to have unique ids of subscription
|
38
|
+
# groups across the system. Otherwise user could set the same name for multiple
|
39
|
+
# subscription groups in many consumer groups effectively having same id for different
|
40
|
+
# entities
|
41
|
+
@id = "#{@consumer_group.id}_#{@name}_#{position}"
|
42
|
+
@position = position
|
43
|
+
@topics = topics
|
44
|
+
@kafka = build_kafka
|
45
|
+
freeze
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [String] consumer group id
|
49
|
+
def consumer_group_id
|
50
|
+
kafka[:'group.id']
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [Integer] max messages fetched in a single go
|
54
|
+
def max_messages
|
55
|
+
@topics.first.max_messages
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Integer] max milliseconds we can wait for incoming messages
|
59
|
+
def max_wait_time
|
60
|
+
@topics.first.max_wait_time
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Boolean] is this subscription group one of active once
|
64
|
+
def active?
|
65
|
+
Karafka::App.config.internal.routing.activity_manager.active?(:subscription_groups, name)
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [Array<String>] names of topics to which we should subscribe.
|
69
|
+
#
|
70
|
+
# @note Most of the time it should not include inactive topics but in case of pattern
|
71
|
+
# matching the matcher topics become inactive down the road, hence we filter out so
|
72
|
+
# they are later removed.
|
73
|
+
def subscriptions
|
74
|
+
topics.select(&:active?).map(&:subscription_name)
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [String] id of the subscription group
|
78
|
+
# @note This is an alias for displaying in places where we print the stringified version.
|
79
|
+
def to_s
|
80
|
+
id
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# @return [Hash] kafka settings are a bit special. They are exactly the same for all of the
|
86
|
+
# topics but they lack the group.id (unless explicitly) provided. To make it compatible
|
87
|
+
# with our routing engine, we inject it before it will go to the consumer
|
88
|
+
def build_kafka
|
89
|
+
kafka = Setup::AttributesMap.consumer(@topics.first.kafka.dup)
|
90
|
+
|
91
|
+
# If we use static group memberships, there can be a case, where same instance id would
|
92
|
+
# be set on many subscription groups as the group instance id from Karafka perspective is
|
93
|
+
# set per config. Each instance even if they are subscribed to different topics needs to
|
94
|
+
# have it fully unique. To make sure of that, we just add extra postfix at the end that
|
95
|
+
# increments.
|
96
|
+
group_instance_id = kafka.fetch(:'group.instance.id', false)
|
97
|
+
|
98
|
+
kafka[:'group.instance.id'] = "#{group_instance_id}_#{@position}" if group_instance_id
|
99
|
+
kafka[:'client.id'] ||= Karafka::App.config.client_id
|
100
|
+
kafka[:'group.id'] ||= @consumer_group.id
|
101
|
+
kafka[:'auto.offset.reset'] ||= @topics.first.initial_offset
|
102
|
+
# Karafka manages the offsets based on the processing state, thus we do not rely on the
|
103
|
+
# rdkafka offset auto-storing
|
104
|
+
kafka[:'enable.auto.offset.store'] = false
|
105
|
+
kafka.freeze
|
106
|
+
kafka
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Routing
|
5
|
+
# rdkafka allows us to group topics subscriptions when they have same settings.
|
6
|
+
# This builder groups topics from a single consumer group into subscription groups that can be
|
7
|
+
# subscribed with one rdkafka connection.
|
8
|
+
# This way we save resources as having several rdkafka consumers under the hood is not the
|
9
|
+
# cheapest thing in a bigger system.
|
10
|
+
#
|
11
|
+
# In general, if we can, we try to subscribe to as many topics with one rdkafka connection as
|
12
|
+
# possible, but if not possible, we divide.
|
13
|
+
class SubscriptionGroupsBuilder
|
14
|
+
# Keys used to build up a hash for subscription groups distribution.
|
15
|
+
# In order to be able to use the same rdkafka connection for several topics, those keys need
|
16
|
+
# to have same values.
|
17
|
+
DISTRIBUTION_KEYS = %i[
|
18
|
+
kafka
|
19
|
+
max_messages
|
20
|
+
max_wait_time
|
21
|
+
initial_offset
|
22
|
+
subscription_group_name
|
23
|
+
].freeze
|
24
|
+
|
25
|
+
private_constant :DISTRIBUTION_KEYS
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@position = -1
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param topics [Karafka::Routing::Topics] all the topics based on which we want to build
|
32
|
+
# subscription groups
|
33
|
+
# @return [Array<SubscriptionGroup>] all subscription groups we need in separate threads
|
34
|
+
def call(topics)
|
35
|
+
topics
|
36
|
+
.map { |topic| [checksum(topic), topic] }
|
37
|
+
.group_by(&:first)
|
38
|
+
.values
|
39
|
+
.map { |value| value.map(&:last) }
|
40
|
+
.map { |topics_array| Routing::Topics.new(topics_array) }
|
41
|
+
.map { |grouped_topics| SubscriptionGroup.new(@position += 1, grouped_topics) }
|
42
|
+
.tap do |subscription_groups|
|
43
|
+
subscription_groups.each do |subscription_group|
|
44
|
+
subscription_group.topics.each do |topic|
|
45
|
+
topic.subscription_group = subscription_group
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# @param topic [Karafka::Routing::Topic] topic for which we compute the grouping checksum
|
54
|
+
# @return [Integer] checksum that we can use to check if topics have the same set of
|
55
|
+
# settings based on which we group
|
56
|
+
def checksum(topic)
|
57
|
+
accu = {}
|
58
|
+
|
59
|
+
DISTRIBUTION_KEYS.each { |key| accu[key] = topic.public_send(key) }
|
60
|
+
|
61
|
+
accu.hash
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -2,17 +2,33 @@
|
|
2
2
|
|
3
3
|
module Karafka
|
4
4
|
module Routing
|
5
|
-
# Topic stores all the details on how we should interact with Kafka given topic
|
5
|
+
# Topic stores all the details on how we should interact with Kafka given topic.
|
6
6
|
# It belongs to a consumer group as from 0.6 all the topics can work in the same consumer group
|
7
|
-
# It is a part of Karafka's DSL
|
7
|
+
# It is a part of Karafka's DSL.
|
8
8
|
class Topic
|
9
|
-
|
10
|
-
|
9
|
+
attr_reader :id, :name, :consumer_group
|
10
|
+
attr_writer :consumer
|
11
11
|
|
12
|
-
|
13
|
-
attr_accessor :consumer
|
12
|
+
attr_accessor :subscription_group_name
|
14
13
|
|
15
|
-
|
14
|
+
# Full subscription group reference can be built only when we have knowledge about the
|
15
|
+
# whole routing tree, this is why it is going to be set later on
|
16
|
+
attr_accessor :subscription_group
|
17
|
+
|
18
|
+
# Attributes we can inherit from the root unless they were defined on this level
|
19
|
+
INHERITABLE_ATTRIBUTES = %i[
|
20
|
+
kafka
|
21
|
+
deserializer
|
22
|
+
max_messages
|
23
|
+
max_wait_time
|
24
|
+
initial_offset
|
25
|
+
consumer_persistence
|
26
|
+
pause_timeout
|
27
|
+
pause_max_timeout
|
28
|
+
pause_with_exponential_backoff
|
29
|
+
].freeze
|
30
|
+
|
31
|
+
private_constant :INHERITABLE_ATTRIBUTES
|
16
32
|
|
17
33
|
# @param [String, Symbol] name of a topic on which we want to listen
|
18
34
|
# @param consumer_group [Karafka::Routing::ConsumerGroup] owning consumer group of this topic
|
@@ -20,42 +36,89 @@ module Karafka
|
|
20
36
|
@name = name.to_s
|
21
37
|
@consumer_group = consumer_group
|
22
38
|
@attributes = {}
|
39
|
+
@active = true
|
23
40
|
# @note We use identifier related to the consumer group that owns a topic, because from
|
24
41
|
# Karafka 0.6 we can handle multiple Kafka instances with the same process and we can
|
25
|
-
# have same topic name across multiple
|
42
|
+
# have same topic name across multiple consumer groups
|
26
43
|
@id = "#{consumer_group.id}_#{@name}"
|
27
44
|
end
|
28
45
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
46
|
+
INHERITABLE_ATTRIBUTES.each do |attribute|
|
47
|
+
attr_writer attribute
|
48
|
+
|
49
|
+
define_method attribute do
|
50
|
+
current_value = instance_variable_get(:"@#{attribute}")
|
51
|
+
|
52
|
+
return current_value unless current_value.nil?
|
53
|
+
|
54
|
+
value = Karafka::App.config.send(attribute)
|
55
|
+
|
56
|
+
instance_variable_set(:"@#{attribute}", value)
|
57
|
+
end
|
36
58
|
end
|
37
59
|
|
38
|
-
# @return [
|
39
|
-
|
40
|
-
|
41
|
-
@responder ||= Karafka::Responders::Builder.new(consumer).build
|
60
|
+
# @return [String] name of subscription that will go to librdkafka
|
61
|
+
def subscription_name
|
62
|
+
name
|
42
63
|
end
|
43
64
|
|
44
|
-
|
45
|
-
|
65
|
+
# @return [Class] consumer class that we should use
|
66
|
+
def consumer
|
67
|
+
if consumer_persistence
|
68
|
+
# When persistence of consumers is on, no need to reload them
|
69
|
+
@consumer
|
70
|
+
else
|
71
|
+
# In order to support code reload without having to change the topic api, we re-fetch the
|
72
|
+
# class of a consumer based on its class name. This will support all the cases where the
|
73
|
+
# consumer class is defined with a name. It won't support code reload for anonymous
|
74
|
+
# consumer classes, but this is an edge case
|
75
|
+
begin
|
76
|
+
::Object.const_get(@consumer.to_s)
|
77
|
+
rescue NameError
|
78
|
+
# It will only fail if the in case of anonymous classes
|
79
|
+
@consumer
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Allows to disable topic by invoking this method and setting it to `false`.
|
85
|
+
# @param active [Boolean] should this topic be consumed or not
|
86
|
+
def active(active)
|
87
|
+
@active = active
|
88
|
+
end
|
89
|
+
|
90
|
+
# @return [Class] consumer class that we should use
|
91
|
+
# @note This is just an alias to the `#consumer` method. We however want to use it internally
|
92
|
+
# instead of referencing the `#consumer`. We use this to indicate that this method returns
|
93
|
+
# class and not an instance. In the routing we want to keep the `#consumer Consumer`
|
94
|
+
# routing syntax, but for references outside, we should use this one.
|
95
|
+
def consumer_class
|
96
|
+
consumer
|
97
|
+
end
|
98
|
+
|
99
|
+
# @return [Boolean] should this topic be in use
|
100
|
+
def active?
|
101
|
+
# Never active if disabled via routing
|
102
|
+
return false unless @active
|
103
|
+
|
104
|
+
Karafka::App.config.internal.routing.activity_manager.active?(:topics, name)
|
46
105
|
end
|
47
106
|
|
48
107
|
# @return [Hash] hash with all the topic attributes
|
49
108
|
# @note This is being used when we validate the consumer_group and its topics
|
50
109
|
def to_h
|
51
|
-
map =
|
110
|
+
map = INHERITABLE_ATTRIBUTES.map do |attribute|
|
52
111
|
[attribute, public_send(attribute)]
|
53
112
|
end
|
54
113
|
|
55
114
|
Hash[map].merge!(
|
56
115
|
id: id,
|
57
|
-
|
58
|
-
|
116
|
+
name: name,
|
117
|
+
active: active?,
|
118
|
+
consumer: consumer,
|
119
|
+
consumer_group_id: consumer_group.id,
|
120
|
+
subscription_group_name: subscription_group_name
|
121
|
+
).freeze
|
59
122
|
end
|
60
123
|
end
|
61
124
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
module Karafka
|
6
|
+
module Routing
|
7
|
+
# Abstraction layer on top of groups of topics
|
8
|
+
class Topics
|
9
|
+
include Enumerable
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
def_delegators :@accumulator, :[], :size, :empty?, :last, :<<
|
13
|
+
|
14
|
+
# @param topics_array [Array<Karafka::Routing::Topic>] array with topics
|
15
|
+
def initialize(topics_array)
|
16
|
+
@accumulator = topics_array.dup
|
17
|
+
end
|
18
|
+
|
19
|
+
# Yields each topic
|
20
|
+
#
|
21
|
+
# @param [Proc] block we want to yield with on each topic
|
22
|
+
def each(&block)
|
23
|
+
@accumulator.each(&block)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Allows us to remove elements from the topics
|
27
|
+
#
|
28
|
+
# Block to decide what to delete
|
29
|
+
# @param block [Proc]
|
30
|
+
def delete_if(&block)
|
31
|
+
@accumulator.delete_if(&block)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Finds topic by its name
|
35
|
+
#
|
36
|
+
# @param topic_name [String] topic name
|
37
|
+
# @return [Karafka::Routing::Topic]
|
38
|
+
# @raise [Karafka::Errors::TopicNotFoundError] this should never happen. If you see it,
|
39
|
+
# please create an issue.
|
40
|
+
def find(topic_name)
|
41
|
+
@accumulator.find { |topic| topic.name == topic_name } ||
|
42
|
+
raise(Karafka::Errors::TopicNotFoundError, topic_name)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
# Class used to run the Karafka listeners in separate threads
|
5
|
+
class Runner
|
6
|
+
# Starts listening on all the listeners asynchronously and handles the jobs queue closing
|
7
|
+
# after listeners are done with their work.
|
8
|
+
def call
|
9
|
+
# Despite possibility of having several independent listeners, we aim to have one queue for
|
10
|
+
# jobs across and one workers poll for that
|
11
|
+
jobs_queue = Processing::JobsQueue.new
|
12
|
+
|
13
|
+
workers = Processing::WorkersBatch.new(jobs_queue)
|
14
|
+
listeners = Connection::ListenersBatch.new(jobs_queue)
|
15
|
+
|
16
|
+
workers.each(&:async_call)
|
17
|
+
listeners.each(&:async_call)
|
18
|
+
|
19
|
+
# We aggregate threads here for a supervised shutdown process
|
20
|
+
Karafka::Server.workers = workers
|
21
|
+
Karafka::Server.listeners = listeners
|
22
|
+
Karafka::Server.jobs_queue = jobs_queue
|
23
|
+
|
24
|
+
# All the listener threads need to finish
|
25
|
+
listeners.each(&:join)
|
26
|
+
|
27
|
+
# We close the jobs queue only when no listener threads are working.
|
28
|
+
# This ensures, that everything was closed prior to us not accepting anymore jobs and that
|
29
|
+
# no more jobs will be enqueued. Since each listener waits for jobs to finish, once those
|
30
|
+
# are done, we can close.
|
31
|
+
jobs_queue.close
|
32
|
+
|
33
|
+
# All the workers need to stop processing anything before we can stop the runner completely
|
34
|
+
# This ensures that even async long-running jobs have time to finish before we are done
|
35
|
+
# with everything. One thing worth keeping in mind though: It is the end user responsibility
|
36
|
+
# to handle the shutdown detection in their long-running processes. Otherwise if timeout
|
37
|
+
# is exceeded, there will be a forced shutdown.
|
38
|
+
workers.each(&:join)
|
39
|
+
# If anything crashes here, we need to raise the error and crush the runner because it means
|
40
|
+
# that something terrible happened
|
41
|
+
rescue StandardError => e
|
42
|
+
Karafka.monitor.instrument(
|
43
|
+
'error.occurred',
|
44
|
+
caller: self,
|
45
|
+
error: e,
|
46
|
+
type: 'runner.call.error'
|
47
|
+
)
|
48
|
+
Karafka::App.stop!
|
49
|
+
raise e
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,25 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Karafka
|
4
|
-
# Module for all supported by default serialization and deserialization ways
|
4
|
+
# Module for all supported by default serialization and deserialization ways.
|
5
5
|
module Serialization
|
6
|
-
# Namespace for json
|
6
|
+
# Namespace for json serializers and deserializers.
|
7
7
|
module Json
|
8
|
-
# Default Karafka Json deserializer for loading JSON data
|
8
|
+
# Default Karafka Json deserializer for loading JSON data.
|
9
9
|
class Deserializer
|
10
|
-
# @param
|
10
|
+
# @param message [Karafka::Messages::Message] Message object that we want to deserialize
|
11
11
|
# @return [Hash] hash with deserialized JSON data
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# 'topic' => 'my-topic',
|
16
|
-
# 'headers' => { 'message_type' => :test }
|
17
|
-
# }
|
18
|
-
# Deserializer.call(params) #=> { 'a' => 1 }
|
19
|
-
def call(params)
|
20
|
-
params.raw_payload.nil? ? nil : ::JSON.parse(params.raw_payload)
|
21
|
-
rescue ::JSON::ParserError => e
|
22
|
-
raise ::Karafka::Errors::DeserializationError, e
|
12
|
+
def call(message)
|
13
|
+
# nil payload can be present for example for tombstone messages
|
14
|
+
message.raw_payload.nil? ? nil : ::JSON.parse(message.raw_payload)
|
23
15
|
end
|
24
16
|
end
|
25
17
|
end
|