sbmt-kafka_consumer 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +34 -0
- data/Appraisals +23 -0
- data/CHANGELOG.md +292 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +296 -0
- data/Rakefile +12 -0
- data/config.ru +9 -0
- data/dip.yml +84 -0
- data/docker-compose.yml +68 -0
- data/exe/kafka_consumer +16 -0
- data/lefthook-local.dip_example.yml +4 -0
- data/lefthook.yml +6 -0
- data/lib/generators/kafka_consumer/concerns/configuration.rb +30 -0
- data/lib/generators/kafka_consumer/consumer/USAGE +24 -0
- data/lib/generators/kafka_consumer/consumer/consumer_generator.rb +41 -0
- data/lib/generators/kafka_consumer/consumer/templates/consumer.rb.erb +9 -0
- data/lib/generators/kafka_consumer/consumer/templates/consumer_group.yml.erb +13 -0
- data/lib/generators/kafka_consumer/inbox_consumer/USAGE +22 -0
- data/lib/generators/kafka_consumer/inbox_consumer/inbox_consumer_generator.rb +48 -0
- data/lib/generators/kafka_consumer/inbox_consumer/templates/consumer_group.yml.erb +22 -0
- data/lib/generators/kafka_consumer/install/USAGE +9 -0
- data/lib/generators/kafka_consumer/install/install_generator.rb +22 -0
- data/lib/generators/kafka_consumer/install/templates/Kafkafile +3 -0
- data/lib/generators/kafka_consumer/install/templates/kafka_consumer.yml +59 -0
- data/lib/sbmt/kafka_consumer/app_initializer.rb +13 -0
- data/lib/sbmt/kafka_consumer/base_consumer.rb +104 -0
- data/lib/sbmt/kafka_consumer/cli.rb +55 -0
- data/lib/sbmt/kafka_consumer/client_configurer.rb +73 -0
- data/lib/sbmt/kafka_consumer/config/auth.rb +56 -0
- data/lib/sbmt/kafka_consumer/config/consumer.rb +16 -0
- data/lib/sbmt/kafka_consumer/config/consumer_group.rb +9 -0
- data/lib/sbmt/kafka_consumer/config/deserializer.rb +15 -0
- data/lib/sbmt/kafka_consumer/config/kafka.rb +32 -0
- data/lib/sbmt/kafka_consumer/config/metrics.rb +10 -0
- data/lib/sbmt/kafka_consumer/config/probes/endpoints.rb +13 -0
- data/lib/sbmt/kafka_consumer/config/probes/liveness_probe.rb +11 -0
- data/lib/sbmt/kafka_consumer/config/probes/readiness_probe.rb +10 -0
- data/lib/sbmt/kafka_consumer/config/probes.rb +8 -0
- data/lib/sbmt/kafka_consumer/config/topic.rb +14 -0
- data/lib/sbmt/kafka_consumer/config.rb +76 -0
- data/lib/sbmt/kafka_consumer/inbox_consumer.rb +129 -0
- data/lib/sbmt/kafka_consumer/instrumentation/base_monitor.rb +25 -0
- data/lib/sbmt/kafka_consumer/instrumentation/chainable_monitor.rb +31 -0
- data/lib/sbmt/kafka_consumer/instrumentation/listener_helper.rb +47 -0
- data/lib/sbmt/kafka_consumer/instrumentation/liveness_listener.rb +71 -0
- data/lib/sbmt/kafka_consumer/instrumentation/logger_listener.rb +44 -0
- data/lib/sbmt/kafka_consumer/instrumentation/open_telemetry_loader.rb +23 -0
- data/lib/sbmt/kafka_consumer/instrumentation/open_telemetry_tracer.rb +106 -0
- data/lib/sbmt/kafka_consumer/instrumentation/readiness_listener.rb +38 -0
- data/lib/sbmt/kafka_consumer/instrumentation/sentry_tracer.rb +103 -0
- data/lib/sbmt/kafka_consumer/instrumentation/tracer.rb +18 -0
- data/lib/sbmt/kafka_consumer/instrumentation/tracing_monitor.rb +17 -0
- data/lib/sbmt/kafka_consumer/instrumentation/yabeda_metrics_listener.rb +186 -0
- data/lib/sbmt/kafka_consumer/probes/host.rb +75 -0
- data/lib/sbmt/kafka_consumer/probes/probe.rb +33 -0
- data/lib/sbmt/kafka_consumer/railtie.rb +31 -0
- data/lib/sbmt/kafka_consumer/routing/karafka_v1_consumer_mapper.rb +12 -0
- data/lib/sbmt/kafka_consumer/routing/karafka_v2_consumer_mapper.rb +9 -0
- data/lib/sbmt/kafka_consumer/serialization/base_deserializer.rb +19 -0
- data/lib/sbmt/kafka_consumer/serialization/json_deserializer.rb +18 -0
- data/lib/sbmt/kafka_consumer/serialization/null_deserializer.rb +13 -0
- data/lib/sbmt/kafka_consumer/serialization/protobuf_deserializer.rb +27 -0
- data/lib/sbmt/kafka_consumer/server.rb +35 -0
- data/lib/sbmt/kafka_consumer/simple_logging_consumer.rb +11 -0
- data/lib/sbmt/kafka_consumer/testing/shared_contexts/with_sbmt_karafka_consumer.rb +61 -0
- data/lib/sbmt/kafka_consumer/testing.rb +5 -0
- data/lib/sbmt/kafka_consumer/types.rb +15 -0
- data/lib/sbmt/kafka_consumer/version.rb +7 -0
- data/lib/sbmt/kafka_consumer/yabeda_configurer.rb +91 -0
- data/lib/sbmt/kafka_consumer.rb +59 -0
- data/rubocop/rspec.yml +29 -0
- data/sbmt-kafka_consumer.gemspec +70 -0
- metadata +571 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fe979c0a187c1aac9f2f8d571d99801e564912db57b86c8219b569fc3faef5c1
|
4
|
+
data.tar.gz: af13a117d78170019ee3f0ae0930c5b65c0dd027efa39a46eb51f1a32998f47b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7105c49b6c2ecf06769bb310c9a4bf836aa5cbad1b2ee994860b814b71059b8217610429dada55b408063597e32893b1efb404be11902d22693b37e4233ddb18
|
7
|
+
data.tar.gz: 2a6195f0db6b8a0a7f9435e6b93745422a97f2238c073598155b0c2d81212891028a67db9029160735754189610a3ab4687c433044c67bf9d6d2b6802bdd1149
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
inherit_mode:
|
2
|
+
merge:
|
3
|
+
- Exclude
|
4
|
+
|
5
|
+
require:
|
6
|
+
- rubocop-performance
|
7
|
+
- rubocop-rails
|
8
|
+
- rubocop-rspec
|
9
|
+
- standard
|
10
|
+
|
11
|
+
inherit_gem:
|
12
|
+
standard: config/base.yml
|
13
|
+
|
14
|
+
inherit_from:
|
15
|
+
- rubocop/rspec.yml
|
16
|
+
|
17
|
+
AllCops:
|
18
|
+
NewCops: enable
|
19
|
+
SuggestExtensions: false
|
20
|
+
TargetRubyVersion: 2.7
|
21
|
+
TargetRailsVersion: 5.2
|
22
|
+
|
23
|
+
RSpec/FilePath:
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
RSpec/VerifiedDoubles:
|
27
|
+
Exclude:
|
28
|
+
- spec/**/*_spec.rb
|
29
|
+
|
30
|
+
Style/SingleLineMethods:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
Style/EmptyMethod:
|
34
|
+
Enabled: false
|
data/Appraisals
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# See compatibility table at https://www.fastruby.io/blog/ruby/rails/versions/compatibility-table.html
|
4
|
+
|
5
|
+
versions_map = {
|
6
|
+
"5.2" => %w[2.7],
|
7
|
+
"6.0" => %w[2.7],
|
8
|
+
"6.1" => %w[2.7 3.0],
|
9
|
+
"7.0" => %w[3.1],
|
10
|
+
"7.1" => %w[3.2]
|
11
|
+
}
|
12
|
+
|
13
|
+
current_ruby_version = RUBY_VERSION.split(".").first(2).join(".")
|
14
|
+
|
15
|
+
versions_map.each do |rails_version, ruby_versions|
|
16
|
+
ruby_versions.each do |ruby_version|
|
17
|
+
next if ruby_version != current_ruby_version
|
18
|
+
|
19
|
+
appraise "rails-#{rails_version}" do
|
20
|
+
gem "rails", "~> #{rails_version}.0"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,292 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
6
|
+
and this project adheres to [Semantic Versioning](http://semver.org/).
|
7
|
+
|
8
|
+
## [Unreleased] - yyyy-mm-dd
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
|
16
|
+
## [2.0.0] - 2024-01-30
|
17
|
+
|
18
|
+
### Changed
|
19
|
+
|
20
|
+
- Remove `sbmt-dev`
|
21
|
+
|
22
|
+
## [1.0.0] - 2024-01-12
|
23
|
+
|
24
|
+
### Added
|
25
|
+
|
26
|
+
- Use mainstream karafka instead of custom fork
|
27
|
+
|
28
|
+
## [0.23.0] - 2024-01-12
|
29
|
+
|
30
|
+
### Added
|
31
|
+
|
32
|
+
- ability to override `kafka_options` for topic
|
33
|
+
|
34
|
+
## [0.22.0] - 2024-01-09
|
35
|
+
|
36
|
+
### Added
|
37
|
+
|
38
|
+
- removed useless `outbox_producer` param for `InboxConsumer` class
|
39
|
+
- removed useless log messages from `InboxConsumer` class
|
40
|
+
|
41
|
+
## [0.21.0] - 2024-01-09
|
42
|
+
|
43
|
+
### Fixed
|
44
|
+
|
45
|
+
- initialization of proxy consumer classes
|
46
|
+
- consumer class name in sentry's transaction name
|
47
|
+
|
48
|
+
## [0.20.0] - 2024-01-09
|
49
|
+
|
50
|
+
### Added
|
51
|
+
|
52
|
+
- New config options `metrics`
|
53
|
+
- `metrics.port` for a metrics port that is different from the probes port
|
54
|
+
- `metrics.path` for a metrics path
|
55
|
+
|
56
|
+
## [0.19.2] - 2023-10-18
|
57
|
+
|
58
|
+
### Fixed
|
59
|
+
|
60
|
+
- Stub kafka_client to prevent calls to librdkafka: fixes SEGFAULT in parallel tests
|
61
|
+
|
62
|
+
## [0.19.1] - 2023-10-05
|
63
|
+
|
64
|
+
### Fixed
|
65
|
+
|
66
|
+
- disable karafka's `config.strict_topics_namespacing`
|
67
|
+
|
68
|
+
## [0.19.0] - 2023-09-29
|
69
|
+
|
70
|
+
### Added
|
71
|
+
|
72
|
+
- `outbox_producer` configuration flag
|
73
|
+
|
74
|
+
## [0.18.4] - 2023-09-26
|
75
|
+
|
76
|
+
### Fixed
|
77
|
+
|
78
|
+
- Use `Rails.application.executor.wrap` instead manual AR connection clearing
|
79
|
+
|
80
|
+
## [0.18.3] - 2023-09-15
|
81
|
+
|
82
|
+
### Fixed
|
83
|
+
|
84
|
+
- Fix broken outbox item generator call in the `kafka_consumer:inbox_consumer` generator
|
85
|
+
|
86
|
+
## [0.18.2] - 2023-09-14
|
87
|
+
|
88
|
+
### Fixed
|
89
|
+
|
90
|
+
- Properly extract opentelemetry context from kafka message headers
|
91
|
+
|
92
|
+
## [0.18.1] - 2023-09-13
|
93
|
+
|
94
|
+
### Fixed
|
95
|
+
|
96
|
+
- Port `v0.17.5` (properly clear `ActiveRecord` connections in case `skip_on_error` option is used) to master (v0.18)
|
97
|
+
|
98
|
+
## [0.18.0] - 2023-09-11
|
99
|
+
|
100
|
+
### Added
|
101
|
+
|
102
|
+
- OpenTelemetry tracing
|
103
|
+
|
104
|
+
## [0.17.5] - 2023-09-13
|
105
|
+
|
106
|
+
### Fixed
|
107
|
+
|
108
|
+
- Properly clear `ActiveRecord` connections in case `skip_on_error` option is used
|
109
|
+
|
110
|
+
## [0.17.4] - 2023-09-05
|
111
|
+
|
112
|
+
### Fixed
|
113
|
+
|
114
|
+
- Latency metrics in seconds instead ms
|
115
|
+
|
116
|
+
## [0.17.3] - 2023-08-31
|
117
|
+
|
118
|
+
### Fixed
|
119
|
+
|
120
|
+
- Decreased sleep time on db error in a consumer
|
121
|
+
|
122
|
+
## [0.17.2] - 2023-08-16
|
123
|
+
|
124
|
+
### Fixed
|
125
|
+
|
126
|
+
- Fix `message.metadata.key` validation if key is an empty string
|
127
|
+
|
128
|
+
## [0.17.1] - 2023-08-08
|
129
|
+
|
130
|
+
### Fixed
|
131
|
+
|
132
|
+
- Check Idempotency-Key for a empty string
|
133
|
+
|
134
|
+
## [0.17.0] - 2023-08-07
|
135
|
+
|
136
|
+
### Added
|
137
|
+
|
138
|
+
- ability to configure consumer group mapper in `kafka_consumer.yml` (needed for proper migration from existing karafka v2 based consumers)
|
139
|
+
- ability to define/override inbox-item attributes in InboxConsumer
|
140
|
+
|
141
|
+
### Fixed
|
142
|
+
- report `kafka_consumer_inbox_consumes` metric with tag `status = skipped` (instead `failure`) if skip_on_error is enabled on InboxConsumer
|
143
|
+
|
144
|
+
## [0.16.0] - 2023-07-27
|
145
|
+
|
146
|
+
### Added
|
147
|
+
|
148
|
+
- additional tags (client, group_id, partition, topic) for metric `kafka_consumer_inbox_consumes`
|
149
|
+
|
150
|
+
## [0.15.0] - 2023-07-21
|
151
|
+
|
152
|
+
### Added
|
153
|
+
|
154
|
+
- `kafka_consumer:install` generator
|
155
|
+
- `kafka_consumer:consumer_group` generator
|
156
|
+
- `kafka_consumer:consumer` generator
|
157
|
+
|
158
|
+
## [0.14.2] - 2023-07-19
|
159
|
+
|
160
|
+
### Changed
|
161
|
+
- `.clear_all_connections!` is now called for all DB roles
|
162
|
+
|
163
|
+
## [0.14.1] - yyyy-mm-dd
|
164
|
+
|
165
|
+
### Added
|
166
|
+
- add label `api` for group `kafka_api`
|
167
|
+
|
168
|
+
### Changed
|
169
|
+
- README improvements
|
170
|
+
|
171
|
+
## [0.14.0] - 2023-07-06
|
172
|
+
|
173
|
+
### Added
|
174
|
+
- report message payload and headers to Sentry if consumer detailed logging is enabled
|
175
|
+
|
176
|
+
## [0.13.1] - 2023-07-05
|
177
|
+
|
178
|
+
### Added
|
179
|
+
- `event_key` callback added to `Sbmt::KafkaConsumer::InboxConsumer`
|
180
|
+
|
181
|
+
## [0.13.0] - 2023-06-20
|
182
|
+
|
183
|
+
### Changed
|
184
|
+
- logging / instrumentation improvements
|
185
|
+
|
186
|
+
## [0.12.0] - 2023-06-20
|
187
|
+
|
188
|
+
### Changed
|
189
|
+
- README improvements
|
190
|
+
- update sbmt-waterdrop (via sbmt-karafka) to fix karafka-rdkafka 0.13 compatibility issue
|
191
|
+
|
192
|
+
## [0.11.0] - 2023-06-13
|
193
|
+
|
194
|
+
### Added
|
195
|
+
- `skip_on_error` consumer option to skip message processing (and commit offsets) if exception was raised
|
196
|
+
|
197
|
+
## [0.10.0] - 2023-06-07
|
198
|
+
|
199
|
+
### Added
|
200
|
+
- `SimpleLoggingConsumer`, which just consumes/logs messages, can be used for debug purposes
|
201
|
+
|
202
|
+
## [0.9.0] - 2023-06-06
|
203
|
+
|
204
|
+
### Changed
|
205
|
+
- add custom `ConsumerMapper` to be consistent with KarafkaV1 consumer-group naming conventions (e.g. karafka v1 uses underscored client-id in consumer group name)
|
206
|
+
- reuse with_db_retry: release ActiveRecord conn everytime after message processing, in case there's a connection-pool degradation
|
207
|
+
|
208
|
+
## [0.8.0] - 2023-06-01
|
209
|
+
|
210
|
+
### Changed
|
211
|
+
- update sbmt-karafka to 2.1.3
|
212
|
+
- remove db retries logic as `ActiveRecord::Base::clear_active_connections!` is already handled by karafka v2 after processing a batch
|
213
|
+
- async metrics reporting for `statistics.emitted` event to prevent rdkafka's main thread hanging, see https://github.com/karafka/karafka/pull/1420/files
|
214
|
+
- use Rails logger by default
|
215
|
+
- use `$stdout.sync = true` in consumer server process to avoid STDOUT buffering issues in docker/k8s
|
216
|
+
|
217
|
+
## [0.7.1] - 2023-05-31
|
218
|
+
|
219
|
+
### Fixed
|
220
|
+
- db error logging in base consumer
|
221
|
+
|
222
|
+
## [0.7.0] - 2023-05-30
|
223
|
+
|
224
|
+
### Added
|
225
|
+
- add `Sbmt::KafkaConsumer::Instrumentation::LivenessListener` and `Sbmt::KafkaConsumer::Instrumentation::ReadinessListener` listeners
|
226
|
+
- add `probes` option
|
227
|
+
- add `HttpHealthCheck` server with probes' endpoints
|
228
|
+
|
229
|
+
## [0.6.1] - 2023-05-30
|
230
|
+
|
231
|
+
### Added
|
232
|
+
- set default `source: "KAFKA"` option when creating `inbox_item` in `InboxConsumer`
|
233
|
+
|
234
|
+
## [0.6.0] - 2023-05-29
|
235
|
+
|
236
|
+
### Added
|
237
|
+
- add `manual_offset_management` topic's option (defaults to true)
|
238
|
+
- add consumer `group_id` to inbox-item metadata (InboxConsumer)
|
239
|
+
|
240
|
+
## [0.5.1] - 2023-05-25
|
241
|
+
|
242
|
+
### Fixed
|
243
|
+
- sentry tracing when instrumentation event is not an exception
|
244
|
+
- payload deserialization if skip_decoding_error is enabled
|
245
|
+
|
246
|
+
## [0.5.0] - 2023-05-23
|
247
|
+
|
248
|
+
### Changed
|
249
|
+
- add default deserializer (NullDeserializer) to config
|
250
|
+
- refactor logging
|
251
|
+
|
252
|
+
## [0.4.0] - 2023-05-19
|
253
|
+
|
254
|
+
### Changed
|
255
|
+
- refactor consumer groups config
|
256
|
+
|
257
|
+
## [0.3.0] - 2023-05-19
|
258
|
+
|
259
|
+
### Added
|
260
|
+
- add timeout aliases to kafka config
|
261
|
+
- README actualization
|
262
|
+
|
263
|
+
## [0.2.0] - 2023-05-16
|
264
|
+
|
265
|
+
### Added
|
266
|
+
- implement consumer metrics
|
267
|
+
|
268
|
+
## [Unreleased] - 2023-05-03
|
269
|
+
|
270
|
+
### Added
|
271
|
+
- base config loader via AnywayConfig
|
272
|
+
|
273
|
+
### Changed
|
274
|
+
|
275
|
+
### Fixed
|
276
|
+
|
277
|
+
## [Unreleased] - 2023-04-26
|
278
|
+
|
279
|
+
### Added
|
280
|
+
- BaseConsumer
|
281
|
+
- InboxConsumer
|
282
|
+
- Instrumentation listeners: sentry, logger, yabeda
|
283
|
+
|
284
|
+
### Changed
|
285
|
+
|
286
|
+
### Fixed
|
287
|
+
|
288
|
+
## [Unreleased]
|
289
|
+
|
290
|
+
## [0.1.0] - 2023-04-19
|
291
|
+
|
292
|
+
- Initial release
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 SberMarket Tech
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,296 @@
|
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/sbmt-kafka_consumer.svg)](https://badge.fury.io/rb/sbmt-kafka_consumer)
|
2
|
+
[![Build Status](https://github.com/SberMarket-Tech/sbmt-kafka_consumer/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/SberMarket-Tech/sbmt-outbox/actions?query=branch%3Amaster)
|
3
|
+
|
4
|
+
# Sbmt-KafkaConsumer
|
5
|
+
|
6
|
+
This gem is used to consume Kafka messages. It is a wrapper over the [Karafka](https://github.com/karafka/karafka) gem, and is recommended for use as a transport with the [sbmt-outbox](https://github.com/SberMarket-Tech/sbmt-outbox) gem.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem "sbmt-kafka_consumer"
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
```bash
|
19
|
+
bundle install
|
20
|
+
```
|
21
|
+
|
22
|
+
## Auto configuration
|
23
|
+
|
24
|
+
We recommend going through the configuration and file creation process using the following Rails generators. Each generator can be run by using the `--help` option to learn more about the available arguments.
|
25
|
+
|
26
|
+
### Initial configuration
|
27
|
+
|
28
|
+
If you plug the gem into your application for the first time, you can generate the initial configuration:
|
29
|
+
|
30
|
+
```shell
|
31
|
+
rails g kafka_consumer:install
|
32
|
+
```
|
33
|
+
|
34
|
+
As the result, the `config/kafka_consumer.yml` file will be created.
|
35
|
+
|
36
|
+
### Consumer class
|
37
|
+
|
38
|
+
A consumer class can be generated with the following command:
|
39
|
+
|
40
|
+
```shell
|
41
|
+
rails g kafka_consumer:consumer MaybeNamespaced::Name
|
42
|
+
```
|
43
|
+
|
44
|
+
### Inbox consumer
|
45
|
+
|
46
|
+
To generate an Inbox consumer for use with gem [sbmt-outbox](https://github.com/SberMarket-Tech/sbmt-outbox), run the following command:
|
47
|
+
|
48
|
+
```shell
|
49
|
+
rails g kafka_consumer:inbox_consumer MaybeNamespaced::Name some-consumer-group some-topic
|
50
|
+
```
|
51
|
+
|
52
|
+
## Manual configuration
|
53
|
+
|
54
|
+
The `config/kafka_consumer.yml` file is a main configuration for the gem.
|
55
|
+
|
56
|
+
Example config with a full set of options:
|
57
|
+
|
58
|
+
```yaml
|
59
|
+
default: &default
|
60
|
+
client_id: "my-app-consumer"
|
61
|
+
concurrency: 4 # max number of threads
|
62
|
+
# optional Karafka options
|
63
|
+
max_wait_time: 1
|
64
|
+
shutdown_timeout: 60
|
65
|
+
pause_timeout: 1
|
66
|
+
pause_max_timeout: 30
|
67
|
+
pause_with_exponential_backoff: true
|
68
|
+
auth:
|
69
|
+
kind: plaintext
|
70
|
+
kafka:
|
71
|
+
servers: "kafka:9092"
|
72
|
+
# optional Kafka options
|
73
|
+
heartbeat_timeout: 5
|
74
|
+
session_timeout: 30
|
75
|
+
reconnect_timeout: 3
|
76
|
+
connect_timeout: 5
|
77
|
+
socket_timeout: 30
|
78
|
+
kafka_options:
|
79
|
+
allow.auto.create.topics: true
|
80
|
+
probes: # optional section
|
81
|
+
port: 9394
|
82
|
+
endpoints:
|
83
|
+
readiness:
|
84
|
+
enabled: true
|
85
|
+
path: "/readiness"
|
86
|
+
liveness:
|
87
|
+
enabled: true
|
88
|
+
path: "/liveness"
|
89
|
+
timeout: 15
|
90
|
+
metrics: # optional section
|
91
|
+
port: 9090
|
92
|
+
path: "/metrics"
|
93
|
+
consumer_groups:
|
94
|
+
group_ref_id_1:
|
95
|
+
name: cg_with_single_topic
|
96
|
+
topics:
|
97
|
+
- name: topic_with_inbox_items
|
98
|
+
consumer:
|
99
|
+
klass: "Sbmt::KafkaConsumer::InboxConsumer"
|
100
|
+
init_attrs:
|
101
|
+
name: "test_items"
|
102
|
+
inbox_item: "TestInboxItem"
|
103
|
+
deserializer:
|
104
|
+
klass: "Sbmt::KafkaConsumer::Serialization::NullDeserializer"
|
105
|
+
kafka_options:
|
106
|
+
auto.offset.reset: latest
|
107
|
+
group_ref_id_2:
|
108
|
+
name: cg_with_multiple_topics
|
109
|
+
topics:
|
110
|
+
- name: topic_with_json_data
|
111
|
+
consumer:
|
112
|
+
klass: "SomeConsumer"
|
113
|
+
deserializer:
|
114
|
+
klass: "Sbmt::KafkaConsumer::Serialization::JsonDeserializer"
|
115
|
+
- name: topic_with_protobuf_data
|
116
|
+
consumer:
|
117
|
+
klass: "SomeConsumer"
|
118
|
+
deserializer:
|
119
|
+
klass: "Sbmt::KafkaConsumer::Serialization::ProtobufDeserializer"
|
120
|
+
init_attrs:
|
121
|
+
message_decoder_klass: "SomeDecoder"
|
122
|
+
skip_decoding_error: true
|
123
|
+
|
124
|
+
development:
|
125
|
+
<<: *default
|
126
|
+
|
127
|
+
test:
|
128
|
+
<<: *default
|
129
|
+
deliver: false
|
130
|
+
|
131
|
+
production:
|
132
|
+
<<: *default
|
133
|
+
```
|
134
|
+
|
135
|
+
### `auth` config section
|
136
|
+
|
137
|
+
The gem supports 2 variants: plaintext (default) and SASL-plaintext
|
138
|
+
|
139
|
+
SASL-plaintext:
|
140
|
+
|
141
|
+
```yaml
|
142
|
+
auth:
|
143
|
+
kind: sasl_plaintext
|
144
|
+
sasl_username: user
|
145
|
+
sasl_password: pwd
|
146
|
+
sasl_mechanism: SCRAM-SHA-512
|
147
|
+
```
|
148
|
+
|
149
|
+
### `kafka` config section
|
150
|
+
|
151
|
+
The `servers` key is required and should be in rdkafka format: without `kafka://` prefix, for example: `srv1:port1,srv2:port2,...`.
|
152
|
+
|
153
|
+
The `kafka_config` section may contain any [rdkafka option](https://github.com/confluentinc/librdkafka/blob/master/CONFIGURATION.md). Also, `kafka_options` may be redefined for each topic.
|
154
|
+
|
155
|
+
### `consumer_groups` config section
|
156
|
+
|
157
|
+
```yaml
|
158
|
+
consumer_groups:
|
159
|
+
# group id can be used when starting a consumer process (see CLI section below)
|
160
|
+
group_id:
|
161
|
+
name: some_group_name # required
|
162
|
+
topics:
|
163
|
+
- name: some_topic_name # required
|
164
|
+
active: true # optional, default true
|
165
|
+
consumer:
|
166
|
+
klass: SomeConsumerClass # required, a consumer class inherited from Sbmt::KafkaConsumer::BaseConsumer
|
167
|
+
init_attrs: # optional, consumer class attributes (see below)
|
168
|
+
key: value
|
169
|
+
deserializer:
|
170
|
+
klass: SomeDeserializerClass # optional, default NullDeserializer, a deserializer class inherited from Sbmt::KafkaConsumer::Serialization::NullDeserializer
|
171
|
+
init_attrs: # optional, deserializer class attributes (see below)
|
172
|
+
key: value
|
173
|
+
kafka_options: # optional, this section allows to redefine the root rdkafka options for each topic
|
174
|
+
auto.offset.reset: latest
|
175
|
+
```
|
176
|
+
|
177
|
+
#### `consumer.init_attrs` options for `BaseConsumer`
|
178
|
+
|
179
|
+
- `skip_on_error` - optional, default false, omit consumer errors in message processing and commit the offset to Kafka
|
180
|
+
|
181
|
+
#### `consumer.init_attrs` options for `InboxConsumer`
|
182
|
+
|
183
|
+
- `inbox_item` - required, name of the inbox item class
|
184
|
+
- `event_name` - optional, default nil, used when the inbox item keep several event types
|
185
|
+
- `skip_on_error` - optional, default false, omit consumer errors in message processing and commit the offset to Kafka
|
186
|
+
|
187
|
+
#### `deserializer.init_attrs` options
|
188
|
+
|
189
|
+
- `skip_decoding_error` — don't raise an exception when cannot deserialize the message
|
190
|
+
|
191
|
+
### `probes` config section
|
192
|
+
|
193
|
+
In Kubernetes, probes are mechanisms used to assess the health of your application running within a container.
|
194
|
+
|
195
|
+
```yaml
|
196
|
+
probes:
|
197
|
+
port: 9394 # optional, default 9394
|
198
|
+
endpoints:
|
199
|
+
liveness:
|
200
|
+
enabled: true # optional, default true
|
201
|
+
path: /liveness # optional, default "/liveness"
|
202
|
+
timeout: 10 # optional, default 10, timeout in seconds after which the group is considered dead
|
203
|
+
readiness:
|
204
|
+
enabled: true # optional, default true
|
205
|
+
path: /readiness/kafka_consumer # optional, default "/readiness/kafka_consumer"
|
206
|
+
```
|
207
|
+
|
208
|
+
### `metrics` config section
|
209
|
+
|
210
|
+
We use [Yabeda](https://github.com/yabeda-rb/yabeda) to collect [all kind of metrics](./lib/sbmt/kafka_consumer/yabeda_configurer.rb).
|
211
|
+
|
212
|
+
```yaml
|
213
|
+
metrics:
|
214
|
+
port: 9090 # optional, default is probes.port
|
215
|
+
path: /metrics # optional, default "/metrics"
|
216
|
+
```
|
217
|
+
|
218
|
+
### `Kafkafile`
|
219
|
+
|
220
|
+
You can create a `Kafkafile` in the root of your app to configure additional settings for your needs.
|
221
|
+
|
222
|
+
Example:
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
require_relative "config/environment"
|
226
|
+
|
227
|
+
some-extra-configuration
|
228
|
+
```
|
229
|
+
|
230
|
+
## CLI
|
231
|
+
|
232
|
+
Run the following command to execute a server
|
233
|
+
|
234
|
+
```shell
|
235
|
+
kafka_consumer -g some_group_id_1 -g some_group_id_2 -c 5
|
236
|
+
```
|
237
|
+
|
238
|
+
Where:
|
239
|
+
- `-g` - `group`, a consumer group id, if not specified, all groups from the config will be processed
|
240
|
+
- `-c` - `concurrency`, a number of threads, default is 4
|
241
|
+
|
242
|
+
### `concurrency` argument
|
243
|
+
|
244
|
+
[Concurrency and Multithreading](https://karafka.io/docs/Concurrency-and-multithreading/).
|
245
|
+
|
246
|
+
Don't forget to properly calculate and set the size of the ActiveRecord connection pool:
|
247
|
+
- each thread will utilize one db connection from the pool
|
248
|
+
- an application can have monitoring threads which can use db connections from the pool
|
249
|
+
|
250
|
+
Also pay attention to the number of processes of the server:
|
251
|
+
- `number_of_processes x concurrency` for topics with high data intensity can be equal to the number of partitions of the consumed topic
|
252
|
+
- `number_sof_processes x concurrency` for topics with low data intensity can be less than the number of partitions of the consumed topic
|
253
|
+
|
254
|
+
## Testing
|
255
|
+
|
256
|
+
To test your consumer with Rspec, please use [this shared context](./lib/sbmt/kafka_consumer/testing/shared_contexts/with_sbmt_karafka_consumer.rb)
|
257
|
+
|
258
|
+
```ruby
|
259
|
+
require "sbmt/kafka_consumer/testing"
|
260
|
+
|
261
|
+
RSpec.describe OrderCreatedConsumer do
|
262
|
+
include_context "with sbmt karafka consumer"
|
263
|
+
|
264
|
+
it "works" do
|
265
|
+
publish_to_sbmt_karafka(payload, deserializer: deserializer)
|
266
|
+
expect { consume_with_sbmt_karafka }.to change(Order, :count).by(1)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
```
|
270
|
+
|
271
|
+
## Development
|
272
|
+
|
273
|
+
1. Prepare environment
|
274
|
+
```shell
|
275
|
+
dip provision
|
276
|
+
```
|
277
|
+
|
278
|
+
2. Run tests
|
279
|
+
```shell
|
280
|
+
dip rspec
|
281
|
+
```
|
282
|
+
|
283
|
+
3. Run linter
|
284
|
+
```shell
|
285
|
+
dip rubocop
|
286
|
+
```
|
287
|
+
|
288
|
+
4. Run Kafka server
|
289
|
+
```shell
|
290
|
+
dip up
|
291
|
+
```
|
292
|
+
|
293
|
+
5. Run consumer server
|
294
|
+
```shell
|
295
|
+
dip kafka-consumer
|
296
|
+
```
|
data/Rakefile
ADDED