karafka-core 2.5.1 → 2.5.2
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 +3 -3
- data/.github/workflows/push.yml +2 -3
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +8 -8
- data/lib/karafka/core/contractable/contract.rb +25 -12
- data/lib/karafka/core/contractable/result.rb +22 -2
- data/lib/karafka/core/monitoring/monitor.rb +8 -0
- data/lib/karafka/core/monitoring/notifications.rb +15 -0
- data/lib/karafka/core/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dcd7aa040c5e5025430de4755c6e3de2850f8e697a8222328a304f571d9bd1fc
|
4
|
+
data.tar.gz: b3498c28bf38256e7012a950a51f464d66a503c045227f1dde0e503b6d9550c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 350399becfcf8a702a9c106cb6f6310dc57255549fbe54cd7bbadae4e1c2c1e13efc53b9d60972c20c2a057775483461f73f60dc2839da964db39de47b7f608d
|
7
|
+
data.tar.gz: 4b94de1f08121280d3321dad105487e7b3e3ddaefe2ba2d4a3dd67a5c2fe3b23cb5588fa707d8ad513346c860749f9389431751b26c1688b19104a585bda4de6
|
data/.github/workflows/ci.yml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
name:
|
1
|
+
name: CI
|
2
2
|
|
3
3
|
concurrency:
|
4
4
|
group: ${{ github.workflow }}-${{ github.ref }}
|
@@ -40,7 +40,7 @@ jobs:
|
|
40
40
|
run: "[ -e $APT_DEPS ] || sudo apt-get install -y --no-install-recommends $APT_DEPS"
|
41
41
|
|
42
42
|
- name: Set up Ruby
|
43
|
-
uses: ruby/setup-ruby@
|
43
|
+
uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
|
44
44
|
with:
|
45
45
|
ruby-version: ${{matrix.ruby}}
|
46
46
|
bundler: 'latest'
|
@@ -71,7 +71,7 @@ jobs:
|
|
71
71
|
with:
|
72
72
|
fetch-depth: 0
|
73
73
|
- name: Set up Ruby
|
74
|
-
uses: ruby/setup-ruby@
|
74
|
+
uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
|
75
75
|
with:
|
76
76
|
ruby-version: 3.4
|
77
77
|
- name: Install latest bundler
|
data/.github/workflows/push.yml
CHANGED
@@ -24,7 +24,7 @@ jobs:
|
|
24
24
|
fetch-depth: 0
|
25
25
|
|
26
26
|
- name: Set up Ruby
|
27
|
-
uses: ruby/setup-ruby@
|
27
|
+
uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
|
28
28
|
with:
|
29
29
|
bundler-cache: false
|
30
30
|
|
@@ -32,5 +32,4 @@ jobs:
|
|
32
32
|
run: |
|
33
33
|
bundle install --jobs 4 --retry 3
|
34
34
|
|
35
|
-
#
|
36
|
-
- uses: rubygems/release-gem@9e85cb11501bebc2ae661c1500176316d3987059 # v1
|
35
|
+
- uses: rubygems/release-gem@a25424ba2ba8b387abc8ef40807c2c85b96cbe32 # v1.1.1
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Karafka Core Changelog
|
2
2
|
|
3
|
+
## 2.5.2 (2025-06-11)
|
4
|
+
- [Enhancement] Support `#unsubscribe`.
|
5
|
+
- [Enhancement] Allow for providing a root scope path for error keys.
|
6
|
+
- [Fix] Fix a bug where on no errors the result would be an array instead of a hash.
|
7
|
+
- [Fix] Fix spec hanging when Kafka cluster on 9092 is running.
|
8
|
+
|
3
9
|
## 2.5.1 (2025-05-23)
|
4
10
|
- [Change] Move to trusted-publishers and remove signing since no longer needed.
|
5
11
|
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
karafka-core (2.5.
|
4
|
+
karafka-core (2.5.2)
|
5
5
|
karafka-rdkafka (>= 0.19.2, < 0.21.0)
|
6
6
|
logger (>= 1.6.0)
|
7
7
|
|
@@ -22,26 +22,26 @@ GEM
|
|
22
22
|
ffi (1.17.2-x86_64-darwin)
|
23
23
|
ffi (1.17.2-x86_64-linux-gnu)
|
24
24
|
ffi (1.17.2-x86_64-linux-musl)
|
25
|
-
karafka-rdkafka (0.19.
|
25
|
+
karafka-rdkafka (0.19.5)
|
26
26
|
ffi (~> 1.15)
|
27
27
|
mini_portile2 (~> 2.6)
|
28
28
|
rake (> 12)
|
29
29
|
logger (1.7.0)
|
30
30
|
mini_portile2 (2.8.9)
|
31
|
-
rake (13.
|
32
|
-
rspec (3.13.
|
31
|
+
rake (13.3.0)
|
32
|
+
rspec (3.13.1)
|
33
33
|
rspec-core (~> 3.13.0)
|
34
34
|
rspec-expectations (~> 3.13.0)
|
35
35
|
rspec-mocks (~> 3.13.0)
|
36
|
-
rspec-core (3.13.
|
36
|
+
rspec-core (3.13.4)
|
37
37
|
rspec-support (~> 3.13.0)
|
38
|
-
rspec-expectations (3.13.
|
38
|
+
rspec-expectations (3.13.5)
|
39
39
|
diff-lcs (>= 1.2.0, < 2.0)
|
40
40
|
rspec-support (~> 3.13.0)
|
41
|
-
rspec-mocks (3.13.
|
41
|
+
rspec-mocks (3.13.5)
|
42
42
|
diff-lcs (>= 1.2.0, < 2.0)
|
43
43
|
rspec-support (~> 3.13.0)
|
44
|
-
rspec-support (3.13.
|
44
|
+
rspec-support (3.13.4)
|
45
45
|
simplecov (0.22.0)
|
46
46
|
docile (~> 1.1)
|
47
47
|
simplecov-html (~> 0.11)
|
@@ -78,18 +78,20 @@ module Karafka
|
|
78
78
|
# Runs the validation
|
79
79
|
#
|
80
80
|
# @param data [Hash] hash with data we want to validate
|
81
|
+
# @param scope [Array<String>] scope of this contract (if any) or empty array if no parent
|
82
|
+
# scope is needed if contract starts from root
|
81
83
|
# @return [Result] validaton result
|
82
|
-
def call(data)
|
84
|
+
def call(data, scope: [])
|
83
85
|
errors = []
|
84
86
|
|
85
87
|
self.class.rules.each do |rule|
|
86
88
|
case rule.type
|
87
89
|
when :required
|
88
|
-
validate_required(data, rule, errors)
|
90
|
+
validate_required(data, rule, errors, scope)
|
89
91
|
when :optional
|
90
|
-
validate_optional(data, rule, errors)
|
92
|
+
validate_optional(data, rule, errors, scope)
|
91
93
|
when :virtual
|
92
|
-
validate_virtual(data, rule, errors)
|
94
|
+
validate_virtual(data, rule, errors, scope)
|
93
95
|
end
|
94
96
|
end
|
95
97
|
|
@@ -98,11 +100,13 @@ module Karafka
|
|
98
100
|
|
99
101
|
# @param data [Hash] data for validation
|
100
102
|
# @param error_class [Class] error class that should be used when validation fails
|
103
|
+
# @param scope [Array<String>] scope of this contract (if any) or empty array if no parent
|
104
|
+
# scope is needed if contract starts from root
|
101
105
|
# @return [Boolean] true
|
102
106
|
# @raise [StandardError] any error provided in the error_class that inherits from the
|
103
107
|
# standard error
|
104
|
-
def validate!(data, error_class)
|
105
|
-
result = call(data)
|
108
|
+
def validate!(data, error_class, scope: [])
|
109
|
+
result = call(data, scope: scope)
|
106
110
|
|
107
111
|
return true if result.success?
|
108
112
|
|
@@ -117,19 +121,20 @@ module Karafka
|
|
117
121
|
# @param data [Hash] input hash
|
118
122
|
# @param rule [Rule] validation rule
|
119
123
|
# @param errors [Array] array with errors from previous rules (if any)
|
120
|
-
|
124
|
+
# @param scope [Array<String>]
|
125
|
+
def validate_required(data, rule, errors, scope)
|
121
126
|
for_checking = dig(data, rule.path)
|
122
127
|
|
123
128
|
# We need to compare `DIG_MISS` against stuff because of the ownership of the `#==`
|
124
129
|
# method
|
125
130
|
if DIG_MISS == for_checking
|
126
|
-
errors << [rule.path, :missing]
|
131
|
+
errors << [scope + rule.path, :missing]
|
127
132
|
else
|
128
133
|
result = rule.validator.call(for_checking, data, errors, self)
|
129
134
|
|
130
135
|
return if result == true
|
131
136
|
|
132
|
-
errors << [rule.path, result || :format]
|
137
|
+
errors << [scope + rule.path, result || :format]
|
133
138
|
end
|
134
139
|
end
|
135
140
|
|
@@ -139,7 +144,8 @@ module Karafka
|
|
139
144
|
# @param data [Hash] input hash
|
140
145
|
# @param rule [Rule] validation rule
|
141
146
|
# @param errors [Array] array with errors from previous rules (if any)
|
142
|
-
|
147
|
+
# @param scope [Array<String>]
|
148
|
+
def validate_optional(data, rule, errors, scope)
|
143
149
|
for_checking = dig(data, rule.path)
|
144
150
|
|
145
151
|
return if DIG_MISS == for_checking
|
@@ -148,7 +154,7 @@ module Karafka
|
|
148
154
|
|
149
155
|
return if result == true
|
150
156
|
|
151
|
-
errors << [rule.path, result || :format]
|
157
|
+
errors << [scope + rule.path, result || :format]
|
152
158
|
end
|
153
159
|
|
154
160
|
# Runs validation for rules on virtual fields (aggregates, etc) and adds errors (if any) to
|
@@ -157,11 +163,18 @@ module Karafka
|
|
157
163
|
# @param data [Hash] input hash
|
158
164
|
# @param rule [Rule] validation rule
|
159
165
|
# @param errors [Array] array with errors from previous rules (if any)
|
160
|
-
|
166
|
+
# @param scope [Array<String>]
|
167
|
+
def validate_virtual(data, rule, errors, scope)
|
161
168
|
result = rule.validator.call(data, errors, self)
|
162
169
|
|
163
170
|
return if result == true
|
164
171
|
|
172
|
+
if result
|
173
|
+
result.each do |sub_result|
|
174
|
+
sub_result[0] = scope + sub_result[0]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
165
178
|
errors.push(*result)
|
166
179
|
end
|
167
180
|
|
@@ -14,7 +14,7 @@ module Karafka
|
|
14
14
|
def initialize(errors, contract)
|
15
15
|
# Short track to skip object allocation for the happy path
|
16
16
|
if errors.empty?
|
17
|
-
@errors =
|
17
|
+
@errors = {}
|
18
18
|
return
|
19
19
|
end
|
20
20
|
|
@@ -41,7 +41,8 @@ module Karafka
|
|
41
41
|
|
42
42
|
private
|
43
43
|
|
44
|
-
# Builds message based on the error messages
|
44
|
+
# Builds message based on the error messages and scope
|
45
|
+
#
|
45
46
|
# @param contract [Object] contract for which we build the result
|
46
47
|
# @param scope [Symbol] path to the key that has an error
|
47
48
|
# @param error_key [Symbol] error key for yaml errors lookup
|
@@ -49,6 +50,25 @@ module Karafka
|
|
49
50
|
def build_message(contract, scope, error_key)
|
50
51
|
messages = contract.class.config.error_messages
|
51
52
|
|
53
|
+
# Split scope into parts for progressive checking
|
54
|
+
scope_parts = scope.to_s.split('.')
|
55
|
+
|
56
|
+
# Try full scope first, then progressively remove from beginning
|
57
|
+
# This allows us to have full path scoped errors but can also be used as a fallback,
|
58
|
+
# when scopes are dynamic. For example 'consumer_group_name.topic_name.name_format'
|
59
|
+
(0..scope_parts.length).each do |i|
|
60
|
+
current_scope_parts = scope_parts[i..]
|
61
|
+
|
62
|
+
key = if current_scope_parts.empty?
|
63
|
+
error_key.to_s
|
64
|
+
else
|
65
|
+
"#{current_scope_parts.join('.')}_#{error_key}"
|
66
|
+
end
|
67
|
+
|
68
|
+
return messages[key] if messages.key?(key)
|
69
|
+
end
|
70
|
+
|
71
|
+
# If nothing found, raise the original error
|
52
72
|
messages.fetch(error_key.to_s) do
|
53
73
|
messages.fetch("#{scope}_#{error_key}")
|
54
74
|
end
|
@@ -42,6 +42,14 @@ module Karafka
|
|
42
42
|
@notifications_bus.subscribe(*args, &block)
|
43
43
|
end
|
44
44
|
|
45
|
+
# Allows for removal of whatever was subscribed
|
46
|
+
#
|
47
|
+
# @param listener_or_block [Object] object that is subscribed whether this is a listener
|
48
|
+
# instance or a block.
|
49
|
+
def unsubscribe(listener_or_block)
|
50
|
+
@notifications_bus.unsubscribe(listener_or_block)
|
51
|
+
end
|
52
|
+
|
45
53
|
# @return [Hash<String, Array>] hash where keys are events and values are arrays with
|
46
54
|
# listeners subscribed to particular events. Since different events may have different
|
47
55
|
# listeners, this is returned that way.
|
@@ -89,6 +89,21 @@ module Karafka
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
+
# Allows for unsubscription from events
|
93
|
+
# This method will remove the listener/block from all events where it's currently subscribed.
|
94
|
+
#
|
95
|
+
# @param listener_or_block [Object] listener object or block to remove from all events
|
96
|
+
#
|
97
|
+
# @example Unsubscribe using listener (removes from all events where it's subscribed)
|
98
|
+
# unsubscribe(my_listener)
|
99
|
+
def unsubscribe(listener_or_block)
|
100
|
+
@mutex.synchronize do
|
101
|
+
@listeners.each_value do |event_listeners|
|
102
|
+
event_listeners.delete(listener_or_block)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
92
107
|
# Allows for code instrumentation
|
93
108
|
# Runs the provided code and sends the instrumentation details to all registered listeners
|
94
109
|
#
|
data/lib/karafka/core/version.rb
CHANGED