karafka 2.6.0.rc1 → 2.6.0.rc2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc797708a61eca1cc0309dce91d05ab1dd623f3c7f6abfd74ac7af69c98f5254
4
- data.tar.gz: 9e0e3bace7cc9f5393dfe788035ddc6e89cd64c8afd7ed5a2400d841cce95637
3
+ metadata.gz: d69bd2578f4c712b61a5d1a8eab6448337c0c5e88324fa4e3b87c1593f444b9f
4
+ data.tar.gz: c8652e3bc72ea6e5e7d14b89cbdcc5c33ff42519c10c515dc5a4426bd2770342
5
5
  SHA512:
6
- metadata.gz: 512bed7912b22916225f0428cf1ef949e534765eaca459606155e451566e847c3c0993a83978f230f72ac202e2d6e797415df4086ed00b37bfdbcdb94f5f4e06
7
- data.tar.gz: f0152dec64b5ba30ebae473db2236848b6a3298473be0dec7956330e44e973593311a70e616eb68cc8705fdbcdf55a53eff1d54a230658a0307d7ba6b00cb413
6
+ metadata.gz: d59922e671375a20a74f46b8b8efe74e6f779367977c94e2c7c3ce42fdcb4dfe2ef1cd1d3a46689bf7acd00cfc6498c9f62ea39d78df4b1fc6b2c2dff9dfd073
7
+ data.tar.gz: b484c30e72d838db5d2d4fcc8183d80980cbcbdcd85b3a8214c9165e990577e837ea8824c0e7833a9a6dcf567d6c05df5a7339cc94b0ede1004395f95c701ff7
data/CHANGELOG.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Karafka Framework Changelog
2
2
 
3
3
  ## 2.6.0 (Unreleased)
4
+ - **[Breaking]** Remove the flat global pause configuration accessors (`config.pause_timeout`, `config.pause_max_timeout`, `config.pause_with_exponential_backoff`) deprecated in 2.5.2. Use the nested `config.pause.*` namespace (`config.pause.timeout`, `config.pause.max_timeout`, `config.pause.with_exponential_backoff`) instead.
5
+ - **[Breaking]** Nest the per-topic pause configuration under `topic.pause`. The flat `topic.pause_timeout`, `topic.pause_max_timeout`, and `topic.pause_with_exponential_backoff` readers are removed in favor of `topic.pause.timeout`, `topic.pause.max_timeout`, and `topic.pause.with_exponential_backoff`; `topic.to_h` now emits a nested `pause:` hash instead of the flat keys. The Pro Granular Backoffs override DSL is unchanged (`pause(timeout:, max_timeout:, with_exponential_backoff:)`), and `topic.pausing`/`topic.pausing?` are now `topic.pause`/`topic.pause?`. In OSS `topic.pause` reflects the global `config.pause.*` settings; per-topic overriding remains a Pro feature.
4
6
  - **[Feature]** Add `Karafka::Admin.read_partition_offsets` (and `Admin::Topics#read_partition_offsets`) exposing the `rd_kafka_ListOffsets` admin API to query partition offsets by spec (`:earliest`, `:latest`, `:max_timestamp`, or a timestamp in ms) without a consumer group. Accepts an optional `isolation_level:` keyword (pass `READ_COMMITTED` for the Last Stable Offset instead of the high-watermark, giving accurate lag on transactional topics).
5
7
  - **[Feature]** Add `Karafka::Connection::Client#read_partition_offsets` (and `Connection::Proxy#read_partition_offsets`) exposing the batched `ListOffsets` query on a consumer's own connection, forwarding its `isolation.level`. Note that `:latest` resolves to the high watermark regardless of isolation level, so it includes uncommitted messages on topics with in-flight transactions.
6
8
  - **[Feature]** Allow `Karafka::Admin` (and subsystems like `Admin::ConsumerGroups`, `Admin::Topics`) to operate on an external client via `Karafka::Admin.new(external_client: client)`. Reuses the caller's client (no per-call bootstrap); its lifecycle stays with its owner.
@@ -32,11 +32,11 @@ en:
32
32
  delaying.delay_format: 'needs to be equal or more than 0 and an integer'
33
33
  delaying.active_format: 'needs to be boolean'
34
34
 
35
- pausing.active_format: 'needs to be boolean'
36
- pausing.timeout_format: needs to be an integer bigger than 0
37
- pausing.max_timeout_format: needs to be an integer bigger than 0
38
- pausing.with_exponential_backoff_format: needs to be either true or false
39
- pausing.timeout_max_timeout_vs_pause_max_timeout: timeout must be less or equal to max_timeout
35
+ pause.active_format: 'needs to be boolean'
36
+ pause.timeout_format: needs to be an integer bigger than 0
37
+ pause.max_timeout_format: needs to be an integer bigger than 0
38
+ pause.with_exponential_backoff_format: needs to be either true or false
39
+ pause.timeout_max_timeout_vs_pause_max_timeout: timeout must be less or equal to max_timeout
40
40
 
41
41
  patterns.active_format: 'needs to be boolean'
42
42
  patterns.type_format: 'needs to be :matcher, :discovered or :regular'
@@ -19,9 +19,9 @@ module Karafka
19
19
  # @return [Karafka::TimeTrackers::Pause] pause tracker instance
20
20
  def fetch(topic, partition)
21
21
  @pauses[topic][partition] ||= TimeTrackers::Pause.new(
22
- timeout: topic.pause_timeout,
23
- max_timeout: topic.pause_max_timeout,
24
- exponential_backoff: topic.pause_with_exponential_backoff
22
+ timeout: topic.pause.timeout,
23
+ max_timeout: topic.pause.max_timeout,
24
+ exponential_backoff: topic.pause.with_exponential_backoff
25
25
  )
26
26
  end
27
27
 
@@ -117,8 +117,7 @@ module Karafka
117
117
  # Since the execution of particular tasks is isolated and guarded, it should not
118
118
  # leak. This means, that this is to handle errors like schedule version
119
119
  # incompatibility and other errors that will not go away without a redeployment
120
- pause_timeout(60 * 1_000)
121
- pause_max_timeout(60 * 1_000)
120
+ pause(timeout: 60 * 1_000, max_timeout: 60 * 1_000)
122
121
 
123
122
  # This is the core of execution. Since we're producers of states, we need a way
124
123
  # to tick without having new data
@@ -33,17 +33,13 @@ module Karafka
33
33
  module Routing
34
34
  module Features
35
35
  class Pausing < Base
36
- # Config for pausing feature
37
- Config = Struct.new(
38
- :active,
39
- :timeout,
40
- :max_timeout,
41
- :with_exponential_backoff,
42
- keyword_init: true
43
- ) do
44
- alias_method :active?, :active
45
- alias_method :with_exponential_backoff?, :with_exponential_backoff
46
- end
36
+ # Config for pausing feature.
37
+ #
38
+ # By convention each routing feature exposes a `Config`. The pause value object is defined
39
+ # in OSS (`Karafka::Routing::Features::Pausing::Config`) because the per-topic `#pause`
40
+ # reader defaults to the global config there, so the feature points its `Config` at that
41
+ # shared class rather than redefining it.
42
+ Config = Karafka::Routing::Features::Pausing::Config
47
43
  end
48
44
  end
49
45
  end
@@ -42,10 +42,8 @@ module Karafka
42
42
  File.join(Karafka.gem_root, "config", "locales", "pro_errors.yml")
43
43
  ).fetch("en").fetch("validations").fetch("routing").fetch("topic")
44
44
 
45
- # Validate the nested pausing configuration
46
- # Both old setters and new pause() method update the pausing config,
47
- # so we only need to validate this one format
48
- nested :pausing do
45
+ # Validate the nested pause configuration
46
+ nested :pause do
49
47
  required(:active) { |val| [true, false].include?(val) }
50
48
  required(:timeout) { |val| val.is_a?(Integer) && val.positive? }
51
49
  required(:max_timeout) { |val| val.is_a?(Integer) && val.positive? }
@@ -56,13 +54,13 @@ module Karafka
56
54
  virtual do |data, errors|
57
55
  next unless errors.empty?
58
56
 
59
- pausing = data.fetch(:pausing)
60
- timeout = pausing.fetch(:timeout)
61
- max_timeout = pausing.fetch(:max_timeout)
57
+ pause = data.fetch(:pause)
58
+ timeout = pause.fetch(:timeout)
59
+ max_timeout = pause.fetch(:max_timeout)
62
60
 
63
61
  next if timeout <= max_timeout
64
62
 
65
- [[%i[pausing timeout], :max_timeout_vs_pause_max_timeout]]
63
+ [[%i[pause timeout], :max_timeout_vs_pause_max_timeout]]
66
64
  end
67
65
  end
68
66
  end
@@ -35,84 +35,39 @@ module Karafka
35
35
  class Pausing < Base
36
36
  # Expansion allowing for a per topic pause strategy definitions
37
37
  module Topic
38
- # This method sets up the extra instance variable to nil before calling
39
- # the parent class initializer. The explicit initialization
40
- # to nil is included as an optimization for Ruby's object shapes system,
41
- # which improves memory layout and access performance.
42
- def initialize(...)
43
- @pausing = nil
44
- super
45
- end
46
-
47
- # Allows for per-topic pausing strategy setting
38
+ # Allows for per-topic pausing strategy setting.
39
+ #
40
+ # Overrides the OSS `#pause` reader (this module is prepended onto `Routing::Topic`).
41
+ # With no arguments it returns the current configuration, defaulting to the global
42
+ # `config.pause.*` settings via `super`. With arguments it overrides the pausing
43
+ # strategy for this topic and marks it as active.
48
44
  #
49
45
  # @param timeout [Integer] how long should we wait upon processing error (milliseconds)
50
46
  # @param max_timeout [Integer] what is the max timeout in case of an exponential
51
47
  # backoff (milliseconds)
52
48
  # @param with_exponential_backoff [Boolean] should we use exponential backoff
53
- # @return [Config] pausing config object
49
+ # @return [Karafka::Routing::Features::Pausing::Config] pausing config object
54
50
  def pause(timeout: nil, max_timeout: nil, with_exponential_backoff: nil)
55
- # If no arguments provided, just return or initialize the config
56
- return pausing if timeout.nil? && max_timeout.nil? && with_exponential_backoff.nil?
51
+ config = super()
57
52
 
58
- # Update instance variables for backwards compatibility
59
- # This ensures code reading @pause_timeout directly or via the inherited getter
60
- # will get the correct values
61
- @pause_timeout = timeout if timeout
62
- @pause_max_timeout = max_timeout if max_timeout
63
-
64
- unless with_exponential_backoff.nil?
65
- @pause_with_exponential_backoff = with_exponential_backoff
66
- end
53
+ # If no arguments provided, just return the current (default or overridden) config
54
+ return config if timeout.nil? && max_timeout.nil? && with_exponential_backoff.nil?
67
55
 
68
- # Create or update the config
69
- @pausing ||= Config.new(
70
- active: false,
71
- timeout: @pause_timeout || Karafka::App.config.pause.timeout,
72
- max_timeout: @pause_max_timeout || Karafka::App.config.pause.max_timeout,
73
- with_exponential_backoff: if @pause_with_exponential_backoff.nil?
74
- Karafka::App.config.pause.with_exponential_backoff
75
- else
76
- @pause_with_exponential_backoff
77
- end
78
- )
79
-
80
- @pausing.timeout = timeout if timeout
81
- @pausing.max_timeout = max_timeout if max_timeout
56
+ config.timeout = timeout if timeout
57
+ config.max_timeout = max_timeout if max_timeout
82
58
 
83
59
  unless with_exponential_backoff.nil?
84
- @pausing.with_exponential_backoff = with_exponential_backoff
60
+ config.with_exponential_backoff = with_exponential_backoff
85
61
  end
86
62
 
87
- @pausing.active = true
88
-
89
- @pausing
90
- end
91
-
92
- # @return [Config] pausing configuration object
93
- def pausing
94
- @pausing ||= Config.new(
95
- active: false,
96
- timeout: @pause_timeout || Karafka::App.config.pause.timeout,
97
- max_timeout: @pause_max_timeout || Karafka::App.config.pause.max_timeout,
98
- with_exponential_backoff: if @pause_with_exponential_backoff.nil?
99
- Karafka::App.config.pause.with_exponential_backoff
100
- else
101
- @pause_with_exponential_backoff
102
- end
103
- )
104
- end
63
+ config.active = true
105
64
 
106
- # @return [Boolean] is pausing explicitly configured
107
- def pausing?
108
- pausing.active?
65
+ config
109
66
  end
110
67
 
111
- # @return [Hash] topic with all its native configuration options plus pausing settings
112
- def to_h
113
- super.merge(
114
- pausing: pausing.to_h
115
- ).freeze
68
+ # @return [Boolean] is pausing explicitly configured on a per-topic basis
69
+ def pause?
70
+ pause.active?
116
71
  end
117
72
  end
118
73
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Routing
5
+ module Features
6
+ module Pausing
7
+ # Per-topic pause (backoff) configuration value object.
8
+ #
9
+ # Defaults to the global `config.pause.*` settings unless overridden on a per-topic basis.
10
+ #
11
+ # Unlike most feature configs, `active` here does not switch the behavior on or off - the
12
+ # pause/backoff always applies. It only marks whether these settings were explicitly set
13
+ # for this topic (`true`) or inherited from the global defaults (`false`).
14
+ Config = Struct.new(
15
+ :active,
16
+ :timeout,
17
+ :max_timeout,
18
+ :with_exponential_backoff,
19
+ keyword_init: true
20
+ ) do
21
+ alias_method :active?, :active
22
+ alias_method :with_exponential_backoff?, :with_exponential_backoff
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Routing
5
+ module Features
6
+ # Namespace holding the pause (backoff) routing configuration. There is no OSS pausing
7
+ # feature to activate here - the backoff behavior is part of the topic itself and its
8
+ # settings default to the global `config.pause.*`.
9
+ module Pausing
10
+ end
11
+ end
12
+ end
13
+ end
@@ -32,9 +32,6 @@ module Karafka
32
32
  max_wait_time
33
33
  initial_offset
34
34
  consumer_persistence
35
- pause_timeout
36
- pause_max_timeout
37
- pause_with_exponential_backoff
38
35
  ].freeze
39
36
 
40
37
  private_constant :INHERITABLE_ATTRIBUTES
@@ -58,6 +55,10 @@ module Karafka
58
55
  INHERITABLE_ATTRIBUTES.each do |attribute|
59
56
  instance_variable_set("@#{attribute}", nil)
60
57
  end
58
+
59
+ # Explicit nil initialization for Ruby's object shapes optimization. The per-topic pause
60
+ # config is built lazily on first read, defaulting to the global `config.pause.*` settings.
61
+ @pause = nil
61
62
  end
62
63
 
63
64
  INHERITABLE_ATTRIBUTES.each do |attribute|
@@ -73,6 +74,17 @@ module Karafka
73
74
  RUBY
74
75
  end
75
76
 
77
+ # @return [Karafka::Routing::Features::Pausing::Config] per-topic pause configuration,
78
+ # reflecting the root `config.pause.*` settings.
79
+ def pause
80
+ @pause ||= Features::Pausing::Config.new(
81
+ active: false,
82
+ timeout: Karafka::App.config.pause.timeout,
83
+ max_timeout: Karafka::App.config.pause.max_timeout,
84
+ with_exponential_backoff: Karafka::App.config.pause.with_exponential_backoff
85
+ )
86
+ end
87
+
76
88
  # Often users want to have the same basic cluster setup with small setting alterations
77
89
  # This method allows us to do so by setting `inherit` to `true`. Whe inherit is enabled,
78
90
  # settings will be merged with defaults.
@@ -155,6 +167,7 @@ module Karafka
155
167
  name: name,
156
168
  active: active?,
157
169
  consumer: consumer,
170
+ pause: pause.to_h,
158
171
  group_id: group.id,
159
172
  # Kept as a reference alongside `group_id` for backwards compatibility. Will be removed
160
173
  # in Karafka 3.0.
@@ -405,53 +405,6 @@ module Karafka
405
405
  # Thanks to that we have an initial state out of the box.
406
406
  configure
407
407
 
408
- # Backwards compatibility: Add old flat API methods to the config instance. These delegate
409
- # to the new nested pause config. Deprecated: Will be removed in Karafka 2.6
410
- #
411
- # Prior to the introduction of nested pause configuration, pause-related settings were
412
- # accessed directly on the config object (e.g., `config.pause_timeout`). With the nested
413
- # structure introduced, these settings moved to `config.pause.timeout`, etc.
414
- #
415
- # This instance_eval block adds delegation methods to maintain backwards compatibility,
416
- # allowing existing code using the old flat API to continue working without modification.
417
- config.instance_eval do
418
- # @return [Integer] delegated timeout value from pause.timeout
419
- # @deprecated Use config.pause.timeout instead
420
- def pause_timeout
421
- pause.timeout
422
- end
423
-
424
- # @param value [Integer] timeout value to set
425
- # @deprecated Use config.pause.timeout= instead
426
- def pause_timeout=(value)
427
- pause.timeout = value
428
- end
429
-
430
- # @return [Integer] delegated max_timeout value from pause.max_timeout
431
- # @deprecated Use config.pause.max_timeout instead
432
- def pause_max_timeout
433
- pause.max_timeout
434
- end
435
-
436
- # @param value [Integer] max timeout value to set
437
- # @deprecated Use config.pause.max_timeout= instead
438
- def pause_max_timeout=(value)
439
- pause.max_timeout = value
440
- end
441
-
442
- # @return [Boolean] delegated exponential backoff flag from pause.with_exponential_backoff
443
- # @deprecated Use config.pause.with_exponential_backoff instead
444
- def pause_with_exponential_backoff
445
- pause.with_exponential_backoff
446
- end
447
-
448
- # @param value [Boolean] exponential backoff flag to set
449
- # @deprecated Use config.pause.with_exponential_backoff= instead
450
- def pause_with_exponential_backoff=(value)
451
- pause.with_exponential_backoff = value
452
- end
453
- end
454
-
455
408
  class << self
456
409
  # Configuring method
457
410
  def setup(&)
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Karafka
4
4
  # Current Karafka version
5
- VERSION = "2.6.0.rc1"
5
+ VERSION = "2.6.0.rc2"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: karafka
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0.rc1
4
+ version: 2.6.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -547,6 +547,8 @@ files:
547
547
  - lib/karafka/routing/features/deserializers/config.rb
548
548
  - lib/karafka/routing/features/deserializers/contracts/topic.rb
549
549
  - lib/karafka/routing/features/deserializers/topic.rb
550
+ - lib/karafka/routing/features/pausing.rb
551
+ - lib/karafka/routing/features/pausing/config.rb
550
552
  - lib/karafka/routing/proxy.rb
551
553
  - lib/karafka/routing/router.rb
552
554
  - lib/karafka/routing/subscription_group.rb