karafka-core 2.6.2 → 2.6.3

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: b5f044e02de2bc5b5e41fb033c9e4f0a4e66f45890615053d3c1fe1c33ec8058
4
- data.tar.gz: 5ad2604a98478db69950c2a94064dcd20d6ceafa6d3eab03d907700b6cadf3eb
3
+ metadata.gz: 70aa3940193aebd6b4f232950a2b765ee57025aea6b3d3d7c72234429f904de4
4
+ data.tar.gz: e4a550006b517eea864370ef12534dacdb6fddae40f3adf7308981fa99a1e7a1
5
5
  SHA512:
6
- metadata.gz: 0cd334edd644f023a15d87bd35cfe535ca0edcddb39f37630c283801bed26821f3cfa6bfcb478bdd987fae0a549bbdbda56cb4258430f8f676636c368afcddcc
7
- data.tar.gz: 44a3eba562af3a0315391f362b28684c54f543110f6f76dd6e99e576655c749866a737f1235cf1971992c0274ed3a1da21db3cf83b07cc83ec28e76ef8d17424
6
+ metadata.gz: '05908e99fd999ee007bcb3efd46a6a3b949d88e40d980c5ca4e8aa90a3c312755717dc8feef7a7de42c5c7c235e3ac623e26b91e9a3456568e4d552a2d8782ea'
7
+ data.tar.gz: 61456523b5822db6c78ad36c839ed6e3bdcbd9bc18d56cebfb95947443296aad94b917b3bef7798f093b471d703ae9d5a7f43d1b09d726ea655e0b2a0b091a3c
@@ -29,7 +29,7 @@ jobs:
29
29
  - ruby: '4.0'
30
30
  coverage: 'true'
31
31
  steps:
32
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
32
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
33
33
  with:
34
34
  fetch-depth: 0
35
35
 
@@ -37,7 +37,7 @@ jobs:
37
37
  run: "[ -e $APT_DEPS ] || sudo apt-get install -y --no-install-recommends $APT_DEPS"
38
38
 
39
39
  - name: Set up Ruby
40
- uses: ruby/setup-ruby@9eb537ca036ebaed86729dcb9309076e4c5c3b74 # v1.314.0
40
+ uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
41
41
  with:
42
42
  ruby-version: ${{matrix.ruby}}
43
43
  bundler: 'latest'
@@ -65,13 +65,13 @@ jobs:
65
65
  env:
66
66
  BUNDLE_GEMFILE: Gemfile.lint
67
67
  steps:
68
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
68
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
69
69
  with:
70
70
  fetch-depth: 0
71
71
  - name: Set up Ruby
72
- uses: ruby/setup-ruby@9eb537ca036ebaed86729dcb9309076e4c5c3b74 # v1.314.0
72
+ uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
73
73
  with:
74
- ruby-version: '4.0.5'
74
+ ruby-version: '4.0.6'
75
75
  bundler-cache: true
76
76
  - name: Run rubocop
77
77
  run: bundle exec rubocop
@@ -82,13 +82,13 @@ jobs:
82
82
  env:
83
83
  BUNDLE_GEMFILE: Gemfile.lint
84
84
  steps:
85
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
85
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
86
86
  with:
87
87
  fetch-depth: 0
88
88
  - name: Set up Ruby
89
- uses: ruby/setup-ruby@9eb537ca036ebaed86729dcb9309076e4c5c3b74 # v1.314.0
89
+ uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
90
90
  with:
91
- ruby-version: '4.0.5'
91
+ ruby-version: '4.0.6'
92
92
  bundler-cache: true
93
93
  - name: Run yard-lint
94
94
  run: bundle exec yard-lint lib/
@@ -97,11 +97,11 @@ jobs:
97
97
  timeout-minutes: 5
98
98
  runs-on: ubuntu-latest
99
99
  steps:
100
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
100
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
101
101
  with:
102
102
  fetch-depth: 0
103
103
  - name: Set up Node.js
104
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
104
+ uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
105
105
  with:
106
106
  node-version: '20'
107
107
  cache: 'npm'
@@ -19,12 +19,12 @@ jobs:
19
19
  id-token: write
20
20
 
21
21
  steps:
22
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
22
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
23
23
  with:
24
24
  fetch-depth: 0
25
25
 
26
26
  - name: Set up Ruby
27
- uses: ruby/setup-ruby@9eb537ca036ebaed86729dcb9309076e4c5c3b74 # v1.314.0
27
+ uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
28
28
  with:
29
29
  bundler-cache: false
30
30
 
@@ -32,4 +32,4 @@ jobs:
32
32
  run: |
33
33
  bundle install --jobs 4 --retry 3
34
34
 
35
- - uses: rubygems/release-gem@052cc82692552de3ef2b81fd670e41d13cba8092 # v1.4.0
35
+ - uses: rubygems/release-gem@7f9650160c1a4e7989fdc9855807bdbd421d8b6b # v1.4.1
@@ -7,7 +7,7 @@ jobs:
7
7
  verify_action_pins:
8
8
  runs-on: ubuntu-latest
9
9
  steps:
10
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
10
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
11
11
  - name: Check SHA pins
12
12
  run: |
13
13
  if grep -E -r "uses: .*/.*@(v[0-9]+|main|master)($|[[:space:]]|$)" --include="*.yml" --include="*.yaml" .github/workflows/ | grep -v "#"; then
data/.gitignore CHANGED
@@ -19,6 +19,7 @@ db/*.sqlite3
19
19
  *.rbc
20
20
  *.sassc
21
21
  .byebug_history
22
+ .claude/
22
23
  .redcar/
23
24
  .capistrano/
24
25
  .sass-cache
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 4.0.5
1
+ 4.0.6
data/.yard-lint.yml CHANGED
@@ -62,6 +62,34 @@ Documentation/BlankLineBeforeDefinition:
62
62
  SingleBlankLine: true
63
63
  OrphanedDocs: true
64
64
 
65
+ Documentation/DuplicateNamespaceComment:
66
+ Description: Detects namespaces documented with a YARD comment in more than one file.
67
+ Enabled: true
68
+ Severity: error
69
+
70
+ Documentation/UnderfilledLines:
71
+ Description: Detects documentation prose that wraps too early and wastes horizontal space.
72
+ Enabled: true
73
+ Severity: error
74
+ # Aligned with RuboCop's Layout/LineLength (Max: 100) so documentation prose
75
+ # wraps to the same width as code.
76
+ MaxLength: 100
77
+
78
+ Documentation/LineLength:
79
+ Description: Detects documentation lines that exceed the maximum length.
80
+ Enabled: true
81
+ Severity: error
82
+ # Aligned with RuboCop's Layout/LineLength (Max: 100).
83
+ MaxLength: 100
84
+
85
+ Documentation/TextSubstitution:
86
+ Description: Detects em/en-dashes in documentation and replaces them with hyphens.
87
+ Enabled: true
88
+ Severity: error
89
+ Substitutions:
90
+ "—": "-" # em-dash (U+2014)
91
+ "–": "-" # en-dash (U+2013)
92
+
65
93
  # Tags validators
66
94
  Tags/Order:
67
95
  Description: Enforces consistent ordering of YARD tags.
@@ -142,7 +170,7 @@ Tags/OptionTags:
142
170
  Tags/ExampleSyntax:
143
171
  Description: Validates Ruby syntax in @example tags.
144
172
  Enabled: true
145
- Severity: warning
173
+ Severity: error
146
174
 
147
175
  Tags/RedundantParamDescription:
148
176
  Description: Detects meaningless parameter descriptions that add no value.
data/CHANGELOG.md CHANGED
@@ -1,31 +1,34 @@
1
1
  # Karafka Core Changelog
2
2
 
3
+ ## 2.6.3 (2026-08-31)
4
+ - [Enhancement] Add `Configurable::Injector`, a reusable base for injecting default values into a config hash without overwriting user-provided settings, with support for layering extra defaults on top.
5
+
3
6
  ## 2.6.2 (2026-06-29)
4
- - [Enhancement] Document that a leaf's `default` value is intentionally shared by reference across the class template and every config instance produced by `Configurable::Node#deep_dup`. This uniform rule (the leaf is shallow-copied) is what lets a shared service object passed as a default (e.g. a logger) keep its identity across all configs; the flip side is that an in-place mutation of a mutable container default (`config.list << :x`) is visible on every instance. Callers that need a per-instance mutable default should assign it inside a `configure` block or dup it themselves rather than relying on a mutable `default:` (e.g. `default: []`). Adds characterization tests covering the shared-default behavior.
7
+ - [Enhancement] Document that a leaf's `default` value is shared by reference across all config instances, so a mutable default (e.g. `default: []`) mutated in place is visible everywhere. Assign it inside a `configure` block if you need a per-instance copy.
5
8
  - [Fix] `require "pathname"` explicitly in `lib/karafka-core.rb` (with the other top-level requires). `Karafka::Core.gem_root` returns a `Pathname`, but the gem never required `pathname` -- it only worked because Bundler (or another gem) happened to load it first. In an environment where nothing else loads it, `gem_root` raised `NameError: uninitialized constant Pathname`.
6
- - [Enhancement] Document the `virtual` rule result contract: a rule must return a freshly built `Array` of `[path, message]` error pairs on every call. `Contract#call` takes ownership of that array and prepends the current scope onto each pair in place (avoiding a per-error allocation), so returning a memoized, shared or frozen array is unsupported -- the in-place scoping would accumulate the scope prefix across validations or raise `FrozenError`. Adds characterization tests for the supported and unsupported patterns.
9
+ - [Enhancement] Document that a `virtual` rule must return a freshly built `Array` of `[path, message]` error pairs on each call; a memoized, shared or frozen array is unsupported.
7
10
  - [Fix] `Configurable::Node#register` raises the documented "already registered" `ArgumentError` for a name already used by an unread lazy-with-constructor setting. The duplicate guard only checked `@configs_refs`, but a lazy setting with a constructor is absent from it until first read, so `register` silently overwrote it; it now checks the defined children.
8
11
  - [Fix] `Contractable::Contract.nested` now pops its path in an `ensure`. If the block raised while the contract was being defined and the caller rescued it, the path stayed on the nesting stack and was prefixed onto every rule defined afterwards.
9
12
  - [Fix] `Contract#call` no longer raises `NoMethodError` when validating a non-Hash root with a 1-key or 2-key rule path; it reports the path as missing, consistent with the 3+-key path (and the non-Hash intermediate handling added in 2.6.1).
10
13
  - [Fix] Honor `excluded_keys` containing `"cgrp"` in `StatisticsDecorator` `only_keys` mode. The `cgrp` branch of the structure-aware fast path lacked the exclusion guard that the `brokers` and `topics` branches have, so excluding the consumer-group subtree still decorated it (inconsistent with the full-decoration path).
11
14
  - [Fix] Guard the patched rdkafka error callback against a null client pointer. librdkafka can invoke the error callback with a NULL `rd_kafka_t` (e.g. very early in client construction); calling `rd_kafka_name` on it dereferenced the null pointer and could segfault the process. Mirrors the upstream `ErrorCallback`.
12
15
  - [Fix] Resolve fatal errors in the patched rdkafka error callback. `ERR__FATAL` is only a generic marker, so the callback now fetches the real underlying error code and description via `RdkafkaError.build_fatal` (`rd_kafka_fatal_error`) instead of reporting the generic fatal code. Mirrors the upstream `ErrorCallback`.
13
- - [Fix] A lazy setting declared without a constructor (`setting(:x, lazy: true)`) no longer raises when its accessor is read. `lazy: true` only makes sense together with a constructor to (re)evaluate; without one there is nothing to evaluate, so such a setting now behaves like a regular setting backed by its default. Previously reading it raised `NoMethodError` — `nil.arity` through the dynamic accessor for a falsy default, or a missing accessor for a truthy default.
16
+ - [Fix] A lazy setting declared without a constructor (`setting(:x, lazy: true)`) no longer raises when read; it now behaves like a regular setting backed by its default.
14
17
  - [Fix] `Contract#call` no longer raises `NoMethodError` when a virtual rule returns `false`. A virtual rule now signals "no errors" with any non-Array result (`true`/`false`/`nil`); only an `Array` of error pairs is collected. Previously a `false` return reached `false.each` (a `nil` return was already tolerated).
15
- - [Fix] Manage `CallbacksManager` callbacks copy-on-write: `add`/`delete` rebuild and atomically swap an immutable values snapshot under a mutex, and `#call` iterates that snapshot directly. The previous values cache (introduced in 2.5.11) was lazily invalidated from within `#call`, which could not be done atomically against a concurrent `add`/`delete`, so a callback racing with dispatch could be silently lost — a removed one kept firing forever, or a newly added one never fired. The copy-on-write read takes no lock and allocates nothing per call, so the race is fixed without reintroducing a per-call `#values` allocation. librdkafka statistics/error callbacks fire from a background thread while callbacks are registered/unregistered, so this was reachable in practice.
16
- - [Fix] Manage `Notifications` subscriptions copy-on-write (`#subscribe`, `#unsubscribe` and `#clear` replace the per-event listener array instead of mutating it in place) so a listener that unsubscribes itself (or another) from within its own handler no longer causes the listener following it to be silently skipped, and concurrent subscribe/unsubscribe during dispatch is safe. Dispatch keeps iterating the live array directly, so there is no per-notification allocation on the hot path.
17
- - [Fix] Report a freeze duration (`_fd`) of `0` for statistics keys that are newly introduced in an emission (e.g. a broker or partition that appears mid-stream) instead of the elapsed time since the previous emission. A key that did not exist in the prior emission could not have been "frozen" for any duration, so accumulating the inter-emission gap was incorrect and also made the related `StatisticsDecorator` spec flaky on slow CIs (`_fd` depended on the wall-clock gap between the two emissions).
18
+ - [Fix] Make `CallbacksManager` thread-safe under concurrent `add`/`delete` during dispatch. A callback registered or removed while callbacks were firing could be lost — kept firing after removal, or never fired after being added. librdkafka fires these from a background thread, so it was reachable in practice.
19
+ - [Fix] Make `Notifications` subscriptions thread-safe: a listener that unsubscribes itself (or another) from within its own handler no longer causes the next listener to be skipped, and concurrent subscribe/unsubscribe during dispatch is now safe.
20
+ - [Fix] Report a freeze duration (`_fd`) of `0` for statistics keys that first appear mid-stream (e.g. a new broker or partition) instead of the time since the previous emission, which was incorrect and made the related spec flaky.
18
21
  - [Fix] Make assigning a setting on a frozen `Configurable::Node` atomic. The ivar-backed writer evaluated `@configs_refs[name] = value` before `instance_variable_set`, so a frozen node mutated the canonical store and only then raised `FrozenError`, leaving the store and the ivar-backed reader permanently out of sync. It now raises before touching any state.
19
- - [Fix] `Configurable::Node#to_h` now evaluates a setting's constructor with its default (arity-aware, matching `#compile`) instead of calling it with no arguments. The documented `->(default) { ... }` constructor form previously raised `ArgumentError: wrong number of arguments` from `#to_h` whenever the value was not yet in the config store (e.g. `#to_h` on an unconfigured instance, or an unread lazy setting).
22
+ - [Fix] `Configurable::Node#to_h` no longer raises for a setting using the `->(default) { ... }` constructor form when its value has not been set yet (e.g. `#to_h` on an unconfigured instance or an unread lazy setting).
20
23
  - [Fix] Honor `excluded_keys` inside `StatisticsDecorator` `only_keys` decoration. A key listed in both `only_keys` and `excluded_keys` was still decorated because the direct-access decoration loop never consulted `excluded_keys`; exclusion now wins, matching the full-decoration path.
21
24
  - [Fix] Strip the tests/specs root directory as an anchored prefix (`sub(/\A.../)`) instead of a global `gsub` in `MinitestLocator` and `RSpecLocator`. When the root directory string recurred later in a test/spec file path, the global replace removed every occurrence and corrupted the derived subject class path; only the leading prefix is now removed.
22
25
 
23
26
  ## 2.6.1 (2026-06-15)
24
- - [Enhancement] Speed up `Contract#call` by ~1.25x for minimal and ~1.4x for fully populated data: resolve rule paths with a single `Hash#fetch` per level instead of `key?` + `[]`, inline the per-rule type dispatch into the rules loop, and compare the dig sentinel via `#equal?` so `#==` is never dispatched to the validated (user-provided) values. This is the per-message validation path in WaterDrop producers.
27
+ - [Enhancement] Speed up `Contract#call` by ~1.25–1.4x, the per-message validation path in WaterDrop producers.
25
28
  - [Fix] `Contract#call` with rule paths of 3+ keys no longer raises `NoMethodError` when an intermediate value is not a `Hash` and reports the path as missing instead, consistent with the 2-key path behavior.
26
29
  - [Change] Reject reserved setting names with an `ArgumentError` in `Configurable::Node#setting` and `#register`: internal state names (`node_name`, `children`, `nestings`, `compiled`, `configs_refs`, `local_defs`) and the node public API names (`setting`, `configure`, `to_h`, `deep_dup`, `register`, `compile`). Previously such names silently shadowed the node own accessors, breaking `deep_dup` or `to_h`, and assignments like `config.children = value` corrupted the node internal state.
27
- - [Enhancement] Skip the event name mapping hash lookup in `Monitor#instrument` when no namespace is used and the event id is already a `String`, which is the case for all events in the Karafka ecosystem (~1.2x faster dispatch on the common no-subscribers path). Symbol event ids and namespaced monitors keep going through the mapping.
28
- - [Enhancement] Mirror config values into instance variables and use `attr_reader` based readers in `Configurable::Node`, yielding ~1.4x faster flat and ~1.6x faster nested settings reads on hot paths. `@configs_refs` remains the canonical store; non-identifier setting names (e.g. registered names with dashes) keep the previous hash-based accessors.
30
+ - [Enhancement] Speed up `Monitor#instrument` dispatch (~1.2x) on the common no-subscribers path.
31
+ - [Enhancement] Speed up `Configurable::Node` settings reads (~1.4x flat, ~1.6x nested) on hot paths.
29
32
  - [Enhancement] Instantiate each `Configurable::Node` through a per-layout anonymous subclass so the ivar-backed settings do not grow object shape variations on the shared `Node` class (which would degrade ivar access and trigger Ruby performance warnings). `deep_dup` reuses the template's subclass, so duplicated configs share object shapes.
30
33
  - [Fix] Symbolize setting names at definition time (`setting`, same as `register`) and on config store writes so `String` setting names work end to end (accessors, `#to_h`, recompilation state) and cannot corrupt node internal state when matching reserved internal names (previously string-named settings were quietly broken as accessors and the store disagreed on the key type).
31
34
  - [Change] Config nodes are now instances of anonymous `Node` subclasses: `is_a?(Karafka::Core::Configurable::Node)` still holds, but `instance_of?(Node)` is now `false` and `node.class.name` is `nil`.
data/Gemfile.lint.lock CHANGED
@@ -55,11 +55,11 @@ GEM
55
55
  unicode-display_width (3.2.0)
56
56
  unicode-emoji (~> 4.1)
57
57
  unicode-emoji (4.2.0)
58
- yard (0.9.38)
59
- yard-lint (1.4.0)
58
+ yard (0.9.45)
59
+ yard-lint (1.10.1)
60
60
  yard (~> 0.9)
61
61
  zeitwerk (~> 2.6)
62
- zeitwerk (2.7.4)
62
+ zeitwerk (2.8.2)
63
63
 
64
64
  PLATFORMS
65
65
  ruby
@@ -75,6 +75,7 @@ DEPENDENCIES
75
75
 
76
76
  CHECKSUMS
77
77
  ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
78
+ bundler (4.0.17) sha256=214e21431b5665dd2f99df8a5511c6b151d7a72e8015c8b38f8b775b61cbb6c1
78
79
  json (2.18.0) sha256=b10506aee4183f5cf49e0efc48073d7b75843ce3782c68dbeb763351c08fd505
79
80
  language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
80
81
  lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
@@ -95,9 +96,9 @@ CHECKSUMS
95
96
  standard-performance (1.9.0) sha256=49483d31be448292951d80e5e67cdcb576c2502103c7b40aec6f1b6e9c88e3f2
96
97
  unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
97
98
  unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
98
- yard (0.9.38) sha256=721fb82afb10532aa49860655f6cc2eaa7130889df291b052e1e6b268283010f
99
- yard-lint (1.4.0) sha256=7dd88fbb08fd77cb840bea899d58812817b36d92291b5693dd0eeb3af9f91f0f
100
- zeitwerk (2.7.4) sha256=2bef90f356bdafe9a6c2bd32bcd804f83a4f9b8bc27f3600fff051eb3edcec8b
99
+ yard (0.9.45) sha256=52e211493f7cb8a3ebf7e104a25a1e73937a3103092545d34cb88fafebb3dc51
100
+ yard-lint (1.10.1) sha256=172ea1905304580bd515c093d82831ec4889e725100c49d5bf77e62101f49129
101
+ zeitwerk (2.8.2) sha256=7212a61311083c604184b1ea2574b9aa05cd14f855a0841c06985cabe9181d12
101
102
 
102
103
  BUNDLED WITH
103
- 4.0.3
104
+ 4.0.17
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- karafka-core (2.6.2)
4
+ karafka-core (2.6.3)
5
5
  karafka-rdkafka (>= 0.20.0)
6
6
  logger (>= 1.6.0)
7
7
 
@@ -10,7 +10,6 @@ GEM
10
10
  specs:
11
11
  byebug (13.0.0)
12
12
  reline (>= 0.6.0)
13
- docile (1.4.1)
14
13
  drb (2.2.3)
15
14
  ffi (1.17.4)
16
15
  ffi (1.17.4-aarch64-linux-gnu)
@@ -24,38 +23,38 @@ GEM
24
23
  ffi (1.17.4-x86_64-linux-gnu)
25
24
  ffi (1.17.4-x86_64-linux-musl)
26
25
  io-console (0.8.2)
27
- json (2.19.7)
28
- karafka-rdkafka (0.27.2)
26
+ json (2.21.2)
27
+ karafka-rdkafka (0.28.0)
29
28
  ffi (~> 1.17.1)
30
29
  json (> 2.0)
31
30
  logger
32
31
  mini_portile2 (~> 2.6)
33
32
  rake (> 12)
34
- karafka-rdkafka (0.27.2-aarch64-linux-gnu)
33
+ karafka-rdkafka (0.28.0-aarch64-linux-gnu)
35
34
  ffi (~> 1.17.1)
36
35
  json (> 2.0)
37
36
  logger
38
37
  mini_portile2 (~> 2.6)
39
38
  rake (> 12)
40
- karafka-rdkafka (0.27.2-aarch64-linux-musl)
39
+ karafka-rdkafka (0.28.0-aarch64-linux-musl)
41
40
  ffi (~> 1.17.1)
42
41
  json (> 2.0)
43
42
  logger
44
43
  mini_portile2 (~> 2.6)
45
44
  rake (> 12)
46
- karafka-rdkafka (0.27.2-arm64-darwin)
45
+ karafka-rdkafka (0.28.0-arm64-darwin)
47
46
  ffi (~> 1.17.1)
48
47
  json (> 2.0)
49
48
  logger
50
49
  mini_portile2 (~> 2.6)
51
50
  rake (> 12)
52
- karafka-rdkafka (0.27.2-x86_64-linux-gnu)
51
+ karafka-rdkafka (0.28.0-x86_64-linux-gnu)
53
52
  ffi (~> 1.17.1)
54
53
  json (> 2.0)
55
54
  logger
56
55
  mini_portile2 (~> 2.6)
57
56
  rake (> 12)
58
- karafka-rdkafka (0.27.2-x86_64-linux-musl)
57
+ karafka-rdkafka (0.28.0-x86_64-linux-musl)
59
58
  ffi (~> 1.17.1)
60
59
  json (> 2.0)
61
60
  logger
@@ -70,12 +69,7 @@ GEM
70
69
  rake (13.4.2)
71
70
  reline (0.6.3)
72
71
  io-console (~> 0.5)
73
- simplecov (0.22.0)
74
- docile (~> 1.1)
75
- simplecov-html (~> 0.11)
76
- simplecov_json_formatter (~> 0.1)
77
- simplecov-html (0.13.2)
78
- simplecov_json_formatter (0.1.4)
72
+ simplecov (1.1.1)
79
73
  warning (1.6.0)
80
74
 
81
75
  PLATFORMS
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Core
5
+ module Configurable
6
+ # Base class for config defaults injectors.
7
+ #
8
+ # An injector enriches a config-like hash with a set of default values, applying each
9
+ # default only when the corresponding key is not already present. This lets a component
10
+ # ship sane defaults while still letting users override any of them by pre-populating the
11
+ # key themselves.
12
+ #
13
+ # Injectors are meant to be layered. A base (e.g. OSS) injector defines its {defaults} and
14
+ # an extension (e.g. Pro) prepends a module onto the singleton class and calls `super` to
15
+ # contribute additional defaults on top:
16
+ #
17
+ # Base.singleton_class.prepend(Extension)
18
+ #
19
+ # The only-if-absent rule applies to the target being enriched, not to the defaults
20
+ # themselves: a key the user already set in the target is never touched. How two layers
21
+ # resolve a key they both define is up to the layers -- e.g. an extension using
22
+ # `super.merge(extra)` lets its own value win, while `extra.merge(super)` would keep the
23
+ # base value.
24
+ #
25
+ # @example Define an injector with defaults
26
+ # class MyInjector < Karafka::Core::Configurable::Injector
27
+ # DEFAULTS = { 'a' => 1, 'b' => 2 }.freeze
28
+ #
29
+ # class << self
30
+ # def defaults
31
+ # DEFAULTS
32
+ # end
33
+ # end
34
+ # end
35
+ #
36
+ # MyInjector.call({ 'b' => 20 }) #=> { 'b' => 20, 'a' => 1 }
37
+ #
38
+ # @example Layer extra defaults (e.g. Pro) via prepend + super
39
+ # module ProDefaults
40
+ # def defaults
41
+ # super.merge('c' => 3)
42
+ # end
43
+ # end
44
+ #
45
+ # MyInjector.singleton_class.prepend(ProDefaults)
46
+ # MyInjector.call({}) #=> { 'a' => 1, 'b' => 2, 'c' => 3 }
47
+ #
48
+ # @note The base class holds no state and defines no defaults on its own; it is not useful
49
+ # directly and is expected to be subclassed. Subclasses should return the same defaults
50
+ # object (e.g. a frozen constant) on each call so that a prepended layer doing
51
+ # `super.merge(...)` never mutates it.
52
+ #
53
+ # @note Default values are injected by reference, not copied. A mutable default (an array or
54
+ # hash) is therefore shared across every target it is injected into, and mutating it in one
55
+ # place is visible everywhere. When a per-target mutable value is needed, the defaults
56
+ # layer should hand out a copy (e.g. `dup` it in `.defaults`).
57
+ class Injector
58
+ # Empty, immutable defaults used by the base class, which defines none of its own.
59
+ EMPTY_DEFAULTS = {}.freeze
60
+
61
+ private_constant :EMPTY_DEFAULTS
62
+
63
+ class << self
64
+ # Enriches the target with the defaults, without overwriting any key that is already
65
+ # present in it. The target is mutated in place.
66
+ #
67
+ # @param target [Hash] config hash to enrich in place
68
+ # @return [Hash] the same target, enriched with the missing defaults
69
+ def call(target)
70
+ defaults.each do |key, value|
71
+ next if target.key?(key)
72
+
73
+ target[key] = value
74
+ end
75
+
76
+ target
77
+ end
78
+
79
+ # @return [Hash] default values to inject. Override in subclasses; extensions may
80
+ # prepend a module onto the singleton class and call `super` to contribute additional
81
+ # defaults on top. The base class defines none.
82
+ def defaults
83
+ EMPTY_DEFAULTS
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -3,8 +3,7 @@
3
3
  module Karafka
4
4
  module Core
5
5
  module Configurable
6
- # Single non-leaf node
7
- # This is a core component for the configurable settings
6
+ # Single non-leaf node. This is a core component for the configurable settings
8
7
  #
9
8
  # The idea here is simple: we collect settings (leafs) and children (nodes) information and
10
9
  # we only compile/initialize the values prior to user running the `#configure` API. This API
@@ -24,7 +24,7 @@ module Karafka
24
24
  this = self
25
25
  # Allows "auto subject" definitions for the `describe` method, as it will figure
26
26
  # out the proper class that we want to describe
27
- # @param block [Proc] block with tests
27
+ # block - block with tests
28
28
  minitest_module.define_singleton_method :describe_current do |&block|
29
29
  describe(this.inherited, &block)
30
30
  end
@@ -27,7 +27,7 @@ module Karafka
27
27
  this = self
28
28
  # Allows "auto subject" definitions for the `#describe` method, as it will figure
29
29
  # out the proper class that we want to describe
30
- # @param block [Proc] block with specs
30
+ # block - block with specs
31
31
  rspec.define_singleton_method :describe_current do |&block|
32
32
  describe(this.inherited, &block)
33
33
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  module Karafka
4
4
  module Core
5
- # Karafka instrumentation related shared components
6
5
  module Instrumentation
7
6
  # This manager allows us to register multiple callbacks into a hook that is suppose to support
8
7
  # a single callback
@@ -100,8 +100,8 @@ module Karafka
100
100
  end
101
101
  end
102
102
 
103
- # Allows for unsubscription from events
104
- # This method will remove the listener/block from all events where it's currently subscribed.
103
+ # Allows for unsubscription from events. This method will remove the listener/block from all
104
+ # events where it's currently subscribed.
105
105
  #
106
106
  # @param listener_or_block [Object] listener object or block to remove from all events
107
107
  #
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Main module namespace
4
3
  module Karafka
5
4
  module Core
6
5
  # Monitoring for Karafka and WaterDrop
@@ -2,8 +2,7 @@
2
2
 
3
3
  module Karafka
4
4
  module Core
5
- # Current Karafka::Core version
6
- # We follow the versioning schema of given Karafka version
7
- VERSION = "2.6.2"
5
+ # Current Karafka::Core version. We follow the versioning schema of given Karafka version
6
+ VERSION = "2.6.3"
8
7
  end
9
8
  end
data/lib/karafka-core.rb CHANGED
@@ -15,6 +15,7 @@ require "karafka/core/monitoring/statistics_decorator"
15
15
  require "karafka/core/configurable"
16
16
  require "karafka/core/configurable/leaf"
17
17
  require "karafka/core/configurable/node"
18
+ require "karafka/core/configurable/injector"
18
19
  require "karafka/core/contractable/contract"
19
20
  require "karafka/core/contractable/result"
20
21
  require "karafka/core/contractable/rule"
@@ -36,12 +37,12 @@ rd_config = Rdkafka::Config
36
37
 
37
38
  # Rdkafka uses a single global callback for things. We bypass that by injecting a manager for
38
39
  # each callback type. Callback manager allows us to register more than one callback
39
- # @note Those managers are also used by Karafka for consumer related statistics
40
+ # Those managers are also used by Karafka for consumer related statistics
40
41
  rd_config.statistics_callback = instrumentation.statistics_callbacks
41
42
  rd_config.error_callback = instrumentation.error_callbacks
42
43
  rd_config.oauthbearer_token_refresh_callback = instrumentation.oauthbearer_token_refresh_callbacks
43
44
 
44
45
  # This loads librdkafka components into memory prior to initializing the client.
45
46
  # This mitigates macos forking issues.
46
- # @see https://github.com/confluentinc/librdkafka/issues/4590
47
+ # See https://github.com/confluentinc/librdkafka/issues/4590
47
48
  Rdkafka::Bindings.rd_kafka_global_init if Rdkafka::Bindings.respond_to?(:rd_kafka_global_init)
data/package-lock.json CHANGED
@@ -286,9 +286,9 @@
286
286
  }
287
287
  },
288
288
  "node_modules/smol-toml": {
289
- "version": "1.6.1",
290
- "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz",
291
- "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==",
289
+ "version": "1.7.1",
290
+ "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.7.1.tgz",
291
+ "integrity": "sha512-PPlsspAZ4jbMBu5DMFhfUGDQLu/vrL4SyBROVS37x8ynnVmFIs1VPBz1Co8Xks3TvpIaZXmU85y4DrQ+UyVFoQ==",
292
292
  "dev": true,
293
293
  "license": "BSD-3-Clause",
294
294
  "engines": {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: karafka-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.2
4
+ version: 2.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -72,6 +72,7 @@ files:
72
72
  - lib/karafka-core.rb
73
73
  - lib/karafka/core.rb
74
74
  - lib/karafka/core/configurable.rb
75
+ - lib/karafka/core/configurable/injector.rb
75
76
  - lib/karafka/core/configurable/leaf.rb
76
77
  - lib/karafka/core/configurable/node.rb
77
78
  - lib/karafka/core/contractable.rb
@@ -120,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
121
  - !ruby/object:Gem::Version
121
122
  version: '0'
122
123
  requirements: []
123
- rubygems_version: 4.0.10
124
+ rubygems_version: 4.0.16
124
125
  specification_version: 4
125
126
  summary: Karafka ecosystem core modules
126
127
  test_files: []