karafka 2.6.0.beta1 → 2.6.0.rc1
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
- data/CHANGELOG.md +64 -27
- data/certs/expired.txt +2 -0
- data/config/locales/errors.yml +5 -0
- data/karafka.gemspec +1 -1
- data/lib/active_job/queue_adapters/karafka_adapter.rb +1 -1
- data/lib/karafka/active_job/current_attributes/loading.rb +1 -1
- data/lib/karafka/active_job/current_attributes.rb +4 -2
- data/lib/karafka/active_job/dispatcher.rb +1 -2
- data/lib/karafka/admin/consumer_groups.rb +8 -2
- data/lib/karafka/admin/replication.rb +6 -3
- data/lib/karafka/admin/topics.rb +32 -12
- data/lib/karafka/admin.rb +155 -59
- data/lib/karafka/app.rb +1 -1
- data/lib/karafka/base_consumer.rb +33 -5
- data/lib/karafka/cli/console.rb +0 -1
- data/lib/karafka/cli/help.rb +0 -1
- data/lib/karafka/cli/info.rb +0 -1
- data/lib/karafka/cli/install.rb +0 -1
- data/lib/karafka/cli/server.rb +0 -1
- data/lib/karafka/cli/swarm.rb +0 -1
- data/lib/karafka/cli.rb +2 -2
- data/lib/karafka/connection/client.rb +44 -7
- data/lib/karafka/connection/listener.rb +3 -3
- data/lib/karafka/connection/manager.rb +0 -1
- data/lib/karafka/connection/pauses_manager.rb +17 -0
- data/lib/karafka/connection/proxy.rb +45 -0
- data/lib/karafka/connection/status.rb +0 -1
- data/lib/karafka/instrumentation/assignments_tracker.rb +34 -0
- data/lib/karafka/instrumentation/callbacks/consumer_groups/decorator.rb +19 -0
- data/lib/karafka/instrumentation/callbacks/consumer_groups/error.rb +0 -1
- data/lib/karafka/instrumentation/callbacks/consumer_groups/statistics.rb +3 -2
- data/lib/karafka/instrumentation/critical_errors_listener.rb +85 -0
- data/lib/karafka/instrumentation/logger_listener.rb +2 -0
- data/lib/karafka/instrumentation/monitor.rb +2 -3
- data/lib/karafka/instrumentation/vendors/appsignal/errors_listener.rb +0 -1
- data/lib/karafka/instrumentation/vendors/appsignal/metrics_listener.rb +0 -1
- data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +4 -3
- data/lib/karafka/instrumentation/vendors/datadog/metrics_listener.rb +0 -2
- data/lib/karafka/instrumentation/vendors/kubernetes/liveness_listener.rb +181 -18
- data/lib/karafka/pro/admin/recovery/errors.rb +0 -1
- data/lib/karafka/pro/admin/recovery.rb +6 -4
- data/lib/karafka/pro/base_consumer.rb +5 -5
- data/lib/karafka/pro/cleaner/messages/metadata.rb +0 -1
- data/lib/karafka/pro/cli/parallel_segments/base.rb +1 -2
- data/lib/karafka/pro/connection/manager.rb +7 -4
- data/lib/karafka/pro/encryption/messages/middleware.rb +5 -0
- data/lib/karafka/pro/encryption/messages/parser.rb +4 -0
- data/lib/karafka/pro/instrumentation/callbacks/consumer_groups/decorator.rb +63 -0
- data/lib/karafka/pro/instrumentation/consumer_groups/lag_compensation/compensator.rb +120 -0
- data/lib/karafka/pro/instrumentation/consumer_groups/lag_compensation/fetcher.rb +88 -0
- data/lib/karafka/pro/instrumentation/consumer_groups/lag_compensation/refresher.rb +185 -0
- data/lib/karafka/pro/instrumentation/consumer_groups/lag_compensation/registry.rb +102 -0
- data/lib/karafka/pro/instrumentation/performance_tracker.rb +40 -6
- data/lib/karafka/pro/iterator/tpl_builder.rb +27 -7
- data/lib/karafka/pro/iterator.rb +22 -7
- data/lib/karafka/pro/loader.rb +12 -0
- data/lib/karafka/pro/processing/consumer_groups/adaptive_iterator/consumer.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/adaptive_iterator/tracker.rb +2 -4
- data/lib/karafka/pro/processing/consumer_groups/collapser.rb +6 -9
- data/lib/karafka/pro/processing/consumer_groups/coordinator.rb +1 -4
- data/lib/karafka/pro/processing/consumer_groups/coordinators/errors_tracker.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/coordinators/filters_applier.rb +21 -10
- data/lib/karafka/pro/processing/consumer_groups/coordinators/virtual_offset_manager.rb +4 -4
- data/lib/karafka/pro/processing/consumer_groups/expansions_selector.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/filters/actions.rb +84 -0
- data/lib/karafka/pro/processing/consumer_groups/filters/base.rb +5 -6
- data/lib/karafka/pro/processing/consumer_groups/filters/delayer.rb +2 -5
- data/lib/karafka/pro/processing/consumer_groups/filters/expirer.rb +1 -4
- data/lib/karafka/pro/processing/consumer_groups/filters/inline_insights_delayer.rb +1 -4
- data/lib/karafka/pro/processing/consumer_groups/filters/throttler.rb +2 -5
- data/lib/karafka/pro/processing/consumer_groups/filters/virtual_limiter.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/jobs/consume_non_blocking.rb +2 -3
- data/lib/karafka/pro/processing/consumer_groups/jobs/eofed_non_blocking.rb +0 -2
- data/lib/karafka/pro/processing/consumer_groups/jobs/periodic.rb +2 -3
- data/lib/karafka/pro/processing/consumer_groups/jobs/periodic_non_blocking.rb +0 -2
- data/lib/karafka/pro/processing/consumer_groups/jobs/revoked_non_blocking.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/jobs_builder.rb +5 -4
- data/lib/karafka/pro/processing/consumer_groups/offset_metadata/consumer.rb +3 -7
- data/lib/karafka/pro/processing/consumer_groups/offset_metadata/fetcher.rb +8 -10
- data/lib/karafka/pro/processing/consumer_groups/offset_metadata/listener.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/parallel_segments/filters/base.rb +3 -5
- data/lib/karafka/pro/processing/consumer_groups/parallel_segments/filters/default.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/parallel_segments/filters/mom.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/partitioner.rb +2 -5
- data/lib/karafka/pro/processing/consumer_groups/periodic_job/consumer.rb +2 -5
- data/lib/karafka/pro/processing/consumer_groups/piping/consumer.rb +2 -5
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_ftr_lrj_mom.rb +10 -9
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_ftr_lrj_mom_vp.rb +11 -10
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_ftr_mom.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_ftr_mom_vp.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_lrj_mom.rb +8 -7
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_lrj_mom_vp.rb +9 -8
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_mom.rb +5 -8
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/dlq_mom_vp.rb +3 -6
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/ftr_lrj_mom.rb +4 -7
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/ftr_lrj_mom_vp.rb +6 -9
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/ftr_mom.rb +3 -7
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/ftr_mom_vp.rb +4 -8
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/lrj_mom.rb +3 -6
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/lrj_mom_vp.rb +4 -7
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/mom.rb +2 -5
- data/lib/karafka/pro/processing/consumer_groups/strategies/aj/mom_vp.rb +3 -6
- data/lib/karafka/pro/processing/consumer_groups/strategies/base.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/default.rb +56 -33
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/default.rb +27 -14
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_lrj.rb +4 -7
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_lrj_mom.rb +5 -8
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_lrj_mom_vp.rb +5 -8
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_lrj_vp.rb +3 -7
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_mom.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_mom_vp.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/ftr_vp.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/lrj.rb +2 -5
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/lrj_mom.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/lrj_mom_vp.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/lrj_vp.rb +3 -6
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/mom.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/mom_vp.rb +3 -6
- data/lib/karafka/pro/processing/consumer_groups/strategies/dlq/vp.rb +65 -8
- data/lib/karafka/pro/processing/consumer_groups/strategies/ftr/default.rb +0 -4
- data/lib/karafka/pro/processing/consumer_groups/strategies/ftr/vp.rb +2 -5
- data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/default.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/ftr.rb +3 -6
- data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/ftr_mom.rb +4 -7
- data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/ftr_mom_vp.rb +4 -8
- data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/ftr_vp.rb +3 -6
- data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/mom.rb +2 -5
- data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/mom_vp.rb +3 -7
- data/lib/karafka/pro/processing/consumer_groups/strategies/lrj/vp.rb +2 -5
- data/lib/karafka/pro/processing/consumer_groups/strategies/mom/default.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/mom/ftr.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/mom/ftr_vp.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/mom/vp.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/strategies/vp/default.rb +11 -6
- data/lib/karafka/pro/processing/consumer_groups/strategy_selector.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/subscription_groups_coordinator.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/virtual_partitions/distributors/balanced.rb +0 -3
- data/lib/karafka/pro/processing/consumer_groups/virtual_partitions/distributors/base.rb +2 -4
- data/lib/karafka/pro/processing/consumer_groups/virtual_partitions/distributors/consistent.rb +0 -3
- data/lib/karafka/pro/processing/jobs_queue.rb +4 -1
- data/lib/karafka/pro/processing/schedulers/base.rb +4 -2
- data/lib/karafka/pro/processing/schedulers/default.rb +2 -2
- data/lib/karafka/pro/recurring_tasks/consumer.rb +9 -2
- data/lib/karafka/pro/recurring_tasks/contracts/config.rb +0 -1
- data/lib/karafka/pro/recurring_tasks/executor.rb +25 -13
- data/lib/karafka/pro/routing/features/consumer_groups/direct_assignments/subscription_group.rb +0 -2
- data/lib/karafka/pro/routing/features/consumer_groups/long_running_job.rb +0 -2
- data/lib/karafka/pro/routing/features/consumer_groups/multiplexing/proxy.rb +2 -2
- data/lib/karafka/pro/routing/features/consumer_groups/non_blocking_job.rb +0 -2
- data/lib/karafka/pro/routing/features/consumer_groups/offset_metadata/topic.rb +0 -6
- data/lib/karafka/pro/routing/features/consumer_groups/parallel_segments/consumer_group.rb +5 -4
- data/lib/karafka/pro/routing/features/consumer_groups/patterns/config.rb +0 -6
- data/lib/karafka/pro/routing/features/consumer_groups/patterns/consumer_group.rb +2 -1
- data/lib/karafka/pro/routing/features/consumer_groups/patterns/contracts/pattern.rb +0 -1
- data/lib/karafka/pro/routing/features/consumer_groups/patterns/detector.rb +2 -1
- data/lib/karafka/pro/routing/features/consumer_groups/patterns/pattern.rb +2 -1
- data/lib/karafka/pro/routing/features/consumer_groups/patterns/topics.rb +8 -8
- data/lib/karafka/pro/routing/features/consumer_groups/periodic_job/topic.rb +5 -5
- data/lib/karafka/pro/routing/features/consumer_groups/recurring_tasks/builder.rb +33 -13
- data/lib/karafka/pro/routing/features/consumer_groups/scheduled_messages/builder.rb +52 -28
- data/lib/karafka/pro/routing/features/consumer_groups/scheduled_messages/topic.rb +2 -1
- data/lib/karafka/pro/routing/features/consumer_groups/virtual_partitions/topic.rb +6 -5
- data/lib/karafka/pro/scheduled_messages/consumer.rb +7 -1
- data/lib/karafka/pro/scheduled_messages/schema_validator.rb +6 -1
- data/lib/karafka/pro/swarm/liveness_listener.rb +118 -13
- data/lib/karafka/pro.rb +0 -6
- data/lib/karafka/processing/consumer_groups/coordinator.rb +4 -5
- data/lib/karafka/processing/consumer_groups/coordinators_buffer.rb +6 -2
- data/lib/karafka/processing/consumer_groups/executor.rb +4 -4
- data/lib/karafka/processing/consumer_groups/executors_buffer.rb +2 -4
- data/lib/karafka/processing/consumer_groups/expansions_selector.rb +0 -2
- data/lib/karafka/processing/consumer_groups/inline_insights/consumer.rb +0 -2
- data/lib/karafka/processing/consumer_groups/inline_insights/listener.rb +0 -2
- data/lib/karafka/processing/consumer_groups/inline_insights/tracker.rb +14 -16
- data/lib/karafka/processing/consumer_groups/jobs/consume.rb +2 -5
- data/lib/karafka/processing/consumer_groups/jobs/eofed.rb +2 -3
- data/lib/karafka/processing/consumer_groups/jobs/idle.rb +2 -2
- data/lib/karafka/processing/consumer_groups/jobs/revoked.rb +2 -4
- data/lib/karafka/processing/consumer_groups/jobs/shutdown.rb +2 -2
- data/lib/karafka/processing/consumer_groups/partitioner.rb +3 -6
- data/lib/karafka/processing/consumer_groups/strategies/aj_dlq_mom.rb +5 -2
- data/lib/karafka/processing/consumer_groups/strategies/aj_mom.rb +2 -4
- data/lib/karafka/processing/consumer_groups/strategies/base.rb +3 -5
- data/lib/karafka/processing/consumer_groups/strategies/default.rb +43 -13
- data/lib/karafka/processing/consumer_groups/strategies/dlq.rb +5 -2
- data/lib/karafka/processing/consumer_groups/strategies/dlq_mom.rb +5 -2
- data/lib/karafka/processing/consumer_groups/strategies/mom.rb +2 -3
- data/lib/karafka/processing/consumer_groups/strategy_selector.rb +0 -2
- data/lib/karafka/processing/coordinator.rb +0 -2
- data/lib/karafka/processing/coordinators_buffer.rb +0 -2
- data/lib/karafka/processing/partitioner.rb +0 -2
- data/lib/karafka/processing/strategy_selector.rb +0 -2
- data/lib/karafka/processing/worker.rb +14 -6
- data/lib/karafka/processing/workers_pool.rb +21 -4
- data/lib/karafka/railtie.rb +0 -1
- data/lib/karafka/routing/contracts/routing.rb +2 -2
- data/lib/karafka/routing/features/consumer_groups/active_job/topic.rb +6 -5
- data/lib/karafka/routing/features/consumer_groups/manual_offset_management/topic.rb +2 -2
- data/lib/karafka/routing/features/deserializers/topic.rb +0 -1
- data/lib/karafka/routing/subscription_group.rb +1 -1
- data/lib/karafka/routing/topic.rb +4 -4
- data/lib/karafka/routing/topics.rb +21 -1
- data/lib/karafka/server.rb +9 -0
- data/lib/karafka/setup/config.rb +54 -10
- data/lib/karafka/setup/config_proxy.rb +2 -1
- data/lib/karafka/setup/contracts/config.rb +14 -0
- data/lib/karafka/swarm/node.rb +2 -2
- data/lib/karafka/version.rb +1 -2
- data/lib/karafka.rb +2 -2
- metadata +12 -4
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Processing
|
|
5
|
-
# Consumer-group-specific processing components (driven by rebalance callbacks and partition
|
|
6
|
-
# ticks). Parallel `ShareGroups` will live next to this namespace once KIP-932 lands.
|
|
7
5
|
module ConsumerGroups
|
|
8
6
|
# Consumer-group-specific job types
|
|
9
7
|
module Jobs
|
|
@@ -11,7 +9,8 @@ module Karafka
|
|
|
11
9
|
class Eofed < ::Karafka::Processing::Jobs::Base
|
|
12
10
|
self.action = :eofed
|
|
13
11
|
|
|
14
|
-
# @param executor [Karafka::Processing::ConsumerGroups::Executor] executor that is
|
|
12
|
+
# @param executor [Karafka::Processing::ConsumerGroups::Executor] executor that is
|
|
13
|
+
# supposed to run the job
|
|
15
14
|
# @return [Eofed]
|
|
16
15
|
def initialize(executor)
|
|
17
16
|
@executor = executor
|
|
@@ -9,8 +9,8 @@ module Karafka
|
|
|
9
9
|
class Idle < ::Karafka::Processing::Jobs::Base
|
|
10
10
|
self.action = :idle
|
|
11
11
|
|
|
12
|
-
# @param executor [Karafka::Processing::ConsumerGroups::Executor] executor that is
|
|
13
|
-
# job on an active consumer
|
|
12
|
+
# @param executor [Karafka::Processing::ConsumerGroups::Executor] executor that is
|
|
13
|
+
# supposed to run a given job on an active consumer
|
|
14
14
|
# @return [Idle]
|
|
15
15
|
def initialize(executor)
|
|
16
16
|
@executor = executor
|
|
@@ -2,16 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Processing
|
|
5
|
-
# Consumer-group-specific processing components (driven by rebalance callbacks and partition
|
|
6
|
-
# ticks). Parallel `ShareGroups` will live next to this namespace once KIP-932 lands.
|
|
7
5
|
module ConsumerGroups
|
|
8
|
-
# Consumer-group-specific job types
|
|
9
6
|
module Jobs
|
|
10
7
|
# Job that runs the revoked operation when we lose a partition on a consumer that lost it.
|
|
11
8
|
class Revoked < ::Karafka::Processing::Jobs::Base
|
|
12
9
|
self.action = :revoked
|
|
13
10
|
|
|
14
|
-
# @param executor [Karafka::Processing::ConsumerGroups::Executor] executor that is
|
|
11
|
+
# @param executor [Karafka::Processing::ConsumerGroups::Executor] executor that is
|
|
12
|
+
# supposed to run the job
|
|
15
13
|
# @return [Revoked]
|
|
16
14
|
def initialize(executor)
|
|
17
15
|
@executor = executor
|
|
@@ -8,8 +8,8 @@ module Karafka
|
|
|
8
8
|
class Shutdown < ::Karafka::Processing::Jobs::Base
|
|
9
9
|
self.action = :shutdown
|
|
10
10
|
|
|
11
|
-
# @param executor [Karafka::Processing::ConsumerGroups::Executor] executor that is
|
|
12
|
-
# job on an active consumer
|
|
11
|
+
# @param executor [Karafka::Processing::ConsumerGroups::Executor] executor that is
|
|
12
|
+
# supposed to run a given job on an active consumer
|
|
13
13
|
# @return [Shutdown]
|
|
14
14
|
def initialize(executor)
|
|
15
15
|
@executor = executor
|
|
@@ -2,11 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Processing
|
|
5
|
-
# Consumer-group-specific processing components (driven by rebalance callbacks and partition
|
|
6
|
-
# ticks). Parallel `ShareGroups` will live next to this namespace once KIP-932 lands.
|
|
7
5
|
module ConsumerGroups
|
|
8
|
-
# Basic partitioner for work division
|
|
9
|
-
# It does not divide any work.
|
|
6
|
+
# Basic partitioner for work division. It does not divide any work.
|
|
10
7
|
class Partitioner
|
|
11
8
|
# @param subscription_group [Karafka::Routing::SubscriptionGroup] subscription group
|
|
12
9
|
def initialize(subscription_group)
|
|
@@ -15,8 +12,8 @@ module Karafka
|
|
|
15
12
|
|
|
16
13
|
# @param _topic [String] topic name
|
|
17
14
|
# @param messages [Array<Karafka::Messages::Message>] karafka messages
|
|
18
|
-
# @param _coordinator [Karafka::Processing::ConsumerGroups::Coordinator] processing
|
|
19
|
-
# be used with those messages
|
|
15
|
+
# @param _coordinator [Karafka::Processing::ConsumerGroups::Coordinator] processing
|
|
16
|
+
# coordinator that will be used with those messages
|
|
20
17
|
# @yieldparam [Integer] group id
|
|
21
18
|
# @yieldparam [Array<Karafka::Messages::Message>] karafka messages
|
|
22
19
|
def call(_topic, messages, _coordinator)
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Processing
|
|
5
|
-
# Consumer-group-specific processing components (driven by rebalance callbacks and partition
|
|
6
|
-
# ticks). Parallel `ShareGroups` will live next to this namespace once KIP-932 lands.
|
|
7
5
|
module ConsumerGroups
|
|
8
6
|
module Strategies
|
|
9
7
|
# ActiveJob strategy to cooperate with the DLQ.
|
|
@@ -28,6 +26,11 @@ module Karafka
|
|
|
28
26
|
if coordinator.success?
|
|
29
27
|
# Do NOT commit offsets, they are comitted after each job in the AJ consumer.
|
|
30
28
|
coordinator.pause_tracker.reset
|
|
29
|
+
# Process-critical errors are never dispatched to the DLQ regardless of the retries
|
|
30
|
+
# state: the retry pause protects the partition during the critical shutdown and
|
|
31
|
+
# the failed batch is redelivered after the restart
|
|
32
|
+
elsif critical_error?(coordinator.consumption(self).cause)
|
|
33
|
+
retry_after_pause
|
|
31
34
|
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
|
32
35
|
retry_after_pause
|
|
33
36
|
else
|
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Processing
|
|
5
|
-
# Consumer-group-specific processing components (driven by rebalance callbacks and partition
|
|
6
|
-
# ticks). Parallel `ShareGroups` will live next to this namespace once KIP-932 lands.
|
|
7
5
|
module ConsumerGroups
|
|
8
6
|
module Strategies
|
|
9
|
-
# ActiveJob enabled
|
|
10
|
-
# Manual offset management enabled
|
|
7
|
+
# - ActiveJob enabled
|
|
8
|
+
# - Manual offset management enabled
|
|
11
9
|
#
|
|
12
10
|
# This is the default AJ strategy since AJ cannot be used without MOM
|
|
13
11
|
module AjMom
|
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Processing
|
|
5
|
-
# Consumer-group-specific processing components (driven by rebalance callbacks and partition
|
|
6
|
-
# ticks). Parallel `ShareGroups` will live next to this namespace once KIP-932 lands.
|
|
7
5
|
module ConsumerGroups
|
|
8
|
-
# Our processing patterns differ depending on various features configurations
|
|
9
|
-
#
|
|
10
|
-
#
|
|
6
|
+
# Our processing patterns differ depending on various features configurations. In this
|
|
7
|
+
# namespace we collect strategies for particular feature combinations to simplify the design.
|
|
8
|
+
# Based on features combinations we can then select handling strategy for a given case.
|
|
11
9
|
#
|
|
12
10
|
# @note The lack of common code here is intentional. It would get complex if there would be
|
|
13
11
|
# any type of composition, so each strategy is expected to be self-sufficient
|
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Processing
|
|
5
|
-
# Consumer-group-specific processing components (driven by rebalance callbacks and partition
|
|
6
|
-
# ticks). Parallel `ShareGroups` will live next to this namespace once KIP-932 lands.
|
|
7
5
|
module ConsumerGroups
|
|
8
6
|
module Strategies
|
|
9
|
-
# No features enabled
|
|
10
|
-
# No manual offset management
|
|
11
|
-
# No long running jobs
|
|
7
|
+
# No features enabled:
|
|
8
|
+
# - No manual offset management
|
|
9
|
+
# - No long running jobs
|
|
10
|
+
#
|
|
12
11
|
# Nothing. Just standard, automatic flow
|
|
13
12
|
module Default
|
|
14
13
|
include Base
|
|
@@ -59,9 +58,18 @@ module Karafka
|
|
|
59
58
|
# In case like this we ignore marking
|
|
60
59
|
return true if seek_offset.nil?
|
|
61
60
|
# Ignore double markings of the same offset
|
|
61
|
+
# Only this exact re-mark is skipped - marking genuinely older offsets is intentionally
|
|
62
|
+
# allowed and rewinds the seek offset for reprocessing (see #2432)
|
|
62
63
|
return true if (seek_offset - 1) == message.offset
|
|
63
64
|
return false if revoked?
|
|
64
|
-
|
|
65
|
+
unless client.mark_as_consumed(message)
|
|
66
|
+
# Evaluate ownership for its coordinator-revoking side effect - all marking
|
|
67
|
+
# failure causes are ownership related. The failure itself always reports false:
|
|
68
|
+
# the offset was not stored, regardless of the current ownership state
|
|
69
|
+
revoked?
|
|
70
|
+
|
|
71
|
+
return false
|
|
72
|
+
end
|
|
65
73
|
|
|
66
74
|
self.seek_offset = message.offset + 1
|
|
67
75
|
|
|
@@ -78,10 +86,19 @@ module Karafka
|
|
|
78
86
|
# In case like this we ignore marking
|
|
79
87
|
return true if seek_offset.nil?
|
|
80
88
|
# Ignore double markings of the same offset
|
|
89
|
+
# Only this exact re-mark is skipped - marking genuinely older offsets is intentionally
|
|
90
|
+
# allowed and rewinds the seek offset for reprocessing (see #2432)
|
|
81
91
|
return true if (seek_offset - 1) == message.offset
|
|
82
92
|
return false if revoked?
|
|
83
93
|
|
|
84
|
-
|
|
94
|
+
unless client.mark_as_consumed!(message)
|
|
95
|
+
# Evaluate ownership for its coordinator-revoking side effect - all marking
|
|
96
|
+
# failure causes are ownership related. The failure itself always reports false:
|
|
97
|
+
# the offset was not committed, regardless of the current ownership state
|
|
98
|
+
revoked?
|
|
99
|
+
|
|
100
|
+
return false
|
|
101
|
+
end
|
|
85
102
|
|
|
86
103
|
self.seek_offset = message.offset + 1
|
|
87
104
|
|
|
@@ -91,17 +108,27 @@ module Karafka
|
|
|
91
108
|
# Triggers an async offset commit
|
|
92
109
|
#
|
|
93
110
|
# @param async [Boolean] should we use async (default) or sync commit
|
|
94
|
-
# @return [Boolean] true if we still
|
|
111
|
+
# @return [Boolean] true if the commit went through and we still owned the partition
|
|
112
|
+
# at that time, false otherwise. False means the offsets were not committed - the
|
|
113
|
+
# caller can retry (the offsets stay stored client-side) or treat the partition as
|
|
114
|
+
# fenced.
|
|
95
115
|
# @note Due to its async nature, this may not fully represent the offset state in some
|
|
96
116
|
# edge cases (like for example going beyond max.poll.interval)
|
|
117
|
+
# @note A commit with no offsets pending is a client-side no-op reported as success
|
|
118
|
+
# without broker validation - the marking result is the fence for that case.
|
|
97
119
|
def commit_offsets(async: true)
|
|
98
120
|
# Do not commit if we already lost the assignment
|
|
99
121
|
return false if revoked?
|
|
100
122
|
return true if client.commit_offsets(async: async)
|
|
101
123
|
|
|
102
|
-
#
|
|
103
|
-
#
|
|
124
|
+
# Evaluate ownership once more for its coordinator-revoking side effect: all
|
|
125
|
+
# commit failure causes the client reports as false are ownership related. The
|
|
126
|
+
# failed commit itself always reports false - its value must not depend on the
|
|
127
|
+
# revocation state, which may not yet be locally visible (or may indicate a
|
|
128
|
+
# retained partition under a cooperative rebalance generation bump)
|
|
104
129
|
revoked?
|
|
130
|
+
|
|
131
|
+
false
|
|
105
132
|
end
|
|
106
133
|
|
|
107
134
|
# Triggers a synchronous offsets commit to Kafka
|
|
@@ -138,7 +165,10 @@ module Karafka
|
|
|
138
165
|
|
|
139
166
|
# Mark job as successful
|
|
140
167
|
coordinator.success!(self)
|
|
141
|
-
|
|
168
|
+
# Failure recording must be class-agnostic: an unrecorded non-StandardError would
|
|
169
|
+
# leave the consumption result in its default (successful) state and the after-consume
|
|
170
|
+
# flow would mark the failed batch as consumed instead of engaging the retry
|
|
171
|
+
rescue Exception => e
|
|
142
172
|
coordinator.failure!(self, e)
|
|
143
173
|
|
|
144
174
|
# Re-raise so reported in the consumer
|
|
@@ -187,8 +217,8 @@ module Karafka
|
|
|
187
217
|
end
|
|
188
218
|
|
|
189
219
|
# We need to always un-pause the processing in case we have lost a given partition.
|
|
190
|
-
# Otherwise the underlying librdkafka would not know we may want to continue processing
|
|
191
|
-
# the pause could in theory last forever
|
|
220
|
+
# Otherwise the underlying librdkafka would not know we may want to continue processing
|
|
221
|
+
# and the pause could in theory last forever
|
|
192
222
|
def handle_revoked
|
|
193
223
|
resume
|
|
194
224
|
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Processing
|
|
5
|
-
# Consumer-group-specific processing components (driven by rebalance callbacks and partition
|
|
6
|
-
# ticks). Parallel `ShareGroups` will live next to this namespace once KIP-932 lands.
|
|
7
5
|
module ConsumerGroups
|
|
8
6
|
module Strategies
|
|
9
7
|
# When using dead letter queue, processing won't stop after defined number of retries
|
|
@@ -64,6 +62,11 @@ module Karafka
|
|
|
64
62
|
return if coordinator.manual_pause?
|
|
65
63
|
|
|
66
64
|
mark_as_consumed(messages.last)
|
|
65
|
+
# Process-critical errors are never dispatched to the DLQ regardless of the retries
|
|
66
|
+
# state: the retry pause protects the partition during the critical shutdown and
|
|
67
|
+
# the failed batch is redelivered after the restart
|
|
68
|
+
elsif critical_error?(coordinator.consumption(self).cause)
|
|
69
|
+
retry_after_pause
|
|
67
70
|
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
|
68
71
|
retry_after_pause
|
|
69
72
|
# If we've reached number of retries that we could, we need to skip the first message
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Processing
|
|
5
|
-
# Consumer-group-specific processing components (driven by rebalance callbacks and partition
|
|
6
|
-
# ticks). Parallel `ShareGroups` will live next to this namespace once KIP-932 lands.
|
|
7
5
|
module ConsumerGroups
|
|
8
6
|
module Strategies
|
|
9
7
|
# Same as pure dead letter queue but we do not marked failed message as consumed
|
|
@@ -23,6 +21,11 @@ module Karafka
|
|
|
23
21
|
|
|
24
22
|
if coordinator.success?
|
|
25
23
|
coordinator.pause_tracker.reset
|
|
24
|
+
# Process-critical errors are never dispatched to the DLQ regardless of the retries
|
|
25
|
+
# state: the retry pause protects the partition during the critical shutdown and
|
|
26
|
+
# the failed batch is redelivered after the restart
|
|
27
|
+
elsif critical_error?(coordinator.consumption(self).cause)
|
|
28
|
+
retry_after_pause
|
|
26
29
|
elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
|
|
27
30
|
retry_after_pause
|
|
28
31
|
# If we've reached number of retries that we could, we need to skip the first message
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Processing
|
|
5
|
-
# Consumer-group-specific processing components (driven by rebalance callbacks and partition
|
|
6
|
-
# ticks). Parallel `ShareGroups` will live next to this namespace once KIP-932 lands.
|
|
7
5
|
module ConsumerGroups
|
|
8
6
|
module Strategies
|
|
9
|
-
# When using manual offset management, we do not mark as consumed after successful
|
|
7
|
+
# When using manual offset management, we do not mark as consumed after successful
|
|
8
|
+
# processing
|
|
10
9
|
module Mom
|
|
11
10
|
include Default
|
|
12
11
|
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Processing
|
|
5
|
-
# Consumer-group-specific processing components (driven by rebalance callbacks and partition
|
|
6
|
-
# ticks). Parallel `ShareGroups` will live next to this namespace once KIP-932 lands.
|
|
7
5
|
module ConsumerGroups
|
|
8
6
|
# Selector of appropriate processing strategy matching topic combinations
|
|
9
7
|
class StrategySelector
|
|
@@ -45,10 +45,16 @@ module Karafka
|
|
|
45
45
|
|
|
46
46
|
# Fetches a single job, processes it and marks as completed.
|
|
47
47
|
#
|
|
48
|
-
# @note
|
|
49
|
-
#
|
|
48
|
+
# @note No user or framework errors should propagate this far. If they do, it is a critical
|
|
49
|
+
# error that we instrument while keeping the worker alive.
|
|
50
50
|
#
|
|
51
51
|
# @note Upon closing the jobs queue, worker will close it's thread
|
|
52
|
+
#
|
|
53
|
+
# @return [Boolean] should the worker keep running. False only when the jobs queue is
|
|
54
|
+
# closed (full shutdown) or a downscale sentinel was received. This decision is
|
|
55
|
+
# deliberately decoupled from the processing flow result: the flow passes through the
|
|
56
|
+
# user-redefinable `#wrap`, whose return value (or an error raised in user code or in an
|
|
57
|
+
# instrumentation subscriber) must never be able to silently kill the worker thread.
|
|
52
58
|
def process
|
|
53
59
|
job = @jobs_queue.pop
|
|
54
60
|
|
|
@@ -76,10 +82,10 @@ module Karafka
|
|
|
76
82
|
end
|
|
77
83
|
|
|
78
84
|
job.after_call
|
|
79
|
-
|
|
80
|
-
true
|
|
81
85
|
end
|
|
82
86
|
end
|
|
87
|
+
|
|
88
|
+
true
|
|
83
89
|
else
|
|
84
90
|
# nil means either queue closed (full shutdown) or pool downscaling.
|
|
85
91
|
# Either way, deregister from pool so it reflects the actual worker count.
|
|
@@ -87,9 +93,7 @@ module Karafka
|
|
|
87
93
|
false
|
|
88
94
|
end
|
|
89
95
|
# We signal critical exceptions, notify and do not allow worker to fail
|
|
90
|
-
# rubocop:disable Lint/RescueException
|
|
91
96
|
rescue Exception => e
|
|
92
|
-
# rubocop:enable Lint/RescueException
|
|
93
97
|
monitor.instrument(
|
|
94
98
|
"error.occurred",
|
|
95
99
|
caller: self,
|
|
@@ -98,6 +102,10 @@ module Karafka
|
|
|
98
102
|
error: e,
|
|
99
103
|
type: "worker.process.error"
|
|
100
104
|
)
|
|
105
|
+
|
|
106
|
+
# Keep the worker alive. Without an explicit true this arm would return the result of
|
|
107
|
+
# the instrumentation call (nil) and the worker thread would silently exit
|
|
108
|
+
true
|
|
101
109
|
ensure
|
|
102
110
|
# job can be nil when the queue is being closed or during pool downscaling
|
|
103
111
|
if job
|
|
@@ -39,6 +39,13 @@ module Karafka
|
|
|
39
39
|
# after a worker exits, so thread names remain unique across the lifetime of the process
|
|
40
40
|
# and make it easy to correlate log entries with specific worker generations.
|
|
41
41
|
@next_index = 0
|
|
42
|
+
# Number of downscale sentinels enqueued but not yet picked up by a worker. Workers
|
|
43
|
+
# deregister asynchronously, so the live thread count alone overstates the pool between
|
|
44
|
+
# a scale-down request and its completion. All sizing decisions use the committed size
|
|
45
|
+
# (live workers minus pending shrinks) so repeated or overlapping scale-down requests do
|
|
46
|
+
# not enqueue duplicate sentinels and drain the pool below the requested target (or
|
|
47
|
+
# below the minimum of one worker).
|
|
48
|
+
@pending_shrinks = 0
|
|
42
49
|
end
|
|
43
50
|
|
|
44
51
|
# Scale pool towards `target` workers (minimum 1).
|
|
@@ -63,7 +70,9 @@ module Karafka
|
|
|
63
70
|
event = nil
|
|
64
71
|
|
|
65
72
|
@mutex.synchronize do
|
|
66
|
-
|
|
73
|
+
# Compute against the committed size, not the live thread count: sentinels already in
|
|
74
|
+
# flight are removals this pool is committed to, just not yet executed by the workers
|
|
75
|
+
current = @workers.size - @pending_shrinks
|
|
67
76
|
delta = target - current
|
|
68
77
|
|
|
69
78
|
if delta.positive?
|
|
@@ -106,6 +115,11 @@ module Karafka
|
|
|
106
115
|
@mutex.synchronize do
|
|
107
116
|
@workers.delete(worker)
|
|
108
117
|
@size = @workers.size
|
|
118
|
+
# A worker exits either because it picked up a downscale sentinel or because the jobs
|
|
119
|
+
# queue was closed for shutdown. The worker cannot tell those apart, so pending
|
|
120
|
+
# removals are settled here, with a floor because shutdown exits may have no pending
|
|
121
|
+
# shrink to consume
|
|
122
|
+
@pending_shrinks -= 1 if @pending_shrinks.positive?
|
|
109
123
|
end
|
|
110
124
|
end
|
|
111
125
|
|
|
@@ -142,14 +156,17 @@ module Karafka
|
|
|
142
156
|
#
|
|
143
157
|
# @param count [Integer] number of workers to remove
|
|
144
158
|
# @return [Array, nil] instrumentation event args or nil if no-op
|
|
145
|
-
# @note Never shrinks below 1 worker
|
|
159
|
+
# @note Never shrinks below 1 worker, including removals already in flight - the cap is
|
|
160
|
+
# computed against the committed size, not the live thread count.
|
|
146
161
|
def shrink(count)
|
|
147
|
-
|
|
162
|
+
committed = @workers.size - @pending_shrinks
|
|
163
|
+
effective = [count, committed - 1].min
|
|
148
164
|
return if effective <= 0
|
|
149
165
|
|
|
150
166
|
from = @workers.size
|
|
167
|
+
@pending_shrinks += effective
|
|
151
168
|
effective.times { @jobs_queue << nil }
|
|
152
|
-
to =
|
|
169
|
+
to = committed - effective
|
|
153
170
|
|
|
154
171
|
["worker.scaling.down", { workers_pool: self, from: from, to: to }]
|
|
155
172
|
end
|
data/lib/karafka/railtie.rb
CHANGED
|
@@ -12,8 +12,8 @@ module Karafka
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
# Ensures, that when declarative topics strict requirement is on, all topics have
|
|
15
|
-
# declarative definition (including DLQ topics)
|
|
16
|
-
#
|
|
15
|
+
# declarative definition (including DLQ topics). It will ignore routing pattern topics
|
|
16
|
+
# because those topics are virtual
|
|
17
17
|
virtual do |data, errors|
|
|
18
18
|
next unless errors.empty?
|
|
19
19
|
# Do not validate declaratives unless required and explicitly enabled
|
|
@@ -7,11 +7,12 @@ module Karafka
|
|
|
7
7
|
class ActiveJob < Base
|
|
8
8
|
# Topic extensions to be able to check if given topic is ActiveJob topic
|
|
9
9
|
#
|
|
10
|
-
# @note ActiveJob topics do not have per-topic deserializer configuration. The
|
|
11
|
-
# is configured globally via `config.internal.active_job.deserializer`
|
|
12
|
-
# serializes jobs before dispatching them, requiring a consistent
|
|
13
|
-
# across all ActiveJob topics. If you need custom serialization
|
|
14
|
-
# configure it once at the application level rather than
|
|
10
|
+
# @note ActiveJob topics do not have per-topic deserializer configuration. The
|
|
11
|
+
# deserializer is configured globally via `config.internal.active_job.deserializer`
|
|
12
|
+
# because Rails serializes jobs before dispatching them, requiring a consistent
|
|
13
|
+
# serialization format across all ActiveJob topics. If you need custom serialization
|
|
14
|
+
# (e.g., Avro, Protobuf), configure it once at the application level rather than
|
|
15
|
+
# per-topic.
|
|
15
16
|
module Topic
|
|
16
17
|
# This method sets up the extra instance variable to nil before calling
|
|
17
18
|
# the parent class initializer. The explicit initialization
|
|
@@ -16,8 +16,8 @@ module Karafka
|
|
|
16
16
|
super
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
# @param active [Boolean] should we stop managing the offset in Karafka and make the
|
|
20
|
-
# responsible for marking messages as consumed.
|
|
19
|
+
# @param active [Boolean] should we stop managing the offset in Karafka and make the
|
|
20
|
+
# user responsible for marking messages as consumed.
|
|
21
21
|
# @return [Config] defined config
|
|
22
22
|
#
|
|
23
23
|
# @note Since this feature supports only one setting (active), we can use the old API
|
|
@@ -16,7 +16,7 @@ module Karafka
|
|
|
16
16
|
|
|
17
17
|
attr_reader :id, :name, :topics, :kafka, :group, :position
|
|
18
18
|
|
|
19
|
-
# Backwards compatible alias for `#group`. Kept purely for compatibility
|
|
19
|
+
# Backwards compatible alias for `#group`. Kept purely for compatibility - this is an
|
|
20
20
|
# unconditional alias and performs no type validation, so callers should prefer `#group`
|
|
21
21
|
# once additional group types (e.g. KIP-932 share groups) land.
|
|
22
22
|
alias_method :consumer_group, :group
|
|
@@ -14,7 +14,7 @@ module Karafka
|
|
|
14
14
|
attr_reader :id, :name, :group
|
|
15
15
|
attr_writer :consumer
|
|
16
16
|
|
|
17
|
-
# Backwards compatible alias for `#group`. Kept purely for compatibility
|
|
17
|
+
# Backwards compatible alias for `#group`. Kept purely for compatibility - this is an
|
|
18
18
|
# unconditional alias and performs no type validation, so callers should prefer `#group`
|
|
19
19
|
# once additional group types (e.g. KIP-932 share groups) land.
|
|
20
20
|
alias_method :consumer_group, :group
|
|
@@ -47,9 +47,9 @@ module Karafka
|
|
|
47
47
|
@group = group
|
|
48
48
|
@attributes = {}
|
|
49
49
|
@active = true
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
#
|
|
50
|
+
# We use identifier related to the group that owns a topic, because from Karafka 0.6 we can
|
|
51
|
+
# handle multiple Kafka instances with the same process and we can have same topic name
|
|
52
|
+
# across multiple groups
|
|
53
53
|
@id = "#{group.id}_#{@name}"
|
|
54
54
|
@consumer = nil
|
|
55
55
|
@active_assigned = false
|
|
@@ -7,13 +7,33 @@ module Karafka
|
|
|
7
7
|
include Enumerable
|
|
8
8
|
extend Forwardable
|
|
9
9
|
|
|
10
|
-
def_delegators :@accumulator, :[], :size, :empty?, :last,
|
|
10
|
+
def_delegators :@accumulator, :[], :size, :empty?, :last, :map!, :sort_by!, :reverse!
|
|
11
11
|
|
|
12
12
|
# @param topics_array [Array<Karafka::Routing::Topic>] array with topics
|
|
13
13
|
def initialize(topics_array)
|
|
14
14
|
@accumulator = topics_array.dup
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
# Adds a topic using copy-on-write: we publish a brand-new accumulator array instead of
|
|
18
|
+
# mutating the existing one in place.
|
|
19
|
+
#
|
|
20
|
+
# @param topic [Karafka::Routing::Topic] topic that should become part of this consumer
|
|
21
|
+
# group's topics
|
|
22
|
+
# @return [self]
|
|
23
|
+
#
|
|
24
|
+
# @note Topics can be appended to this collection at runtime from one thread while other
|
|
25
|
+
# threads iterate the same collection (for example during routing lookups). Swapping the
|
|
26
|
+
# `@accumulator` reference atomically (rather than appending in place) guarantees a
|
|
27
|
+
# concurrent `#each` always traverses a complete, immutable snapshot: it either sees the
|
|
28
|
+
# newly added topic or it does not, but never a torn array. This holds on every Ruby
|
|
29
|
+
# runtime, not only on MRI's GIL. The in-place mutators above (`map!`, `sort_by!`,
|
|
30
|
+
# `reverse!`) only run while routes are built at boot, single-threaded, so they do not
|
|
31
|
+
# need the same treatment.
|
|
32
|
+
def <<(topic)
|
|
33
|
+
@accumulator += [topic]
|
|
34
|
+
self
|
|
35
|
+
end
|
|
36
|
+
|
|
17
37
|
# Yields each topic
|
|
18
38
|
def each(&)
|
|
19
39
|
@accumulator.each(&)
|
data/lib/karafka/server.rb
CHANGED
|
@@ -168,6 +168,15 @@ module Karafka
|
|
|
168
168
|
# otherwise we would overwrite the shutdown process of the process that started Karafka
|
|
169
169
|
return unless process.supervised?
|
|
170
170
|
|
|
171
|
+
# We intentionally do NOT flush or close the producer before the `Kernel.exit!` below.
|
|
172
|
+
# Forceful shutdown is a last resort - a job already exceeded `shutdown_timeout` - and it
|
|
173
|
+
# is expected that in-flight, async-buffered data (user `produce_async` calls and DLQ
|
|
174
|
+
# `produce_async` copies) may be lost. Flushing here would be risky precisely when it
|
|
175
|
+
# matters: the producer (or its connection pool) may itself be the resource that is blocked
|
|
176
|
+
# (e.g. an unreachable broker), so waiting on it could stall or hang the very forceful exit
|
|
177
|
+
# that must guarantee the process terminates. On a normal (graceful) shutdown the producer
|
|
178
|
+
# is still closed via the `ensure` block below, which `exit!` deliberately skips here.
|
|
179
|
+
#
|
|
171
180
|
# exit! is not within the instrumentation as it would not trigger due to exit
|
|
172
181
|
Kernel.exit!(forceful_exit_code)
|
|
173
182
|
ensure
|