karafka 2.0.23 → 2.0.24
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
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ci.yml +2 -0
- data/CHANGELOG.md +32 -1
- data/Gemfile.lock +8 -7
- data/README.md +3 -3
- data/config/{errors.yml → locales/errors.yml} +1 -1
- data/config/locales/pro_errors.yml +18 -0
- data/docker-compose.yml +3 -0
- data/karafka.gemspec +2 -2
- data/lib/karafka/active_job/job_options_contract.rb +1 -1
- data/lib/karafka/admin.rb +2 -4
- data/lib/karafka/app.rb +15 -4
- data/lib/karafka/base_consumer.rb +36 -0
- data/lib/karafka/connection/listener.rb +1 -1
- data/lib/karafka/contracts/config.rb +1 -1
- data/lib/karafka/contracts/consumer_group.rb +1 -1
- data/lib/karafka/contracts/server_cli_options.rb +1 -1
- data/lib/karafka/contracts/topic.rb +1 -1
- data/lib/karafka/instrumentation/logger_listener.rb +32 -0
- data/lib/karafka/instrumentation/notifications.rb +3 -0
- data/lib/karafka/messages/message.rb +14 -2
- data/lib/karafka/messages/parser.rb +14 -0
- data/lib/karafka/pro/active_job/job_options_contract.rb +1 -1
- data/lib/karafka/pro/encryption/cipher.rb +58 -0
- data/lib/karafka/pro/encryption/contracts/config.rb +79 -0
- data/lib/karafka/pro/encryption/errors.rb +24 -0
- data/lib/karafka/pro/encryption/messages/middleware.rb +46 -0
- data/lib/karafka/pro/encryption/messages/parser.rb +56 -0
- data/lib/karafka/pro/encryption/setup/config.rb +48 -0
- data/lib/karafka/pro/encryption.rb +47 -0
- data/lib/karafka/pro/loader.rb +22 -1
- data/lib/karafka/pro/processing/strategies/aj_dlq_mom.rb +1 -1
- data/lib/karafka/pro/processing/strategies/aj_lrj_mom_vp.rb +1 -1
- data/lib/karafka/pro/processing/strategies/aj_mom_vp.rb +1 -1
- data/lib/karafka/pro/processing/strategies/default.rb +1 -1
- data/lib/karafka/pro/processing/strategies/dlq.rb +1 -1
- data/lib/karafka/pro/processing/strategies/dlq_lrj.rb +1 -1
- data/lib/karafka/pro/processing/strategies/dlq_lrj_mom.rb +1 -1
- data/lib/karafka/pro/processing/strategies/dlq_mom.rb +1 -1
- data/lib/karafka/pro/processing/strategies/lrj.rb +1 -1
- data/lib/karafka/pro/processing/strategies/lrj_mom.rb +1 -1
- data/lib/karafka/pro/processing/strategies/mom.rb +1 -1
- data/lib/karafka/pro/routing/features/dead_letter_queue/contract.rb +2 -2
- data/lib/karafka/pro/routing/features/long_running_job/contract.rb +2 -2
- data/lib/karafka/pro/routing/features/virtual_partitions/contract.rb +2 -2
- data/lib/karafka/processing/executor.rb +1 -1
- data/lib/karafka/processing/strategies/aj_dlq_mom.rb +1 -1
- data/lib/karafka/processing/strategies/default.rb +1 -1
- data/lib/karafka/processing/strategies/dlq.rb +1 -1
- data/lib/karafka/processing/strategies/dlq_mom.rb +1 -1
- data/lib/karafka/processing/strategies/mom.rb +1 -1
- data/lib/karafka/processing/worker.rb +1 -1
- data/lib/karafka/railtie.rb +3 -0
- data/lib/karafka/routing/builder.rb +1 -1
- data/lib/karafka/routing/consumer_group.rb +3 -3
- data/lib/karafka/routing/features/active_job/contract.rb +1 -1
- data/lib/karafka/routing/features/dead_letter_queue/contract.rb +1 -1
- data/lib/karafka/routing/features/manual_offset_management/contract.rb +1 -1
- data/lib/karafka/server.rb +14 -14
- data/lib/karafka/setup/config.rb +15 -2
- data/lib/karafka/status.rb +27 -9
- data/lib/karafka/templates/karafka.rb.erb +1 -2
- data/lib/karafka/time_trackers/pause.rb +3 -1
- data/lib/karafka/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +16 -7
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 25eb837923f78f1bf35402bf24469228d8f5af12090b2d406718a0077ce42598
|
4
|
+
data.tar.gz: 23520ecab430080061046e683c0dcb47316d1216d1ad9843894caefff76e24cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e84c4c4dedd7a160ebcbd6cff53e0dfcf601a31eb19469d1a86eabb3f33507f3b1871c8f4489b743651118ed47e52925f12dba4fc67e462bd8be04d71dfa3bb
|
7
|
+
data.tar.gz: 8b9754f5566c5ef213c4803cfba2a4263553a5112e23fd12e42a963fd493f8f20c1409b12303628519ba7ef5bcf07aa09fabc6dd4ffc2a2114a6bad8f94cbc72
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.github/workflows/ci.yml
CHANGED
@@ -46,6 +46,7 @@ jobs:
|
|
46
46
|
run: \curl -sSL https://api.coditsu.io/run/ci | bash
|
47
47
|
|
48
48
|
specs:
|
49
|
+
timeout-minutes: 30
|
49
50
|
runs-on: ubuntu-latest
|
50
51
|
needs: diffend
|
51
52
|
strategy:
|
@@ -84,6 +85,7 @@ jobs:
|
|
84
85
|
run: bin/rspecs
|
85
86
|
|
86
87
|
integrations:
|
88
|
+
timeout-minutes: 30
|
87
89
|
runs-on: ubuntu-latest
|
88
90
|
needs: diffend
|
89
91
|
strategy:
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,36 @@
|
|
1
1
|
# Karafka framework changelog
|
2
2
|
|
3
|
+
## 2.0.24 (2022-12-19)
|
4
|
+
- **[Feature]** Provide out of the box encryption support for Pro.
|
5
|
+
- [Improvement] Add instrumentation upon `#pause`.
|
6
|
+
- [Improvement] Add instrumentation upon retries.
|
7
|
+
- [Improvement] Assign `#id` to consumers similar to other entities for ease of debugging.
|
8
|
+
- [Improvement] Add retries and pausing to the default `LoggerListener`.
|
9
|
+
- [Improvement] Introduce a new final `terminated` state that will kick in prior to exit but after all the instrumentation and other things are done.
|
10
|
+
- [Improvement] Ensure that state transitions are thread-safe and ensure state transitions can occur in one direction.
|
11
|
+
- [Improvement] Optimize status methods proxying to `Karafka::App`.
|
12
|
+
- [Improvement] Allow for easier state usage by introducing explicit `#to_s` for reporting.
|
13
|
+
- [Improvement] Change auto-generated id from `SecureRandom#uuid` to `SecureRandom#hex(6)`
|
14
|
+
- [Improvement] Emit statistic every 5 seconds by default.
|
15
|
+
- [Improvement] Introduce general messages parser that can be swapped when needed.
|
16
|
+
- [Fix] Do not trigger code reloading when `consumer_persistence` is enabled.
|
17
|
+
- [Fix] Shutdown producer after all the consumer components are down and the status is stopped. This will ensure, that any instrumentation related Kafka messaging can still operate.
|
18
|
+
|
19
|
+
### Upgrade notes
|
20
|
+
|
21
|
+
If you want to disable `librdkafka` statistics because you do not use them at all, update the `kafka` `statistics.interval.ms` setting and set it to `0`:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
class KarafkaApp < Karafka::App
|
25
|
+
setup do |config|
|
26
|
+
# Other settings...
|
27
|
+
config.kafka = {
|
28
|
+
'statistics.interval.ms': 0
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
3
34
|
## 2.0.23 (2022-12-07)
|
4
35
|
- [Maintenance] Align with `waterdrop` and `karafka-core`
|
5
36
|
- [Improvement] Provide `Admin#read_topic` API to get topic data without subscribing.
|
@@ -425,7 +456,7 @@ There are several things in the plan already for 2.1 and beyond, including a web
|
|
425
456
|
- Small integration specs refactoring + specs for pausing scenarios
|
426
457
|
|
427
458
|
## 2.0.0-alpha6 (2022-04-17)
|
428
|
-
- Fix a bug, where upon missing boot file and Rails, railtie would fail with a generic exception (#818)
|
459
|
+
- Fix a bug, where upon missing boot file and Rails, railtie would fail with a generic exception (#818)
|
429
460
|
- Fix an issue with parallel pristine specs colliding with each other during `bundle install` (#820)
|
430
461
|
- Replace `consumer.consume` with `consumer.consumed` event to match the behaviour
|
431
462
|
- Make sure, that offset committing happens before the `consumer.consumed` event is propagated
|
data/Gemfile.lock
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
karafka (2.0.
|
5
|
-
karafka-core (>= 2.0.
|
4
|
+
karafka (2.0.24)
|
5
|
+
karafka-core (>= 2.0.7, < 3.0.0)
|
6
6
|
thor (>= 0.20)
|
7
|
-
waterdrop (>= 2.4.
|
7
|
+
waterdrop (>= 2.4.7, < 3.0.0)
|
8
8
|
zeitwerk (~> 2.3)
|
9
9
|
|
10
10
|
GEM
|
@@ -29,7 +29,7 @@ GEM
|
|
29
29
|
activesupport (>= 5.0)
|
30
30
|
i18n (1.12.0)
|
31
31
|
concurrent-ruby (~> 1.0)
|
32
|
-
karafka-core (2.0.
|
32
|
+
karafka-core (2.0.7)
|
33
33
|
concurrent-ruby (>= 1.1)
|
34
34
|
rdkafka (>= 0.12)
|
35
35
|
mini_portile2 (2.8.0)
|
@@ -48,7 +48,7 @@ GEM
|
|
48
48
|
rspec-expectations (3.12.0)
|
49
49
|
diff-lcs (>= 1.2.0, < 2.0)
|
50
50
|
rspec-support (~> 3.12.0)
|
51
|
-
rspec-mocks (3.12.
|
51
|
+
rspec-mocks (3.12.1)
|
52
52
|
diff-lcs (>= 1.2.0, < 2.0)
|
53
53
|
rspec-support (~> 3.12.0)
|
54
54
|
rspec-support (3.12.0)
|
@@ -61,12 +61,13 @@ GEM
|
|
61
61
|
thor (1.2.1)
|
62
62
|
tzinfo (2.0.5)
|
63
63
|
concurrent-ruby (~> 1.0)
|
64
|
-
waterdrop (2.4.
|
65
|
-
karafka-core (>= 2.0.
|
64
|
+
waterdrop (2.4.7)
|
65
|
+
karafka-core (>= 2.0.7, < 3.0.0)
|
66
66
|
zeitwerk (~> 2.3)
|
67
67
|
zeitwerk (2.6.6)
|
68
68
|
|
69
69
|
PLATFORMS
|
70
|
+
x86_64-darwin-21
|
70
71
|
x86_64-linux
|
71
72
|
|
72
73
|
DEPENDENCIES
|
data/README.md
CHANGED
@@ -72,10 +72,10 @@ Karafka.producer.produce_sync(topic: 'example', payload: { 'ping' => 'pong' }.to
|
|
72
72
|
```bash
|
73
73
|
bundle exec karafka server
|
74
74
|
|
75
|
-
[
|
76
|
-
[
|
75
|
+
[86d47f0b92f7] Polled 1 message in 1000ms
|
76
|
+
[3732873c8a74] Consume job for ExampleConsumer on example started
|
77
77
|
{"ping"=>"pong"}
|
78
|
-
[
|
78
|
+
[3732873c8a74] Consume job for ExampleConsumer on example finished in 0ms
|
79
79
|
```
|
80
80
|
|
81
81
|
## Want to Upgrade? LGPL is not for you? Want to help?
|
@@ -63,7 +63,7 @@ en:
|
|
63
63
|
|
64
64
|
pro_topic:
|
65
65
|
virtual_partitions.partitioner_respond_to_call: needs to be defined and needs to respond to `#call`
|
66
|
-
virtual_partitions.max_partitions_format: needs to be
|
66
|
+
virtual_partitions.max_partitions_format: needs to be equal or more than 1
|
67
67
|
manual_offset_management_not_with_virtual_partitions: cannot be used together with Virtual Partitions
|
68
68
|
long_running_job.active_format: needs to be either true or false
|
69
69
|
dead_letter_queue_not_with_virtual_partitions: cannot be used together with Virtual Partitions
|
@@ -0,0 +1,18 @@
|
|
1
|
+
en:
|
2
|
+
validations:
|
3
|
+
topic:
|
4
|
+
virtual_partitions.partitioner_respond_to_call: needs to be defined and needs to respond to `#call`
|
5
|
+
virtual_partitions.max_partitions_format: needs to be equal or more than 1
|
6
|
+
manual_offset_management_not_with_virtual_partitions: cannot be used together with Virtual Partitions
|
7
|
+
long_running_job.active_format: needs to be either true or false
|
8
|
+
dead_letter_queue_not_with_virtual_partitions: cannot be used together with Virtual Partitions
|
9
|
+
|
10
|
+
config:
|
11
|
+
encryption.active_format: 'needs to be either true or false'
|
12
|
+
encryption.public_key_invalid: 'is not a valid public RSA key'
|
13
|
+
encryption.public_key_needs_to_be_public: 'is a private RSA key not a public one'
|
14
|
+
encryption.private_keys_format: 'needs to be a hash of version and private key value'
|
15
|
+
encryption.private_keys_need_to_be_private: 'all keys need to be private'
|
16
|
+
encryption.version_format: must be a non-empty string
|
17
|
+
encryption.public_key_format: 'is not a valid public RSA key'
|
18
|
+
encryption.private_keys_invalid: 'contains an invalid private RSA key string'
|
data/docker-compose.yml
CHANGED
@@ -3,8 +3,10 @@ services:
|
|
3
3
|
zookeeper:
|
4
4
|
container_name: karafka_20_zookeeper
|
5
5
|
image: wurstmeister/zookeeper
|
6
|
+
restart: on-failure
|
6
7
|
ports:
|
7
8
|
- '2181:2181'
|
9
|
+
|
8
10
|
kafka:
|
9
11
|
container_name: karafka_20_kafka
|
10
12
|
image: wurstmeister/kafka
|
@@ -22,3 +24,4 @@ services:
|
|
22
24
|
benchmarks_00_10:10:1"
|
23
25
|
volumes:
|
24
26
|
- /var/run/docker.sock:/var/run/docker.sock
|
27
|
+
restart: on-failure
|
data/karafka.gemspec
CHANGED
@@ -21,9 +21,9 @@ Gem::Specification.new do |spec|
|
|
21
21
|
without having to focus on things that are not your business domain.
|
22
22
|
DESC
|
23
23
|
|
24
|
-
spec.add_dependency 'karafka-core', '>= 2.0.
|
24
|
+
spec.add_dependency 'karafka-core', '>= 2.0.7', '< 3.0.0'
|
25
25
|
spec.add_dependency 'thor', '>= 0.20'
|
26
|
-
spec.add_dependency 'waterdrop', '>= 2.4.
|
26
|
+
spec.add_dependency 'waterdrop', '>= 2.4.7', '< 3.0.0'
|
27
27
|
spec.add_dependency 'zeitwerk', '~> 2.3'
|
28
28
|
|
29
29
|
spec.required_ruby_version = '>= 2.7.0'
|
@@ -10,7 +10,7 @@ module Karafka
|
|
10
10
|
configure do |config|
|
11
11
|
config.error_messages = YAML.safe_load(
|
12
12
|
File.read(
|
13
|
-
File.join(Karafka.gem_root, 'config', 'errors.yml')
|
13
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'errors.yml')
|
14
14
|
)
|
15
15
|
).fetch('en').fetch('validations').fetch('job_options')
|
16
16
|
end
|
data/lib/karafka/admin.rb
CHANGED
@@ -116,8 +116,7 @@ module Karafka
|
|
116
116
|
# Creates admin instance and yields it. After usage it closes the admin instance
|
117
117
|
def with_admin
|
118
118
|
admin = config(:producer).admin
|
119
|
-
|
120
|
-
result
|
119
|
+
yield(admin)
|
121
120
|
ensure
|
122
121
|
admin&.close
|
123
122
|
end
|
@@ -125,8 +124,7 @@ module Karafka
|
|
125
124
|
# Creates consumer instance and yields it. After usage it closes the consumer instance
|
126
125
|
def with_consumer
|
127
126
|
consumer = config(:consumer).consumer
|
128
|
-
|
129
|
-
result
|
127
|
+
yield(consumer)
|
130
128
|
ensure
|
131
129
|
consumer&.close
|
132
130
|
end
|
data/lib/karafka/app.rb
CHANGED
@@ -35,10 +35,21 @@ module Karafka
|
|
35
35
|
# Just a nicer name for the consumer groups
|
36
36
|
alias routes consumer_groups
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
# Allow for easier status management via `Karafka::App` by aliasing status methods here
|
39
|
+
Status::STATES.each do |state, transition|
|
40
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
41
|
+
def #{state}
|
42
|
+
App.config.internal.status.#{state}
|
43
|
+
end
|
44
|
+
|
45
|
+
def #{state}?
|
46
|
+
App.config.internal.status.#{state}?
|
47
|
+
end
|
48
|
+
|
49
|
+
def #{transition}
|
50
|
+
App.config.internal.status.#{transition}
|
51
|
+
end
|
52
|
+
RUBY
|
42
53
|
end
|
43
54
|
|
44
55
|
# Methods that should be delegated to Karafka module
|
@@ -4,6 +4,8 @@
|
|
4
4
|
module Karafka
|
5
5
|
# Base consumer from which all Karafka consumers should inherit
|
6
6
|
class BaseConsumer
|
7
|
+
# @return [String] id of the current consumer
|
8
|
+
attr_reader :id
|
7
9
|
# @return [Karafka::Routing::Topic] topic to which a given consumer is subscribed
|
8
10
|
attr_accessor :topic
|
9
11
|
# @return [Karafka::Messages::Messages] current messages batch
|
@@ -15,6 +17,11 @@ module Karafka
|
|
15
17
|
# @return [Waterdrop::Producer] producer instance
|
16
18
|
attr_accessor :producer
|
17
19
|
|
20
|
+
# Creates new consumer and assigns it an id
|
21
|
+
def initialize
|
22
|
+
@id = SecureRandom.hex(6)
|
23
|
+
end
|
24
|
+
|
18
25
|
# Can be used to run preparation code prior to the job being enqueued
|
19
26
|
#
|
20
27
|
# @private
|
@@ -204,6 +211,17 @@ module Karafka
|
|
204
211
|
|
205
212
|
# Indicate, that user took a manual action of pausing
|
206
213
|
coordinator.manual_pause if manual_pause
|
214
|
+
|
215
|
+
Karafka.monitor.instrument(
|
216
|
+
'consumer.consuming.pause',
|
217
|
+
caller: self,
|
218
|
+
manual: manual_pause,
|
219
|
+
topic: messages.metadata.topic,
|
220
|
+
partition: messages.metadata.partition,
|
221
|
+
offset: offset,
|
222
|
+
timeout: coordinator.pause_tracker.current_timeout,
|
223
|
+
attempt: coordinator.pause_tracker.attempt
|
224
|
+
)
|
207
225
|
end
|
208
226
|
|
209
227
|
# Resumes processing of the current topic partition
|
@@ -232,5 +250,23 @@ module Karafka
|
|
232
250
|
def revoked?
|
233
251
|
coordinator.revoked?
|
234
252
|
end
|
253
|
+
|
254
|
+
# Pauses the processing from the last offset to retry on given message
|
255
|
+
# @private
|
256
|
+
def retry_after_pause
|
257
|
+
pause(coordinator.seek_offset, nil, false)
|
258
|
+
|
259
|
+
# Instrumentation needs to run **after** `#pause` invocation because we rely on the states
|
260
|
+
# set by `#pause`
|
261
|
+
Karafka.monitor.instrument(
|
262
|
+
'consumer.consuming.retry',
|
263
|
+
caller: self,
|
264
|
+
topic: messages.metadata.topic,
|
265
|
+
partition: messages.metadata.partition,
|
266
|
+
offset: coordinator.seek_offset,
|
267
|
+
timeout: coordinator.pause_tracker.current_timeout,
|
268
|
+
attempt: coordinator.pause_tracker.attempt
|
269
|
+
)
|
270
|
+
end
|
235
271
|
end
|
236
272
|
end
|
@@ -21,7 +21,7 @@ module Karafka
|
|
21
21
|
def initialize(consumer_group_coordinator, subscription_group, jobs_queue)
|
22
22
|
proc_config = ::Karafka::App.config.internal.processing
|
23
23
|
|
24
|
-
@id = SecureRandom.
|
24
|
+
@id = SecureRandom.hex(6)
|
25
25
|
@consumer_group_coordinator = consumer_group_coordinator
|
26
26
|
@subscription_group = subscription_group
|
27
27
|
@jobs_queue = jobs_queue
|
@@ -12,7 +12,7 @@ module Karafka
|
|
12
12
|
configure do |config|
|
13
13
|
config.error_messages = YAML.safe_load(
|
14
14
|
File.read(
|
15
|
-
File.join(Karafka.gem_root, 'config', 'errors.yml')
|
15
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'errors.yml')
|
16
16
|
)
|
17
17
|
).fetch('en').fetch('validations').fetch('config')
|
18
18
|
end
|
@@ -7,7 +7,7 @@ module Karafka
|
|
7
7
|
configure do |config|
|
8
8
|
config.error_messages = YAML.safe_load(
|
9
9
|
File.read(
|
10
|
-
File.join(Karafka.gem_root, 'config', 'errors.yml')
|
10
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'errors.yml')
|
11
11
|
)
|
12
12
|
).fetch('en').fetch('validations').fetch('consumer_group')
|
13
13
|
end
|
@@ -7,7 +7,7 @@ module Karafka
|
|
7
7
|
configure do |config|
|
8
8
|
config.error_messages = YAML.safe_load(
|
9
9
|
File.read(
|
10
|
-
File.join(Karafka.gem_root, 'config', 'errors.yml')
|
10
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'errors.yml')
|
11
11
|
)
|
12
12
|
).fetch('en').fetch('validations').fetch('server_cli_options')
|
13
13
|
end
|
@@ -7,7 +7,7 @@ module Karafka
|
|
7
7
|
configure do |config|
|
8
8
|
config.error_messages = YAML.safe_load(
|
9
9
|
File.read(
|
10
|
-
File.join(Karafka.gem_root, 'config', 'errors.yml')
|
10
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'errors.yml')
|
11
11
|
)
|
12
12
|
).fetch('en').fetch('validations').fetch('topic')
|
13
13
|
end
|
@@ -63,6 +63,38 @@ module Karafka
|
|
63
63
|
info "[#{job.id}] #{job_type} job for #{consumer} on #{topic} finished in #{time}ms"
|
64
64
|
end
|
65
65
|
|
66
|
+
# Prints info about a pause occurrence. Irrelevant if user or system initiated.
|
67
|
+
#
|
68
|
+
# @param event [Karafka::Core::Monitoring::Event] event details including payload
|
69
|
+
def on_consumer_consuming_pause(event)
|
70
|
+
topic = event[:topic]
|
71
|
+
partition = event[:partition]
|
72
|
+
offset = event[:offset]
|
73
|
+
consumer = event[:caller]
|
74
|
+
timeout = event[:timeout]
|
75
|
+
|
76
|
+
info <<~MSG.tr("\n", ' ').strip!
|
77
|
+
[#{consumer.id}] Pausing partition #{partition} of topic #{topic}
|
78
|
+
on offset #{offset} for #{timeout} ms.
|
79
|
+
MSG
|
80
|
+
end
|
81
|
+
|
82
|
+
# Prints info about retry of processing after an error
|
83
|
+
#
|
84
|
+
# @param event [Karafka::Core::Monitoring::Event] event details including payload
|
85
|
+
def on_consumer_consuming_retry(event)
|
86
|
+
topic = event[:topic]
|
87
|
+
partition = event[:partition]
|
88
|
+
offset = event[:offset]
|
89
|
+
consumer = event[:caller]
|
90
|
+
timeout = event[:timeout]
|
91
|
+
|
92
|
+
info <<~MSG.tr("\n", ' ').strip!
|
93
|
+
[#{consumer.id}] Retrying of #{consumer.class} after #{timeout} ms
|
94
|
+
on partition #{partition} of topic #{topic} from offset #{offset}
|
95
|
+
MSG
|
96
|
+
end
|
97
|
+
|
66
98
|
# Logs info about system signals that Karafka received and prints backtrace for threads in
|
67
99
|
# case of ttin
|
68
100
|
#
|
@@ -9,7 +9,19 @@ module Karafka
|
|
9
9
|
class Message
|
10
10
|
extend Forwardable
|
11
11
|
|
12
|
-
|
12
|
+
class << self
|
13
|
+
# @return [Object] general parser
|
14
|
+
# @note We cache it here for performance reasons. It is 2.5x times faster than getting it
|
15
|
+
# via the config chain.
|
16
|
+
def parser
|
17
|
+
@parser ||= App.config.internal.messages.parser
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :metadata
|
22
|
+
# raw payload needs to be mutable as we want to have option to change it in the parser
|
23
|
+
# prior to the final deserialization
|
24
|
+
attr_accessor :raw_payload
|
13
25
|
|
14
26
|
def_delegators :metadata, *Metadata.members
|
15
27
|
|
@@ -42,7 +54,7 @@ module Karafka
|
|
42
54
|
|
43
55
|
# @return [Object] deserialized data
|
44
56
|
def deserialize
|
45
|
-
|
57
|
+
self.class.parser.call(self)
|
46
58
|
end
|
47
59
|
end
|
48
60
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Messages
|
5
|
+
# Default message parser. The only thing it does, is calling the deserializer
|
6
|
+
class Parser
|
7
|
+
# @param message [::Karafka::Messages::Message]
|
8
|
+
# @return [Object] deserialized payload
|
9
|
+
def call(message)
|
10
|
+
message.metadata.deserializer.call(message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -20,7 +20,7 @@ module Karafka
|
|
20
20
|
configure do |config|
|
21
21
|
config.error_messages = YAML.safe_load(
|
22
22
|
File.read(
|
23
|
-
File.join(Karafka.gem_root, 'config', 'errors.yml')
|
23
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'errors.yml')
|
24
24
|
)
|
25
25
|
).fetch('en').fetch('validations').fetch('job_options')
|
26
26
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Pro
|
16
|
+
module Encryption
|
17
|
+
# Cipher for encrypting and decrypting data
|
18
|
+
class Cipher
|
19
|
+
def initialize
|
20
|
+
@private_pems = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Encrypts given string content with the public key
|
24
|
+
# @param content [String]
|
25
|
+
# @return [String]
|
26
|
+
def encrypt(content)
|
27
|
+
public_pem.public_encrypt(content)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Decrypts provided content using `version` key
|
31
|
+
# @param version [String] encryption version
|
32
|
+
# @param content [String] encrypted content
|
33
|
+
# @return [String] decrypted content
|
34
|
+
def decrypt(version, content)
|
35
|
+
private_pem(version).private_decrypt(content)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# @return [::OpenSSL::PKey::RSA] rsa public key
|
41
|
+
def public_pem
|
42
|
+
@public_pem ||= ::OpenSSL::PKey::RSA.new(::Karafka::App.config.encryption.public_key)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param version [String] version for which we want to get the rsa key
|
46
|
+
# @return [::OpenSSL::PKey::RSA] rsa private key
|
47
|
+
def private_pem(version)
|
48
|
+
return @private_pems[version] if @private_pems.key?(version)
|
49
|
+
|
50
|
+
key_string = ::Karafka::App.config.encryption.private_keys[version]
|
51
|
+
key_string || raise(Errors::PrivateKeyNotFound, version)
|
52
|
+
|
53
|
+
@private_pems[version] = ::OpenSSL::PKey::RSA.new(key_string)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Pro
|
16
|
+
module Encryption
|
17
|
+
# Encryption related contracts
|
18
|
+
module Contracts
|
19
|
+
# Makes sure, all the expected config is defined as it should be
|
20
|
+
class Config < ::Karafka::Contracts::Base
|
21
|
+
configure do |config|
|
22
|
+
config.error_messages = YAML.safe_load(
|
23
|
+
File.read(
|
24
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
|
25
|
+
)
|
26
|
+
).fetch('en').fetch('validations').fetch('config')
|
27
|
+
end
|
28
|
+
|
29
|
+
nested(:encryption) do
|
30
|
+
required(:active) { |val| [true, false].include?(val) }
|
31
|
+
required(:version) { |val| val.is_a?(String) && !val.empty? }
|
32
|
+
required(:public_key) { |val| val.is_a?(String) }
|
33
|
+
|
34
|
+
required(:private_keys) do |val|
|
35
|
+
val.is_a?(Hash) &&
|
36
|
+
val.keys.all? { |key| key.is_a?(String) } &&
|
37
|
+
val.values.all? { |key| key.is_a?(String) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Public key validation
|
42
|
+
virtual do |data, errors|
|
43
|
+
next unless errors.empty?
|
44
|
+
next unless data.fetch(:encryption).fetch(:active)
|
45
|
+
|
46
|
+
key = OpenSSL::PKey::RSA.new(data.fetch(:encryption).fetch(:public_key))
|
47
|
+
|
48
|
+
next unless key.private?
|
49
|
+
|
50
|
+
[[%i[encryption public_key], :needs_to_be_public]]
|
51
|
+
rescue OpenSSL::PKey::RSAError
|
52
|
+
[[%i[encryption public_key], :invalid]]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Private keys validation
|
56
|
+
virtual do |data, errors|
|
57
|
+
next unless errors.empty?
|
58
|
+
next unless data.fetch(:encryption).fetch(:active)
|
59
|
+
|
60
|
+
private_keys = data.fetch(:encryption).fetch(:private_keys)
|
61
|
+
|
62
|
+
# Keys may be empty for production only envs
|
63
|
+
next if private_keys.empty?
|
64
|
+
|
65
|
+
keys = private_keys.each_value.map do |key|
|
66
|
+
OpenSSL::PKey::RSA.new(key)
|
67
|
+
end
|
68
|
+
|
69
|
+
next if keys.all?(&:private?)
|
70
|
+
|
71
|
+
[[%i[encryption private_keys], :need_to_be_private]]
|
72
|
+
rescue OpenSSL::PKey::RSAError
|
73
|
+
[[%i[encryption private_keys], :invalid]]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Pro
|
16
|
+
module Encryption
|
17
|
+
# Encryption related errors
|
18
|
+
module Errors
|
19
|
+
# Raised when we have encountered encryption key with version we do not have
|
20
|
+
PrivateKeyNotFound = Class.new(::Karafka::Errors::BaseError)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|