karafka-core 2.6.2 → 2.6.4
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/.github/workflows/ci.yml +10 -10
- data/.github/workflows/push.yml +3 -3
- data/.github/workflows/verify-action-pins.yml +1 -1
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/.yard-lint.yml +29 -1
- data/CHANGELOG.md +28 -22
- data/Gemfile.lint.lock +8 -7
- data/Gemfile.lock +11 -17
- data/lib/karafka/core/configurable/importer.rb +148 -0
- data/lib/karafka/core/configurable/injector.rb +89 -0
- data/lib/karafka/core/configurable/node.rb +1 -2
- data/lib/karafka/core/helpers/minitest_locator.rb +1 -1
- data/lib/karafka/core/helpers/rspec_locator.rb +1 -1
- data/lib/karafka/core/instrumentation/callbacks_manager.rb +0 -1
- data/lib/karafka/core/monitoring/notifications.rb +2 -2
- data/lib/karafka/core/monitoring.rb +0 -1
- data/lib/karafka/core/version.rb +2 -3
- data/lib/karafka-core.rb +4 -2
- data/package-lock.json +6 -6
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b7064756fbbf13ddd1048da55f30969b2ae10d58442b9a4ec8c8b5250a260473
|
|
4
|
+
data.tar.gz: 9d6fbe9c4257ce42e03017333602354265c6fa408e585099c6c515d3523c368d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4889fd25e48a9f06adfe9797862aa7d52dd6f363cb95839bf31e4bf66b499db9210331d1d5302f9bdf8d221c9895e68dcc58b8aec07b52004c21e7796779ed48
|
|
7
|
+
data.tar.gz: b154d18d6feeefac2e715d21c0f63c7e5841c145f5f13dbd588386d7dbd54cc0187c2640a1034679b806db66dc6e19ffb8bf5007ca44c914a0e69abb8758f356
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -29,7 +29,7 @@ jobs:
|
|
|
29
29
|
- ruby: '4.0'
|
|
30
30
|
coverage: 'true'
|
|
31
31
|
steps:
|
|
32
|
-
- uses: actions/checkout@
|
|
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@
|
|
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@
|
|
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@
|
|
72
|
+
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
|
73
73
|
with:
|
|
74
|
-
ruby-version: '4.0.
|
|
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@
|
|
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@
|
|
89
|
+
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
|
90
90
|
with:
|
|
91
|
-
ruby-version: '4.0.
|
|
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@
|
|
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@
|
|
104
|
+
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
105
105
|
with:
|
|
106
106
|
node-version: '20'
|
|
107
107
|
cache: 'npm'
|
data/.github/workflows/push.yml
CHANGED
|
@@ -19,12 +19,12 @@ jobs:
|
|
|
19
19
|
id-token: write
|
|
20
20
|
|
|
21
21
|
steps:
|
|
22
|
-
- uses: actions/checkout@
|
|
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@
|
|
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@
|
|
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@
|
|
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
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.0.
|
|
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:
|
|
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,33 +1,39 @@
|
|
|
1
1
|
# Karafka Core Changelog
|
|
2
2
|
|
|
3
|
+
## 2.6.4 (2026-09-11)
|
|
4
|
+
- [Enhancement] Add `Configurable::Importer`, a subclassable base for injecting memoized config readers into a class. A subclass names the config root once by overriding `.root`, and each use site then names only the attributes it wants. Supports both `include` and `extend`.
|
|
5
|
+
|
|
6
|
+
## 2.6.3 (2026-08-31)
|
|
7
|
+
- [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.
|
|
8
|
+
|
|
3
9
|
## 2.6.2 (2026-06-29)
|
|
4
|
-
- [Enhancement] Document that a leaf's `default` value is
|
|
5
|
-
- [Fix] `require "pathname"` explicitly in `lib/karafka-core.rb
|
|
6
|
-
- [Enhancement] Document
|
|
7
|
-
- [Fix] `Configurable::Node#register` raises the documented "already registered" `ArgumentError` for a name
|
|
10
|
+
- [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.
|
|
11
|
+
- [Fix] `require "pathname"` explicitly in `lib/karafka-core.rb`. `Karafka::Core.gem_root` returns a `Pathname` but the gem never required it, so `gem_root` raised `NameError` wherever nothing else happened to load it first.
|
|
12
|
+
- [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.
|
|
13
|
+
- [Fix] `Configurable::Node#register` now raises the documented "already registered" `ArgumentError` for a name used by an unread lazy-with-constructor setting, which it previously overwrote silently.
|
|
8
14
|
- [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
15
|
- [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
|
-
- [Fix] Honor `excluded_keys` containing `"cgrp"` in `StatisticsDecorator` `only_keys` mode
|
|
11
|
-
- [Fix] Guard the patched rdkafka error callback against a null client pointer
|
|
12
|
-
- [Fix] Resolve fatal errors in the patched rdkafka error callback
|
|
13
|
-
- [Fix] A lazy setting declared without a constructor (`setting(:x, lazy: true)`) no longer raises when
|
|
14
|
-
- [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
|
|
15
|
-
- [Fix]
|
|
16
|
-
- [Fix]
|
|
17
|
-
- [Fix] Report a freeze duration (`_fd`) of `0` for statistics keys that
|
|
18
|
-
- [Fix] Make assigning a setting on a frozen `Configurable::Node` atomic
|
|
19
|
-
- [Fix] `Configurable::Node#to_h`
|
|
16
|
+
- [Fix] Honor `excluded_keys` containing `"cgrp"` in `StatisticsDecorator` `only_keys` mode; the `cgrp` branch lacked the exclusion guard its `brokers` and `topics` siblings have.
|
|
17
|
+
- [Fix] Guard the patched rdkafka error callback against a null client pointer, which librdkafka can pass early in client construction and which could segfault the process.
|
|
18
|
+
- [Fix] Resolve fatal errors in the patched rdkafka error callback via `RdkafkaError.build_fatal`, so the real underlying error is reported instead of the generic `ERR__FATAL` marker.
|
|
19
|
+
- [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.
|
|
20
|
+
- [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; only an `Array` of error pairs is collected.
|
|
21
|
+
- [Fix] Make `CallbacksManager` thread-safe under concurrent `add`/`delete` during dispatch, so a callback registered or removed while callbacks were firing is no longer lost.
|
|
22
|
+
- [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.
|
|
23
|
+
- [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.
|
|
24
|
+
- [Fix] Make assigning a setting on a frozen `Configurable::Node` atomic; it previously mutated the canonical store before raising `FrozenError`, leaving the store and the reader permanently out of sync.
|
|
25
|
+
- [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
26
|
- [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
|
-
- [Fix] Strip the tests/specs root directory as an anchored prefix
|
|
27
|
+
- [Fix] Strip the tests/specs root directory as an anchored prefix instead of a global `gsub` in `MinitestLocator` and `RSpecLocator`, which corrupted the derived subject path when the root string recurred later in it.
|
|
22
28
|
|
|
23
29
|
## 2.6.1 (2026-06-15)
|
|
24
|
-
- [Enhancement] Speed up `Contract#call` by ~1.
|
|
30
|
+
- [Enhancement] Speed up `Contract#call` by ~1.25–1.4x, the per-message validation path in WaterDrop producers.
|
|
25
31
|
- [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
|
-
- [Change] Reject reserved setting names with an `ArgumentError` in `Configurable::Node#setting` and `#register
|
|
27
|
-
- [Enhancement]
|
|
28
|
-
- [Enhancement]
|
|
29
|
-
- [Enhancement] Instantiate each `Configurable::Node` through a per-layout anonymous subclass so
|
|
30
|
-
- [Fix] Symbolize setting names at definition time
|
|
32
|
+
- [Change] Reject reserved setting names with an `ArgumentError` in `Configurable::Node#setting` and `#register` (internal state names and the node public API names). Such names previously shadowed the node's own accessors and could corrupt its internal state.
|
|
33
|
+
- [Enhancement] Speed up `Monitor#instrument` dispatch (~1.2x) on the common no-subscribers path.
|
|
34
|
+
- [Enhancement] Speed up `Configurable::Node` settings reads (~1.4x flat, ~1.6x nested) on hot paths.
|
|
35
|
+
- [Enhancement] Instantiate each `Configurable::Node` through a per-layout anonymous subclass so ivar-backed settings do not grow object shape variations on the shared `Node` class. `deep_dup` reuses the template's subclass.
|
|
36
|
+
- [Fix] Symbolize setting names at definition time and on config store writes, so `String` setting names work end to end and cannot corrupt node internal state when they match reserved internal names.
|
|
31
37
|
- [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`.
|
|
32
38
|
- [Change] Assigning a setting on a frozen config node now raises `FrozenError` (previously the write silently mutated internal storage despite the freeze).
|
|
33
39
|
|
|
@@ -52,7 +58,7 @@
|
|
|
52
58
|
- [Enhancement] Store execution time separately in `Event` and build the merged payload hash lazily on `#payload` access, eliminating 1 Hash allocation per `Notifications#instrument` call when listeners use `#[]` access (the common pattern), yielding ~1.7x faster event dispatch.
|
|
53
59
|
- [Enhancement] Replace `StatisticsDecorator#diff` pending-writes buffer with `keys.each` direct-write iteration, eliminating the buffer and write-back loop for ~13% faster decoration at scale (10 brokers, 20 topics, 2000 partitions).
|
|
54
60
|
- [Enhancement] Reorder `StatisticsDecorator#diff` type checks to test `Numeric` before `Hash`, matching the ~80% numeric value distribution in librdkafka statistics.
|
|
55
|
-
- [Enhancement] Support `only_keys` option in `StatisticsDecorator` to decorate only specified numeric keys
|
|
61
|
+
- [Enhancement] Support an `only_keys` option in `StatisticsDecorator` to decorate only specified numeric keys. Combined with `excluded_keys`, this cuts decoration cost from ~80ms to ~8.5ms per call on large clusters (10 brokers, 20 topics, 2000 partitions).
|
|
56
62
|
- [Enhancement] Cache `Tags#to_a` values array and invalidate on `add`/`delete`/`clear` to avoid allocating a new Array and running `uniq` on every call, yielding ~7x faster reads at 5 tags and ~28x faster at 20 tags.
|
|
57
63
|
|
|
58
64
|
## 2.5.10 (2026-03-02)
|
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.
|
|
59
|
-
yard-lint (1.
|
|
58
|
+
yard (0.9.45)
|
|
59
|
+
yard-lint (1.10.1)
|
|
60
60
|
yard (~> 0.9)
|
|
61
61
|
zeitwerk (~> 2.6)
|
|
62
|
-
zeitwerk (2.
|
|
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.
|
|
99
|
-
yard-lint (1.
|
|
100
|
-
zeitwerk (2.
|
|
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.
|
|
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.
|
|
4
|
+
karafka-core (2.6.4)
|
|
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)
|
|
@@ -23,39 +22,39 @@ GEM
|
|
|
23
22
|
ffi (1.17.4-x86_64-darwin)
|
|
24
23
|
ffi (1.17.4-x86_64-linux-gnu)
|
|
25
24
|
ffi (1.17.4-x86_64-linux-musl)
|
|
26
|
-
io-console (0.
|
|
27
|
-
json (2.
|
|
28
|
-
karafka-rdkafka (0.
|
|
25
|
+
io-console (0.9.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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
57
|
+
karafka-rdkafka (0.28.0-x86_64-linux-musl)
|
|
59
58
|
ffi (~> 1.17.1)
|
|
60
59
|
json (> 2.0)
|
|
61
60
|
logger
|
|
@@ -68,14 +67,9 @@ GEM
|
|
|
68
67
|
prism (~> 1.5)
|
|
69
68
|
prism (1.9.0)
|
|
70
69
|
rake (13.4.2)
|
|
71
|
-
reline (0.
|
|
70
|
+
reline (0.7.0)
|
|
72
71
|
io-console (~> 0.5)
|
|
73
|
-
simplecov (
|
|
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,148 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Karafka
|
|
4
|
+
module Core
|
|
5
|
+
module Configurable
|
|
6
|
+
# Base class for config importers.
|
|
7
|
+
#
|
|
8
|
+
# An importer builds memoized config readers on a target, so a class can read a few config
|
|
9
|
+
# values under short, local names instead of spelling out the full config path at every
|
|
10
|
+
# call site.
|
|
11
|
+
#
|
|
12
|
+
# The config root is not hardcoded and is not passed per use site: it is defined once, by
|
|
13
|
+
# overriding {root} in a subclass. Each consumer therefore ships one importer subclass
|
|
14
|
+
# pointing at its own config tree (e.g. `Karafka::App.config` or `Karafka::Web.config`),
|
|
15
|
+
# and every use site only names the attributes it wants.
|
|
16
|
+
#
|
|
17
|
+
# {root} is a method rather than a stored config object, so it is resolved lazily, on the
|
|
18
|
+
# first read of a given attribute. That matters because importers are typically built while
|
|
19
|
+
# a class body is being loaded, which is usually before the config itself has been set up.
|
|
20
|
+
#
|
|
21
|
+
# Each attribute is memoized per target, so the path is walked only once and every later
|
|
22
|
+
# read is a plain instance variable lookup. Memoization is `||=`-based, so an attribute
|
|
23
|
+
# whose configured value is `nil` or `false` is re-read on each call.
|
|
24
|
+
#
|
|
25
|
+
# @example Define the importer once, with the root
|
|
26
|
+
# module Karafka
|
|
27
|
+
# module Web
|
|
28
|
+
# module Helpers
|
|
29
|
+
# class ConfigImporter < Karafka::Core::Configurable::Importer
|
|
30
|
+
# class << self
|
|
31
|
+
# def root
|
|
32
|
+
# Karafka::Web.config
|
|
33
|
+
# end
|
|
34
|
+
# end
|
|
35
|
+
# end
|
|
36
|
+
# end
|
|
37
|
+
# end
|
|
38
|
+
# end
|
|
39
|
+
#
|
|
40
|
+
# @example Import instance-level readers
|
|
41
|
+
# class LagStats
|
|
42
|
+
# include Karafka::Web::Helpers::ConfigImporter.new(
|
|
43
|
+
# skew_threshold: %i[ui health lags skew_threshold]
|
|
44
|
+
# )
|
|
45
|
+
#
|
|
46
|
+
# def skewed?(lag)
|
|
47
|
+
# lag > skew_threshold
|
|
48
|
+
# end
|
|
49
|
+
# end
|
|
50
|
+
#
|
|
51
|
+
# @example Import class-level readers
|
|
52
|
+
# class Message
|
|
53
|
+
# extend Karafka::Web::Helpers::ConfigImporter.new(per_page: %i[ui per_page])
|
|
54
|
+
# end
|
|
55
|
+
#
|
|
56
|
+
# Message.per_page
|
|
57
|
+
#
|
|
58
|
+
# @example Import the whole config root under `#config` (the default)
|
|
59
|
+
# class Consumer
|
|
60
|
+
# include Karafka::Web::Helpers::ConfigImporter.new
|
|
61
|
+
# end
|
|
62
|
+
#
|
|
63
|
+
# @note The base class defines no root of its own; it is not useful directly and is expected
|
|
64
|
+
# to be subclassed. Reading an attribute off an importer whose class defines no {root}
|
|
65
|
+
# raises `NotImplementedError`.
|
|
66
|
+
#
|
|
67
|
+
# @note The readers are defined directly on the target, so an attribute name that collides
|
|
68
|
+
# with an existing method silently replaces it.
|
|
69
|
+
class Importer < Module
|
|
70
|
+
# Default attributes map, exposing the whole config root under `#config`.
|
|
71
|
+
DEFAULT_ATTRIBUTES = { config: %i[itself] }.freeze
|
|
72
|
+
|
|
73
|
+
private_constant :DEFAULT_ATTRIBUTES
|
|
74
|
+
|
|
75
|
+
class << self
|
|
76
|
+
# @return [Object] config root the attribute paths are resolved against. Override in
|
|
77
|
+
# subclasses; the base class defines none. Called on each memoization miss rather
|
|
78
|
+
# than when the importer is built, so it may safely reference a config that does not
|
|
79
|
+
# exist yet at load time.
|
|
80
|
+
# @raise [NotImplementedError] when called on a class that does not define a root
|
|
81
|
+
def root
|
|
82
|
+
raise(
|
|
83
|
+
NotImplementedError,
|
|
84
|
+
"Define .root in a Karafka::Core::Configurable::Importer subclass"
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# @param attributes [Hash{Symbol => Array<Symbol>}] map defining what to import. The key
|
|
90
|
+
# is the name the reader will be available under and the value is the path to the
|
|
91
|
+
# attribute, relative to the root, as an array of message names.
|
|
92
|
+
def initialize(attributes = DEFAULT_ATTRIBUTES)
|
|
93
|
+
super()
|
|
94
|
+
@attributes = attributes
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# @return [Object] config root this importer resolves against, as defined by its class
|
|
98
|
+
def root
|
|
99
|
+
self.class.root
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Defines the readers as instance methods on the target.
|
|
103
|
+
#
|
|
104
|
+
# @param model [Object] object to which we want to add the config fetchers
|
|
105
|
+
# @return [void]
|
|
106
|
+
def included(model)
|
|
107
|
+
super
|
|
108
|
+
|
|
109
|
+
define_readers(model, :define_method)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Defines the readers as class-level methods on the target.
|
|
113
|
+
#
|
|
114
|
+
# @param model [Object] object to which we want to add the config fetchers on a class
|
|
115
|
+
# level
|
|
116
|
+
# @return [void]
|
|
117
|
+
def extended(model)
|
|
118
|
+
super
|
|
119
|
+
|
|
120
|
+
define_readers(model, :define_singleton_method)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
|
|
125
|
+
# Defines one memoized reader per configured attribute on the target.
|
|
126
|
+
#
|
|
127
|
+
# @param model [Object] object the readers are defined on
|
|
128
|
+
# @param definer [Symbol] method used to define them, either `:define_method` for
|
|
129
|
+
# instance-level readers or `:define_singleton_method` for class-level ones
|
|
130
|
+
# @return [void]
|
|
131
|
+
def define_readers(model, definer)
|
|
132
|
+
importer = self
|
|
133
|
+
|
|
134
|
+
@attributes.each do |name, path|
|
|
135
|
+
ivar = :"@#{name}"
|
|
136
|
+
|
|
137
|
+
model.public_send(definer, name) do
|
|
138
|
+
instance_variable_get(ivar) || instance_variable_set(
|
|
139
|
+
ivar,
|
|
140
|
+
path.reduce(importer.root) { |node, part| node.public_send(part) }
|
|
141
|
+
)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
@@ -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
|
-
#
|
|
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
|
-
#
|
|
30
|
+
# block - block with specs
|
|
31
31
|
rspec.define_singleton_method :describe_current do |&block|
|
|
32
32
|
describe(this.inherited, &block)
|
|
33
33
|
end
|
|
@@ -100,8 +100,8 @@ module Karafka
|
|
|
100
100
|
end
|
|
101
101
|
end
|
|
102
102
|
|
|
103
|
-
# Allows for unsubscription from events
|
|
104
|
-
#
|
|
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
|
#
|
data/lib/karafka/core/version.rb
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Karafka
|
|
4
4
|
module Core
|
|
5
|
-
# Current Karafka::Core version
|
|
6
|
-
|
|
7
|
-
VERSION = "2.6.2"
|
|
5
|
+
# Current Karafka::Core version. We follow the versioning schema of given Karafka version
|
|
6
|
+
VERSION = "2.6.4"
|
|
8
7
|
end
|
|
9
8
|
end
|
data/lib/karafka-core.rb
CHANGED
|
@@ -15,6 +15,8 @@ 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"
|
|
19
|
+
require "karafka/core/configurable/importer"
|
|
18
20
|
require "karafka/core/contractable/contract"
|
|
19
21
|
require "karafka/core/contractable/result"
|
|
20
22
|
require "karafka/core/contractable/rule"
|
|
@@ -36,12 +38,12 @@ rd_config = Rdkafka::Config
|
|
|
36
38
|
|
|
37
39
|
# Rdkafka uses a single global callback for things. We bypass that by injecting a manager for
|
|
38
40
|
# each callback type. Callback manager allows us to register more than one callback
|
|
39
|
-
#
|
|
41
|
+
# Those managers are also used by Karafka for consumer related statistics
|
|
40
42
|
rd_config.statistics_callback = instrumentation.statistics_callbacks
|
|
41
43
|
rd_config.error_callback = instrumentation.error_callbacks
|
|
42
44
|
rd_config.oauthbearer_token_refresh_callback = instrumentation.oauthbearer_token_refresh_callbacks
|
|
43
45
|
|
|
44
46
|
# This loads librdkafka components into memory prior to initializing the client.
|
|
45
47
|
# This mitigates macos forking issues.
|
|
46
|
-
#
|
|
48
|
+
# See https://github.com/confluentinc/librdkafka/issues/4590
|
|
47
49
|
Rdkafka::Bindings.rd_kafka_global_init if Rdkafka::Bindings.respond_to?(:rd_kafka_global_init)
|
data/package-lock.json
CHANGED
|
@@ -103,9 +103,9 @@
|
|
|
103
103
|
}
|
|
104
104
|
},
|
|
105
105
|
"node_modules/fastq": {
|
|
106
|
-
"version": "1.20.
|
|
107
|
-
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.
|
|
108
|
-
"integrity": "sha512-
|
|
106
|
+
"version": "1.20.2",
|
|
107
|
+
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.2.tgz",
|
|
108
|
+
"integrity": "sha512-UpGiiODyCGprM8EPP6JodP6jC9Rws6TCuiDOD+nn0CJhR8guI3g/ozo4ugL0vJ+Yz1UtJuuRPqvQuybVOF1VQA==",
|
|
109
109
|
"dev": true,
|
|
110
110
|
"license": "ISC",
|
|
111
111
|
"dependencies": {
|
|
@@ -286,9 +286,9 @@
|
|
|
286
286
|
}
|
|
287
287
|
},
|
|
288
288
|
"node_modules/smol-toml": {
|
|
289
|
-
"version": "1.
|
|
290
|
-
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.
|
|
291
|
-
"integrity": "sha512-
|
|
289
|
+
"version": "1.8.0",
|
|
290
|
+
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.8.0.tgz",
|
|
291
|
+
"integrity": "sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==",
|
|
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.
|
|
4
|
+
version: 2.6.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Maciej Mensfeld
|
|
@@ -72,6 +72,8 @@ 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/importer.rb
|
|
76
|
+
- lib/karafka/core/configurable/injector.rb
|
|
75
77
|
- lib/karafka/core/configurable/leaf.rb
|
|
76
78
|
- lib/karafka/core/configurable/node.rb
|
|
77
79
|
- lib/karafka/core/contractable.rb
|
|
@@ -120,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
120
122
|
- !ruby/object:Gem::Version
|
|
121
123
|
version: '0'
|
|
122
124
|
requirements: []
|
|
123
|
-
rubygems_version: 4.0.
|
|
125
|
+
rubygems_version: 4.0.16
|
|
124
126
|
specification_version: 4
|
|
125
127
|
summary: Karafka ecosystem core modules
|
|
126
128
|
test_files: []
|