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
data/lib/karafka/admin.rb
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
module Karafka
|
|
4
4
|
# Admin actions that we can perform via Karafka on our Kafka cluster
|
|
5
5
|
#
|
|
6
|
-
# @note
|
|
7
|
-
# Since admin actions are not performed that often, that should be ok.
|
|
6
|
+
# @note Each operation initializes its own dedicated instance as we want to ensure it is
|
|
7
|
+
# always closed. Since admin actions are not performed that often, that should be ok. When
|
|
8
|
+
# an external client is provided, it is reused instead and its lifecycle stays fully with
|
|
9
|
+
# its owner.
|
|
8
10
|
#
|
|
9
11
|
# @note By default it uses the primary defined cluster. For multi-cluster operations, create
|
|
10
12
|
# an Admin instance with custom kafka configuration:
|
|
@@ -22,34 +24,80 @@ module Karafka
|
|
|
22
24
|
admin_kafka: %i[admin kafka]
|
|
23
25
|
)
|
|
24
26
|
|
|
25
|
-
# Custom kafka configuration for this admin instance
|
|
26
|
-
# @return [Hash] custom kafka settings to merge with defaults
|
|
27
|
-
attr_reader :custom_kafka
|
|
28
|
-
|
|
29
27
|
# Creates a new Admin instance
|
|
30
28
|
#
|
|
31
29
|
# @param kafka [Hash] custom kafka configuration to merge with app defaults.
|
|
32
30
|
# Useful for multi-cluster operations where you want to target a different cluster.
|
|
31
|
+
# @param external_client [Object, nil] active rdkafka client (raw, wrapped with
|
|
32
|
+
# `Karafka::Connection::Proxy` or a `Karafka::Connection::Client` of a running consumer)
|
|
33
|
+
# on which admin operations should run, instead of each operation creating its own
|
|
34
|
+
# short-lived instance. Routing is capability based: rdkafka admin instances are used by
|
|
35
|
+
# admin-based operations (`with_admin` and everything built on top of it, e.g.
|
|
36
|
+
# `cluster_info`), any other external client is used by consumer-based operations
|
|
37
|
+
# (`with_consumer` and everything built on top of it). The lifecycle of an external
|
|
38
|
+
# client belongs fully to its owner: it is never configured, started or closed here and
|
|
39
|
+
# all operations run within its identity, including its `group.id`. This is a low-level
|
|
40
|
+
# internal API: the caller is responsible for providing a client capable of the invoked
|
|
41
|
+
# operations and for invoking only operations that are safe to run on a live client.
|
|
42
|
+
#
|
|
43
|
+
# @note Raw and proxied rdkafka instances are resolved once at construction, so the admin
|
|
44
|
+
# instance should not outlive them. `Karafka::Connection::Client` instances are resolved
|
|
45
|
+
# on each use instead, so the admin instance follows such a client across the underlying
|
|
46
|
+
# connection recovery resets.
|
|
33
47
|
#
|
|
34
48
|
# @example Create admin for a different cluster
|
|
35
49
|
# admin = Karafka::Admin.new(kafka: { 'bootstrap.servers': 'other-cluster:9092' })
|
|
36
50
|
# admin.cluster_info
|
|
37
|
-
|
|
51
|
+
#
|
|
52
|
+
# @example Read lags of a running consumer via its own client connection
|
|
53
|
+
# admin = Karafka::Admin.new(external_client: client)
|
|
54
|
+
# admin.read_lags_with_offsets({ 'my-group' => ['events'] })
|
|
55
|
+
def initialize(kafka: {}, external_client: nil)
|
|
38
56
|
@custom_kafka = kafka
|
|
57
|
+
@external_client = nil
|
|
58
|
+
@external_admin = false
|
|
59
|
+
@external_consumer = false
|
|
60
|
+
|
|
61
|
+
return unless external_client
|
|
62
|
+
|
|
63
|
+
# A running consumer connection client is kept as-is and its current handle is resolved
|
|
64
|
+
# on each use: such clients swap their underlying rdkafka instance across recovery
|
|
65
|
+
# resets, so a handle resolved once at construction could go stale while the client
|
|
66
|
+
# itself remains fully operational
|
|
67
|
+
if external_client.is_a?(Karafka::Connection::Client)
|
|
68
|
+
@external_client = external_client
|
|
69
|
+
@external_consumer = true
|
|
70
|
+
|
|
71
|
+
return
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Raw and proxied rdkafka instances are wrapped upfront - the proxy itself prevents
|
|
75
|
+
# double wrapping
|
|
76
|
+
@external_client = Karafka::Connection::Proxy.new(external_client)
|
|
77
|
+
|
|
78
|
+
# Capability based routing resolved once upfront: rdkafka admin instances serve
|
|
79
|
+
# admin-based operations, any other external client is assumed consumer capable
|
|
80
|
+
if @external_client.wrapped.is_a?(Rdkafka::Admin)
|
|
81
|
+
@external_admin = true
|
|
82
|
+
else
|
|
83
|
+
@external_consumer = true
|
|
84
|
+
end
|
|
39
85
|
end
|
|
40
86
|
|
|
41
87
|
# No-op close to normalize the API surface.
|
|
42
88
|
#
|
|
43
|
-
# Each admin operation
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
89
|
+
# Each admin operation opens and closes its own dedicated rdkafka instance internally,
|
|
90
|
+
# while external clients are owned and closed by their providers, so there is nothing to
|
|
91
|
+
# release at the `Karafka::Admin` level right now. This method exists so that callers who
|
|
92
|
+
# hold an instance and call `#close` on it (matching the pattern of other closeable
|
|
93
|
+
# resources) do not raise `NoMethodError`.
|
|
47
94
|
#
|
|
48
|
-
# In the future, `Karafka::Admin` is planned to be refactored to reuse a single
|
|
49
|
-
# instance across multiple operations rather than creating and tearing one
|
|
50
|
-
# that happens, this method will need to release that shared
|
|
51
|
-
#
|
|
52
|
-
# the
|
|
95
|
+
# In the future, `Karafka::Admin` is planned to be refactored to reuse a single owned
|
|
96
|
+
# rdkafka admin instance across multiple operations rather than creating and tearing one
|
|
97
|
+
# down per call. When that happens, this method will need to release that shared owned
|
|
98
|
+
# instance - though never an external client. The no-op is here now so that all callers are
|
|
99
|
+
# already written against the correct API and require no changes when the real
|
|
100
|
+
# implementation lands.
|
|
53
101
|
def close
|
|
54
102
|
end
|
|
55
103
|
|
|
@@ -257,7 +305,7 @@ module Karafka
|
|
|
257
305
|
# @param settings [Hash] kafka extra settings (optional)
|
|
258
306
|
# @see Topics#read
|
|
259
307
|
def read_topic(name, partition, count, start_offset = -1, settings = {})
|
|
260
|
-
|
|
308
|
+
topics_admin.read(name, partition, count, start_offset, settings)
|
|
261
309
|
end
|
|
262
310
|
|
|
263
311
|
# @param name [String] topic name
|
|
@@ -266,47 +314,47 @@ module Karafka
|
|
|
266
314
|
# @param topic_config [Hash] topic config details
|
|
267
315
|
# @see Topics#create
|
|
268
316
|
def create_topic(name, partitions, replication_factor, topic_config = {})
|
|
269
|
-
|
|
317
|
+
topics_admin.create(name, partitions, replication_factor, topic_config)
|
|
270
318
|
end
|
|
271
319
|
|
|
272
320
|
# @param name [String] topic name
|
|
273
321
|
# @see Topics#delete
|
|
274
322
|
def delete_topic(name)
|
|
275
|
-
|
|
323
|
+
topics_admin.delete(name)
|
|
276
324
|
end
|
|
277
325
|
|
|
278
326
|
# @param name [String] topic name
|
|
279
327
|
# @param partitions [Integer] total number of partitions we expect to end up with
|
|
280
328
|
# @see Topics#create_partitions
|
|
281
329
|
def create_partitions(name, partitions)
|
|
282
|
-
|
|
330
|
+
topics_admin.create_partitions(name, partitions)
|
|
283
331
|
end
|
|
284
332
|
|
|
285
333
|
# @param name_or_hash [String, Symbol, Hash] topic name or hash with topics and partitions
|
|
286
334
|
# @param partition [Integer, nil] partition (nil when using hash format)
|
|
287
335
|
# @see Topics#read_watermark_offsets
|
|
288
336
|
def read_watermark_offsets(name_or_hash, partition = nil)
|
|
289
|
-
|
|
337
|
+
topics_admin.read_watermark_offsets(name_or_hash, partition)
|
|
290
338
|
end
|
|
291
339
|
|
|
292
340
|
# @param topic_partition_offsets [Hash{String => Array<Hash>}] topics with partition specs
|
|
293
341
|
# @param isolation_level [Integer, nil] optional isolation level constant
|
|
294
342
|
# @see Topics#read_partition_offsets
|
|
295
343
|
def read_partition_offsets(topic_partition_offsets, isolation_level: nil)
|
|
296
|
-
|
|
344
|
+
topics_admin.read_partition_offsets(topic_partition_offsets, isolation_level: isolation_level)
|
|
297
345
|
end
|
|
298
346
|
|
|
299
347
|
# @param topic_name [String] name of the topic we're interested in
|
|
300
348
|
# @see Topics#info
|
|
301
349
|
def topic_info(topic_name)
|
|
302
|
-
|
|
350
|
+
topics_admin.info(topic_name)
|
|
303
351
|
end
|
|
304
352
|
|
|
305
353
|
# @param group_id [String] group for which we want to move offsets
|
|
306
354
|
# @param topics_with_partitions_and_offsets [Hash] hash with topics and settings
|
|
307
355
|
# @see ConsumerGroups#seek
|
|
308
356
|
def seek_consumer_group(group_id, topics_with_partitions_and_offsets)
|
|
309
|
-
|
|
357
|
+
consumer_groups_admin.seek(
|
|
310
358
|
group_id,
|
|
311
359
|
topics_with_partitions_and_offsets
|
|
312
360
|
)
|
|
@@ -317,7 +365,7 @@ module Karafka
|
|
|
317
365
|
# @param topics [Array<String>] topics for which we want to copy offsets
|
|
318
366
|
# @see ConsumerGroups#copy
|
|
319
367
|
def copy_consumer_group(previous_name, new_name, topics)
|
|
320
|
-
|
|
368
|
+
consumer_groups_admin.copy(previous_name, new_name, topics)
|
|
321
369
|
end
|
|
322
370
|
|
|
323
371
|
# @param previous_name [String] old consumer group name
|
|
@@ -326,7 +374,7 @@ module Karafka
|
|
|
326
374
|
# @param delete_previous [Boolean] should we delete previous consumer group after rename
|
|
327
375
|
# @see ConsumerGroups#rename
|
|
328
376
|
def rename_consumer_group(previous_name, new_name, topics, delete_previous: true)
|
|
329
|
-
|
|
377
|
+
consumer_groups_admin.rename(
|
|
330
378
|
previous_name,
|
|
331
379
|
new_name,
|
|
332
380
|
topics,
|
|
@@ -337,13 +385,13 @@ module Karafka
|
|
|
337
385
|
# @param group_id [String] group name
|
|
338
386
|
# @see ConsumerGroups#delete
|
|
339
387
|
def delete_consumer_group(group_id)
|
|
340
|
-
|
|
388
|
+
consumer_groups_admin.delete(group_id)
|
|
341
389
|
end
|
|
342
390
|
|
|
343
391
|
# @param group_id [String] group id to trigger rebalance for
|
|
344
392
|
# @see ConsumerGroups#trigger_rebalance
|
|
345
393
|
def trigger_rebalance(group_id)
|
|
346
|
-
|
|
394
|
+
consumer_groups_admin.trigger_rebalance(group_id)
|
|
347
395
|
end
|
|
348
396
|
|
|
349
397
|
# @param groups_with_topics [Hash{String => Array<String>}] hash with group
|
|
@@ -351,7 +399,7 @@ module Karafka
|
|
|
351
399
|
# @param active_topics_only [Boolean] if set to false, will select also inactive topics
|
|
352
400
|
# @see ConsumerGroups#read_lags_with_offsets
|
|
353
401
|
def read_lags_with_offsets(groups_with_topics = {}, active_topics_only: true)
|
|
354
|
-
|
|
402
|
+
consumer_groups_admin.read_lags_with_offsets(
|
|
355
403
|
groups_with_topics,
|
|
356
404
|
active_topics_only: active_topics_only
|
|
357
405
|
)
|
|
@@ -362,7 +410,7 @@ module Karafka
|
|
|
362
410
|
# @param brokers [Hash, nil] optional manual broker assignments per partition
|
|
363
411
|
# @see Replication#plan
|
|
364
412
|
def plan_topic_replication(topic:, replication_factor:, brokers: nil)
|
|
365
|
-
Replication.new(kafka: @custom_kafka).plan(
|
|
413
|
+
Replication.new(kafka: @custom_kafka, external_client: @external_client).plan(
|
|
366
414
|
topic: topic,
|
|
367
415
|
to: replication_factor,
|
|
368
416
|
brokers: brokers
|
|
@@ -381,53 +429,101 @@ module Karafka
|
|
|
381
429
|
#
|
|
382
430
|
# @note We always ship and yield a proxied consumer because admin API performance is not
|
|
383
431
|
# that relevant. That is, there are no high frequency calls that would have to be delegated
|
|
432
|
+
#
|
|
433
|
+
# @note When an external client is present, it is yielded wrapped with
|
|
434
|
+
# `Karafka::Connection::Proxy` (which unwraps pre-proxied clients, so no double wrapping
|
|
435
|
+
# occurs) and its lifecycle is not managed here in any way: no oauth binding, no start and
|
|
436
|
+
# no closing. `settings` are
|
|
437
|
+
# ignored as the external instance is already configured and operations run within its
|
|
438
|
+
# identity, including its `group.id`. External rdkafka admin instances are not used here
|
|
439
|
+
# as they are not capable of consumer operations - they are used by `#with_admin` instead.
|
|
384
440
|
def with_consumer(settings = {})
|
|
385
|
-
|
|
441
|
+
return yield(external_client_proxy) if @external_consumer
|
|
386
442
|
|
|
387
|
-
|
|
388
|
-
|
|
443
|
+
bind_id = SecureRandom.uuid
|
|
444
|
+
consumer = nil
|
|
389
445
|
|
|
390
|
-
consumer.start
|
|
391
|
-
proxy = Karafka::Connection::Proxy.new(consumer)
|
|
392
|
-
yield(proxy)
|
|
393
|
-
ensure
|
|
394
|
-
# Always unsubscribe consumer just to be sure, that no metadata requests are running
|
|
395
|
-
# when we close the consumer. This in theory should prevent from some race-conditions
|
|
396
|
-
# that originate from librdkafka
|
|
397
446
|
begin
|
|
398
|
-
consumer
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
447
|
+
consumer = config(:consumer, settings).consumer(native_kafka_auto_start: false)
|
|
448
|
+
bind_oauth(bind_id, consumer)
|
|
449
|
+
|
|
450
|
+
consumer.start
|
|
451
|
+
proxy = Karafka::Connection::Proxy.new(consumer)
|
|
452
|
+
yield(proxy)
|
|
453
|
+
ensure
|
|
454
|
+
# Always unsubscribe consumer just to be sure, that no metadata requests are running
|
|
455
|
+
# when we close the consumer. This in theory should prevent from some race-conditions
|
|
456
|
+
# that originate from librdkafka
|
|
457
|
+
begin
|
|
458
|
+
consumer&.unsubscribe
|
|
459
|
+
# Ignore any errors and continue to close consumer despite them
|
|
460
|
+
rescue Rdkafka::RdkafkaError
|
|
461
|
+
nil
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
consumer&.close
|
|
465
|
+
|
|
466
|
+
unbind_oauth(bind_id)
|
|
402
467
|
end
|
|
403
|
-
|
|
404
|
-
consumer&.close
|
|
405
|
-
|
|
406
|
-
unbind_oauth(bind_id)
|
|
407
468
|
end
|
|
408
469
|
|
|
409
470
|
# Creates admin instance and yields it. After usage it closes the admin instance
|
|
471
|
+
#
|
|
472
|
+
# @note When the external client is an rdkafka admin instance, it is yielded wrapped with
|
|
473
|
+
# `Karafka::Connection::Proxy` (which unwraps pre-proxied clients, so no double wrapping
|
|
474
|
+
# occurs) and its lifecycle is not managed here in any way, same as with `#with_consumer`.
|
|
475
|
+
# External
|
|
476
|
+
# clients of other types (consumers, producers) are not capable of admin operations, thus
|
|
477
|
+
# a dedicated admin instance is created for them as usual.
|
|
410
478
|
def with_admin
|
|
479
|
+
return yield(external_client_proxy) if @external_admin
|
|
480
|
+
|
|
411
481
|
bind_id = SecureRandom.uuid
|
|
482
|
+
admin = nil
|
|
412
483
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
484
|
+
begin
|
|
485
|
+
admin = config(:producer, {}).admin(
|
|
486
|
+
native_kafka_auto_start: false,
|
|
487
|
+
native_kafka_poll_timeout_ms: self.class.poll_timeout
|
|
488
|
+
)
|
|
417
489
|
|
|
418
|
-
|
|
490
|
+
bind_oauth(bind_id, admin)
|
|
419
491
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
492
|
+
admin.start
|
|
493
|
+
proxy = Karafka::Connection::Proxy.new(admin)
|
|
494
|
+
yield(proxy)
|
|
495
|
+
ensure
|
|
496
|
+
admin&.close
|
|
425
497
|
|
|
426
|
-
|
|
498
|
+
unbind_oauth(bind_id)
|
|
499
|
+
end
|
|
427
500
|
end
|
|
428
501
|
|
|
429
502
|
private
|
|
430
503
|
|
|
504
|
+
# @return [Karafka::Connection::Proxy] proxy wrapping the current external client handle.
|
|
505
|
+
# For connection clients the handle is resolved on each use as they swap their underlying
|
|
506
|
+
# rdkafka instance across recovery resets while remaining operational
|
|
507
|
+
def external_client_proxy
|
|
508
|
+
if @external_client.is_a?(Karafka::Connection::Client)
|
|
509
|
+
@external_client.wrapped_kafka
|
|
510
|
+
else
|
|
511
|
+
@external_client
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
# @return [Topics] topics admin operating within this instance context (custom kafka and
|
|
516
|
+
# external client carried over)
|
|
517
|
+
def topics_admin
|
|
518
|
+
Topics.new(kafka: @custom_kafka, external_client: @external_client)
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
# @return [ConsumerGroups] consumer groups admin operating within this instance context
|
|
522
|
+
# (custom kafka and external client carried over)
|
|
523
|
+
def consumer_groups_admin
|
|
524
|
+
ConsumerGroups.new(kafka: @custom_kafka, external_client: @external_client)
|
|
525
|
+
end
|
|
526
|
+
|
|
431
527
|
# @return [Integer] max wait time in ms
|
|
432
528
|
def max_wait_time_ms
|
|
433
529
|
self.class.max_wait_time
|
data/lib/karafka/app.rb
CHANGED
|
@@ -57,7 +57,7 @@ module Karafka
|
|
|
57
57
|
|
|
58
58
|
# Just a nicer name for the consumer groups
|
|
59
59
|
alias_method :routes, :consumer_groups
|
|
60
|
-
# Generalized alias
|
|
60
|
+
# Generalized alias - routing entries are "groups" (consumer groups today, other kinds
|
|
61
61
|
# of groups like KIP-932 share groups in the future).
|
|
62
62
|
alias_method :groups, :consumer_groups
|
|
63
63
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Karafka module namespace
|
|
4
3
|
module Karafka
|
|
5
4
|
# Base consumer from which all Karafka consumers should inherit
|
|
6
5
|
class BaseConsumer
|
|
7
6
|
# Allow for consumer instance tagging for instrumentation
|
|
8
7
|
include Karafka::Core::Taggable
|
|
9
8
|
include Helpers::ConfigImporter.new(
|
|
10
|
-
monitor: %i[monitor]
|
|
9
|
+
monitor: %i[monitor],
|
|
10
|
+
critical_errors: %i[internal processing critical_errors]
|
|
11
11
|
)
|
|
12
12
|
|
|
13
13
|
extend Forwardable
|
|
@@ -104,7 +104,17 @@ module Karafka
|
|
|
104
104
|
# message.
|
|
105
105
|
def on_consume
|
|
106
106
|
handle_consume
|
|
107
|
-
|
|
107
|
+
# Containment is intentionally broader than StandardError: any error escaping this method
|
|
108
|
+
# would bypass `#on_after_consume` in the worker, skipping the retry/pause flow entirely.
|
|
109
|
+
# The next successful batch would then auto-mark its offsets, durably committing past the
|
|
110
|
+
# failed batch - a silent at-least-once violation. Errors like SystemStackError or the
|
|
111
|
+
# ScriptError family (e.g. LoadError surfacing from a Rails autoload hiccup) are per-message
|
|
112
|
+
# failures and go through the regular retry flow like any other processing error.
|
|
113
|
+
# Process-critical errors additionally trigger a graceful shutdown via the auto-subscribed
|
|
114
|
+
# `Instrumentation::CriticalErrorsListener` watching this very instrumentation - the
|
|
115
|
+
# recorded failure plus the retry pause keep this partition protected during the shutdown
|
|
116
|
+
# window and the batch is redelivered after restart.
|
|
117
|
+
rescue Exception => e
|
|
108
118
|
monitor.instrument(
|
|
109
119
|
"error.occurred",
|
|
110
120
|
error: e,
|
|
@@ -124,7 +134,11 @@ module Karafka
|
|
|
124
134
|
# flows do not interact with external systems and their errors are expected to bubble up
|
|
125
135
|
def on_after_consume
|
|
126
136
|
handle_after_consume
|
|
127
|
-
|
|
137
|
+
# Same containment rationale as in `#on_consume`: an error escaping this method would skip
|
|
138
|
+
# the retry below and the next successful batch would auto-mark its offsets, committing
|
|
139
|
+
# past the failed batch. The after-consume flow runs user-extensible code as well (DLQ
|
|
140
|
+
# strategies, dispatch enhancements), so it needs the same class-agnostic protection
|
|
141
|
+
rescue Exception => e
|
|
128
142
|
monitor.instrument(
|
|
129
143
|
"error.occurred",
|
|
130
144
|
error: e,
|
|
@@ -380,7 +394,6 @@ module Karafka
|
|
|
380
394
|
# @note Please note, that if you are seeking to a time offset, getting the offset is blocking
|
|
381
395
|
def seek(offset, manual_seek = true, reset_offset: true)
|
|
382
396
|
coordinator.manual_seek if manual_seek
|
|
383
|
-
self.seek_offset = nil if reset_offset
|
|
384
397
|
|
|
385
398
|
message = Karafka::Messages::Seek.new(
|
|
386
399
|
topic.name,
|
|
@@ -398,6 +411,12 @@ module Karafka
|
|
|
398
411
|
reset_offset: reset_offset
|
|
399
412
|
) do
|
|
400
413
|
client.seek(message)
|
|
414
|
+
|
|
415
|
+
# We reset the seek offset only after the seek actually succeeded. Resetting it before the
|
|
416
|
+
# seek would, on a raising seek (for example an unresolvable time-based offset), leave
|
|
417
|
+
# seek_offset nil so the failure-driven retry would pause without seeking back and skip the
|
|
418
|
+
# rest of the batch.
|
|
419
|
+
self.seek_offset = nil if reset_offset
|
|
401
420
|
end
|
|
402
421
|
end
|
|
403
422
|
|
|
@@ -446,5 +465,14 @@ module Karafka
|
|
|
446
465
|
attempt: attempt
|
|
447
466
|
)
|
|
448
467
|
end
|
|
468
|
+
|
|
469
|
+
# @param error [Exception, nil] error to check or nil when none was recorded
|
|
470
|
+
# @return [Boolean] is the error one of the process-critical ones (configurable via the
|
|
471
|
+
# `internal.processing.critical_errors` setting)
|
|
472
|
+
def critical_error?(error)
|
|
473
|
+
return false unless error
|
|
474
|
+
|
|
475
|
+
critical_errors.any? { |type| error.is_a?(type) }
|
|
476
|
+
end
|
|
449
477
|
end
|
|
450
478
|
end
|
data/lib/karafka/cli/console.rb
CHANGED
data/lib/karafka/cli/help.rb
CHANGED
data/lib/karafka/cli/info.rb
CHANGED
data/lib/karafka/cli/install.rb
CHANGED
data/lib/karafka/cli/server.rb
CHANGED
data/lib/karafka/cli/swarm.rb
CHANGED
data/lib/karafka/cli.rb
CHANGED
|
@@ -50,7 +50,7 @@ end
|
|
|
50
50
|
# so this method is only available when the Karafka console is running
|
|
51
51
|
#
|
|
52
52
|
# We skip this because this should exist and be only valid in the console
|
|
53
|
-
# :
|
|
53
|
+
# simplecov:disable
|
|
54
54
|
if ENV["KARAFKA_CONSOLE"]
|
|
55
55
|
# Reloads Karafka irb console session
|
|
56
56
|
def reload!
|
|
@@ -58,4 +58,4 @@ if ENV["KARAFKA_CONSOLE"]
|
|
|
58
58
|
Kernel.exec Karafka::Cli::Console.command
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
|
-
# :
|
|
61
|
+
# simplecov:enable
|
|
@@ -28,6 +28,12 @@ module Karafka
|
|
|
28
28
|
# @return [String] id of the client
|
|
29
29
|
attr_reader :id
|
|
30
30
|
|
|
31
|
+
# @return [Karafka::Connection::Proxy, nil] proxy wrapping the underlying rdkafka consumer
|
|
32
|
+
# instance or nil when the connection was not yet established. Used by the admin APIs
|
|
33
|
+
# external client support to run admin operations on top of a running consumer
|
|
34
|
+
# connection. Low-level internal API.
|
|
35
|
+
attr_reader :wrapped_kafka
|
|
36
|
+
|
|
31
37
|
# How many times should we retry polling in case of a failure
|
|
32
38
|
MAX_POLL_RETRIES = 20
|
|
33
39
|
|
|
@@ -320,8 +326,8 @@ module Karafka
|
|
|
320
326
|
# won't get into this loop again. This can happen when supervision decides it should close
|
|
321
327
|
# things faster
|
|
322
328
|
#
|
|
323
|
-
#
|
|
324
|
-
#
|
|
329
|
+
# See https://github.com/confluentinc/librdkafka/issues/4792
|
|
330
|
+
# See https://github.com/confluentinc/librdkafka/issues/4527
|
|
325
331
|
if unsubscribe?
|
|
326
332
|
@unsubscribing = true
|
|
327
333
|
|
|
@@ -454,6 +460,26 @@ module Karafka
|
|
|
454
460
|
@wrapped_kafka.query_watermark_offsets(topic, partition)
|
|
455
461
|
end
|
|
456
462
|
|
|
463
|
+
# Resolves offsets of many partitions with one batched request instead of one broker
|
|
464
|
+
# roundtrip per partition.
|
|
465
|
+
#
|
|
466
|
+
# @param topic_partition_offsets [Hash{String => Array<Hash>}] topics with arrays of
|
|
467
|
+
# partition offset specs, each with a `:partition` and an `:offset` (`:earliest`,
|
|
468
|
+
# `:latest`, `:max_timestamp` or an integer timestamp in ms)
|
|
469
|
+
# @return [Array<Hash>] resolved offsets, each with `:topic`, `:partition` and `:offset`
|
|
470
|
+
# @note This consumer own isolation level is forwarded to the query. Be aware that the
|
|
471
|
+
# underlying batched `ListOffsets` resolves `:latest` to the high watermark regardless of
|
|
472
|
+
# the isolation level (unlike the consumer `query_watermark_offsets`, which returns the
|
|
473
|
+
# last stable offset for a read_committed consumer). On a topic with an in-flight
|
|
474
|
+
# transaction `:latest` therefore includes the uncommitted messages a read_committed
|
|
475
|
+
# consumer will not see. Non-transactional topics are unaffected (LSO == HWM).
|
|
476
|
+
def read_partition_offsets(topic_partition_offsets)
|
|
477
|
+
@wrapped_kafka.read_partition_offsets(
|
|
478
|
+
topic_partition_offsets,
|
|
479
|
+
isolation_level: isolation_level
|
|
480
|
+
)
|
|
481
|
+
end
|
|
482
|
+
|
|
457
483
|
# @return [String] safe inspection string that is causing circular dependencies and other
|
|
458
484
|
# issues
|
|
459
485
|
def inspect
|
|
@@ -463,6 +489,17 @@ module Karafka
|
|
|
463
489
|
|
|
464
490
|
private
|
|
465
491
|
|
|
492
|
+
# @return [Integer] isolation level of this consumer mapped to the constant expected by the
|
|
493
|
+
# offsets queries. It cannot change after the client is created, hence memoized.
|
|
494
|
+
# @note When not configured, librdkafka reads committed, so we mirror that default here.
|
|
495
|
+
def isolation_level
|
|
496
|
+
@isolation_level ||=
|
|
497
|
+
case @subscription_group.kafka.fetch(:"isolation.level", "read_committed").to_s
|
|
498
|
+
when "read_uncommitted" then Admin::IsolationLevels::READ_UNCOMMITTED
|
|
499
|
+
else Admin::IsolationLevels::READ_COMMITTED
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
|
|
466
503
|
# When we cannot store an offset, it means we no longer own the partition
|
|
467
504
|
#
|
|
468
505
|
# Non thread-safe offset storing method
|
|
@@ -560,8 +597,8 @@ module Karafka
|
|
|
560
597
|
@kafka = nil
|
|
561
598
|
@wrapped_kafka = nil
|
|
562
599
|
@buffer.clear
|
|
563
|
-
#
|
|
564
|
-
#
|
|
600
|
+
# We do not clear rebalance manager here as we may still have revocation info here that we
|
|
601
|
+
# want to consider valid prior to running another reconnection
|
|
565
602
|
end
|
|
566
603
|
|
|
567
604
|
# Unsubscribes from all the subscriptions
|
|
@@ -665,7 +702,7 @@ module Karafka
|
|
|
665
702
|
case e.code
|
|
666
703
|
when *EARLY_REPORT_ERRORS
|
|
667
704
|
early_report = true
|
|
668
|
-
#
|
|
705
|
+
# See
|
|
669
706
|
# https://github.com/confluentinc/confluent-kafka-dotnet/issues/1366#issuecomment-821842990
|
|
670
707
|
# This will be raised each time poll detects a non-existing topic. When auto creation is
|
|
671
708
|
# on, we can safely ignore it
|
|
@@ -700,8 +737,8 @@ module Karafka
|
|
|
700
737
|
raise unless retryable
|
|
701
738
|
|
|
702
739
|
# Most of the errors can be safely ignored as librdkafka will recover from them
|
|
703
|
-
#
|
|
704
|
-
#
|
|
740
|
+
# See https://github.com/edenhill/librdkafka/issues/1987#issuecomment-422008750
|
|
741
|
+
# See https://github.com/edenhill/librdkafka/wiki/Error-handling
|
|
705
742
|
|
|
706
743
|
time_poll.checkpoint
|
|
707
744
|
time_poll.backoff
|
|
@@ -26,9 +26,9 @@ module Karafka
|
|
|
26
26
|
# @return [Karafka::Routing::SubscriptionGroup] subscription group that this listener handles
|
|
27
27
|
attr_reader :subscription_group
|
|
28
28
|
|
|
29
|
-
# @return [Processing::ConsumerGroups::CoordinatorsBuffer] coordinator buffers that can be
|
|
30
|
-
# advanced cases of changes to the polling flow (like triggered seek back
|
|
31
|
-
# ahead in the topic)
|
|
29
|
+
# @return [Processing::ConsumerGroups::CoordinatorsBuffer] coordinator buffers that can be
|
|
30
|
+
# used directly in advanced cases of changes to the polling flow (like triggered seek back
|
|
31
|
+
# without messages ahead in the topic)
|
|
32
32
|
attr_reader :coordinators
|
|
33
33
|
|
|
34
34
|
# How long to wait in the initial events poll. Increases chances of having the initial events
|
|
@@ -25,6 +25,23 @@ module Karafka
|
|
|
25
25
|
)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
# Resets the attempt count of a given topic partition pause tracker.
|
|
29
|
+
#
|
|
30
|
+
# Used on revocation so that a later reclaim of the same partition starts counting retry
|
|
31
|
+
# attempts from zero instead of carrying the stale count across the rebalance. We reset
|
|
32
|
+
# rather than remove the tracker because the pause itself may still need to be resumed after
|
|
33
|
+
# the reclaim (the partition can be re-paused via the retained paused offsets on rebalance).
|
|
34
|
+
#
|
|
35
|
+
# A coordinator and its pause tracker are created together in
|
|
36
|
+
# `CoordinatorsBuffer#find_or_create`, and `CoordinatorsBuffer#revoke` only calls us once it
|
|
37
|
+
# has confirmed the coordinator exists - so the tracker is always present here.
|
|
38
|
+
#
|
|
39
|
+
# @param topic [::Karafka::Routing::Topic] topic
|
|
40
|
+
# @param partition [Integer] partition number
|
|
41
|
+
def revoke(topic, partition)
|
|
42
|
+
@pauses[topic][partition].reset
|
|
43
|
+
end
|
|
44
|
+
|
|
28
45
|
# Resumes processing of partitions for which pause time has ended.
|
|
29
46
|
#
|
|
30
47
|
# @yieldparam [Karafka::Routing::Topic] topic
|