karafka 1.2.8 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.coditsu/ci.yml +3 -0
- data/.console_irbrc +1 -3
- data/.diffend.yml +3 -0
- data/.github/FUNDING.yml +3 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +50 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/ci.yml +52 -0
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +134 -14
- data/CODE_OF_CONDUCT.md +1 -1
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +4 -5
- data/Gemfile.lock +92 -81
- data/README.md +9 -12
- data/bin/karafka +1 -1
- data/certs/mensfeld.pem +25 -0
- data/config/errors.yml +38 -5
- data/docker-compose.yml +17 -0
- data/karafka.gemspec +18 -17
- data/lib/karafka.rb +10 -16
- data/lib/karafka/app.rb +14 -6
- data/lib/karafka/attributes_map.rb +5 -10
- data/lib/karafka/base_consumer.rb +19 -30
- data/lib/karafka/base_responder.rb +45 -27
- data/lib/karafka/cli.rb +2 -2
- data/lib/karafka/cli/console.rb +11 -9
- data/lib/karafka/cli/flow.rb +9 -7
- data/lib/karafka/cli/info.rb +4 -2
- data/lib/karafka/cli/install.rb +30 -6
- data/lib/karafka/cli/server.rb +11 -6
- data/lib/karafka/code_reloader.rb +67 -0
- data/lib/karafka/connection/api_adapter.rb +22 -9
- data/lib/karafka/connection/batch_delegator.rb +55 -0
- data/lib/karafka/connection/builder.rb +5 -3
- data/lib/karafka/connection/client.rb +31 -31
- data/lib/karafka/connection/listener.rb +26 -15
- data/lib/karafka/connection/message_delegator.rb +36 -0
- data/lib/karafka/consumers/batch_metadata.rb +10 -0
- data/lib/karafka/consumers/callbacks.rb +32 -15
- data/lib/karafka/consumers/includer.rb +31 -18
- data/lib/karafka/consumers/responders.rb +2 -2
- data/lib/karafka/contracts.rb +10 -0
- data/lib/karafka/contracts/config.rb +21 -0
- data/lib/karafka/contracts/consumer_group.rb +206 -0
- data/lib/karafka/contracts/consumer_group_topic.rb +19 -0
- data/lib/karafka/contracts/responder_usage.rb +54 -0
- data/lib/karafka/contracts/server_cli_options.rb +31 -0
- data/lib/karafka/errors.rb +17 -16
- data/lib/karafka/fetcher.rb +28 -30
- data/lib/karafka/helpers/class_matcher.rb +12 -2
- data/lib/karafka/helpers/config_retriever.rb +1 -1
- data/lib/karafka/helpers/inflector.rb +26 -0
- data/lib/karafka/helpers/multi_delegator.rb +0 -1
- data/lib/karafka/instrumentation/logger.rb +9 -6
- data/lib/karafka/instrumentation/monitor.rb +15 -9
- data/lib/karafka/instrumentation/proctitle_listener.rb +36 -0
- data/lib/karafka/instrumentation/stdout_listener.rb +140 -0
- data/lib/karafka/params/batch_metadata.rb +26 -0
- data/lib/karafka/params/builders/batch_metadata.rb +30 -0
- data/lib/karafka/params/builders/params.rb +38 -0
- data/lib/karafka/params/builders/params_batch.rb +25 -0
- data/lib/karafka/params/metadata.rb +20 -0
- data/lib/karafka/params/params.rb +54 -0
- data/lib/karafka/params/params_batch.rb +35 -21
- data/lib/karafka/patches/ruby_kafka.rb +21 -8
- data/lib/karafka/persistence/client.rb +15 -11
- data/lib/karafka/persistence/{consumer.rb → consumers.rb} +20 -13
- data/lib/karafka/persistence/topics.rb +48 -0
- data/lib/karafka/process.rb +0 -2
- data/lib/karafka/responders/builder.rb +1 -1
- data/lib/karafka/responders/topic.rb +6 -8
- data/lib/karafka/routing/builder.rb +36 -8
- data/lib/karafka/routing/consumer_group.rb +1 -1
- data/lib/karafka/routing/consumer_mapper.rb +9 -9
- data/lib/karafka/routing/proxy.rb +10 -1
- data/lib/karafka/routing/topic.rb +5 -3
- data/lib/karafka/routing/topic_mapper.rb +16 -18
- data/lib/karafka/serialization/json/deserializer.rb +27 -0
- data/lib/karafka/serialization/json/serializer.rb +31 -0
- data/lib/karafka/server.rb +29 -28
- data/lib/karafka/setup/config.rb +67 -37
- data/lib/karafka/setup/configurators/water_drop.rb +7 -3
- data/lib/karafka/setup/dsl.rb +0 -1
- data/lib/karafka/status.rb +7 -3
- data/lib/karafka/templates/{application_consumer.rb.example → application_consumer.rb.erb} +2 -1
- data/lib/karafka/templates/{application_responder.rb.example → application_responder.rb.erb} +0 -0
- data/lib/karafka/templates/karafka.rb.erb +92 -0
- data/lib/karafka/version.rb +1 -1
- metadata +94 -72
- metadata.gz.sig +0 -0
- data/.travis.yml +0 -21
- data/lib/karafka/callbacks.rb +0 -30
- data/lib/karafka/callbacks/config.rb +0 -22
- data/lib/karafka/callbacks/dsl.rb +0 -16
- data/lib/karafka/connection/delegator.rb +0 -46
- data/lib/karafka/instrumentation/listener.rb +0 -112
- data/lib/karafka/loader.rb +0 -28
- data/lib/karafka/params/dsl.rb +0 -156
- data/lib/karafka/parsers/json.rb +0 -38
- data/lib/karafka/patches/dry_configurable.rb +0 -35
- data/lib/karafka/persistence/topic.rb +0 -29
- data/lib/karafka/schemas/config.rb +0 -24
- data/lib/karafka/schemas/consumer_group.rb +0 -78
- data/lib/karafka/schemas/consumer_group_topic.rb +0 -18
- data/lib/karafka/schemas/responder_usage.rb +0 -39
- data/lib/karafka/schemas/server_cli_options.rb +0 -43
- data/lib/karafka/setup/configurators/base.rb +0 -29
- data/lib/karafka/setup/configurators/params.rb +0 -25
- data/lib/karafka/templates/karafka.rb.example +0 -54
@@ -1,24 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Karafka
|
4
|
-
# Namespace for all the validation schemas that we use to check input
|
5
|
-
module Schemas
|
6
|
-
# Regexp for validating format of groups and topics
|
7
|
-
TOPIC_REGEXP = /\A(\w|\-|\.)+\z/
|
8
|
-
|
9
|
-
# Schema with validation rules for Karafka configuration details
|
10
|
-
# @note There are many more configuration options inside of the
|
11
|
-
# Karafka::Setup::Config model, but we don't validate them here as they are
|
12
|
-
# validated per each route (topic + consumer_group) because they can be overwritten,
|
13
|
-
# so we validate all of that once all the routes are defined and ready
|
14
|
-
Config = Dry::Validation.Schema do
|
15
|
-
required(:client_id).filled(:str?, format?: Karafka::Schemas::TOPIC_REGEXP)
|
16
|
-
required(:shutdown_timeout) { none? | (int? & gteq?(0)) }
|
17
|
-
required(:consumer_mapper)
|
18
|
-
required(:topic_mapper)
|
19
|
-
required(:params_base_class).filled
|
20
|
-
|
21
|
-
optional(:backend).filled
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Karafka
|
4
|
-
module Schemas
|
5
|
-
# Schema for single full route (consumer group + topics) validation.
|
6
|
-
ConsumerGroup = Dry::Validation.Schema do
|
7
|
-
# Valid uri schemas of Kafka broker url
|
8
|
-
# The ||= is due to the behavior of require_all that resolves dependencies
|
9
|
-
# but someetimes loads things twice
|
10
|
-
URI_SCHEMES ||= %w[kafka kafka+ssl plaintext ssl].freeze
|
11
|
-
|
12
|
-
# Available sasl scram mechanism of authentication (plus nil)
|
13
|
-
SASL_SCRAM_MECHANISMS ||= %w[sha256 sha512].freeze
|
14
|
-
|
15
|
-
configure do
|
16
|
-
config.messages_file = File.join(
|
17
|
-
Karafka.gem_root, 'config', 'errors.yml'
|
18
|
-
)
|
19
|
-
|
20
|
-
# Uri validator to check if uri is in a Karafka acceptable format
|
21
|
-
# @param uri [String] uri we want to validate
|
22
|
-
# @return [Boolean] true if it is a valid uri, otherwise false
|
23
|
-
def broker_schema?(uri)
|
24
|
-
uri = URI.parse(uri)
|
25
|
-
URI_SCHEMES.include?(uri.scheme) && uri.port
|
26
|
-
rescue URI::InvalidURIError
|
27
|
-
false
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
required(:id).filled(:str?, format?: Karafka::Schemas::TOPIC_REGEXP)
|
32
|
-
required(:seed_brokers).filled { each(:broker_schema?) }
|
33
|
-
required(:session_timeout).filled { int? | float? }
|
34
|
-
required(:pause_timeout) { none? | ((int? | float?) & gteq?(0)) }
|
35
|
-
required(:offset_commit_interval) { int? | float? }
|
36
|
-
required(:offset_commit_threshold).filled(:int?)
|
37
|
-
required(:offset_retention_time) { none?.not > int? }
|
38
|
-
required(:heartbeat_interval).filled { (int? | float?) & gteq?(0) }
|
39
|
-
required(:fetcher_max_queue_size).filled(:int?, gt?: 0)
|
40
|
-
required(:connect_timeout).filled { (int? | float?) & gt?(0) }
|
41
|
-
required(:socket_timeout).filled { (int? | float?) & gt?(0) }
|
42
|
-
required(:min_bytes).filled(:int?, gt?: 0)
|
43
|
-
required(:max_bytes).filled(:int?, gt?: 0)
|
44
|
-
required(:max_wait_time).filled { (int? | float?) & gteq?(0) }
|
45
|
-
required(:batch_fetching).filled(:bool?)
|
46
|
-
required(:topics).filled { each { schema(ConsumerGroupTopic) } }
|
47
|
-
|
48
|
-
# Max wait time cannot exceed socket_timeout - wouldn't make sense
|
49
|
-
rule(
|
50
|
-
max_wait_time_limit: %i[max_wait_time socket_timeout]
|
51
|
-
) do |max_wait_time, socket_timeout|
|
52
|
-
socket_timeout.int? > max_wait_time.lteq?(value(:socket_timeout))
|
53
|
-
end
|
54
|
-
|
55
|
-
%i[
|
56
|
-
ssl_ca_cert
|
57
|
-
ssl_ca_cert_file_path
|
58
|
-
ssl_client_cert
|
59
|
-
ssl_client_cert_key
|
60
|
-
sasl_gssapi_principal
|
61
|
-
sasl_gssapi_keytab
|
62
|
-
sasl_plain_authzid
|
63
|
-
sasl_plain_username
|
64
|
-
sasl_plain_password
|
65
|
-
sasl_scram_username
|
66
|
-
sasl_scram_password
|
67
|
-
].each do |encryption_attribute|
|
68
|
-
optional(encryption_attribute).maybe(:str?)
|
69
|
-
end
|
70
|
-
|
71
|
-
optional(:ssl_ca_certs_from_system).maybe(:bool?)
|
72
|
-
|
73
|
-
# It's not with other encryptions as it has some more rules
|
74
|
-
optional(:sasl_scram_mechanism)
|
75
|
-
.maybe(:str?, included_in?: Karafka::Schemas::SASL_SCRAM_MECHANISMS)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Karafka
|
4
|
-
module Schemas
|
5
|
-
# Consumer group topic validation rules
|
6
|
-
ConsumerGroupTopic = Dry::Validation.Schema do
|
7
|
-
required(:id).filled(:str?, format?: Karafka::Schemas::TOPIC_REGEXP)
|
8
|
-
required(:name).filled(:str?, format?: Karafka::Schemas::TOPIC_REGEXP)
|
9
|
-
required(:backend).filled(included_in?: %i[inline sidekiq])
|
10
|
-
required(:consumer).filled
|
11
|
-
required(:parser).filled
|
12
|
-
required(:max_bytes_per_partition).filled(:int?, gteq?: 0)
|
13
|
-
required(:start_from_beginning).filled(:bool?)
|
14
|
-
required(:batch_consuming).filled(:bool?)
|
15
|
-
required(:persistent).filled(:bool?)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Karafka
|
4
|
-
module Schemas
|
5
|
-
# Validator to check responder topic usage
|
6
|
-
ResponderUsageTopic = Dry::Validation.Schema do
|
7
|
-
required(:name).filled(:str?, format?: Karafka::Schemas::TOPIC_REGEXP)
|
8
|
-
required(:required).filled(:bool?)
|
9
|
-
required(:multiple_usage).filled(:bool?)
|
10
|
-
required(:usage_count).filled(:int?, gteq?: 0)
|
11
|
-
required(:registered).filled(eql?: true)
|
12
|
-
required(:async).filled(:bool?)
|
13
|
-
|
14
|
-
rule(
|
15
|
-
required_usage: %i[required usage_count]
|
16
|
-
) do |required, usage_count|
|
17
|
-
required.true? > usage_count.gteq?(1)
|
18
|
-
end
|
19
|
-
|
20
|
-
rule(
|
21
|
-
multiple_usage_permission: %i[multiple_usage usage_count]
|
22
|
-
) do |multiple_usage, usage_count|
|
23
|
-
usage_count.gt?(1) > multiple_usage.true?
|
24
|
-
end
|
25
|
-
|
26
|
-
rule(
|
27
|
-
multiple_usage_block: %i[multiple_usage usage_count]
|
28
|
-
) do |multiple_usage, usage_count|
|
29
|
-
multiple_usage.false? > usage_count.lteq?(1)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# Validator to check that everything in a responder flow matches responder rules
|
34
|
-
ResponderUsage = Dry::Validation.Schema do
|
35
|
-
required(:used_topics) { filled? > each { schema(ResponderUsageTopic) } }
|
36
|
-
required(:registered_topics) { filled? > each { schema(ResponderUsageTopic) } }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Karafka
|
4
|
-
module Schemas
|
5
|
-
# Schema for validating correctness of the server cli command options
|
6
|
-
# We validate some basics + the list of consumer_groups on which we want to use, to make
|
7
|
-
# sure that all of them are defined, plus that a pidfile does not exist
|
8
|
-
ServerCliOptions = Dry::Validation.Schema do
|
9
|
-
configure do
|
10
|
-
option :consumer_groups
|
11
|
-
|
12
|
-
def self.messages
|
13
|
-
super.merge(
|
14
|
-
en: {
|
15
|
-
errors: {
|
16
|
-
consumer_groups_inclusion: 'Unknown consumer group.',
|
17
|
-
pid_existence: 'Pidfile already exists.'
|
18
|
-
}
|
19
|
-
}
|
20
|
-
)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
optional(:pid).filled(:str?)
|
25
|
-
optional(:daemon).filled(:bool?)
|
26
|
-
optional(:consumer_groups).filled(:array?)
|
27
|
-
|
28
|
-
validate(consumer_groups_inclusion: :consumer_groups) do |consumer_groups|
|
29
|
-
# If there were no consumer_groups declared in the server cli, it means that we will
|
30
|
-
# run all of them and no need to validate them here at all
|
31
|
-
if consumer_groups.nil?
|
32
|
-
true
|
33
|
-
else
|
34
|
-
(consumer_groups - Karafka::Routing::Builder.instance.map(&:name)).empty?
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
validate(pid_existence: :pid) do |pid|
|
39
|
-
pid ? !File.exist?(pid) : true
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Karafka
|
4
|
-
module Setup
|
5
|
-
# Configurators module is used to enclose all the external dependencies configurations
|
6
|
-
# upon which Karafka depents
|
7
|
-
class Configurators
|
8
|
-
# Karafka has some components that it relies on (like Sidekiq)
|
9
|
-
# We need to configure all of them only when the framework was set up.
|
10
|
-
# Any class that descends from this one will be automatically invoked upon setup (after it)
|
11
|
-
# @note This should be used only for internal Karafka dependencies configuration
|
12
|
-
# End users configuration should go to the after_init block
|
13
|
-
# @example Configure an Example class
|
14
|
-
# class ExampleConfigurator < Base
|
15
|
-
# def setup
|
16
|
-
# ExampleClass.logger = Karafka.logger
|
17
|
-
# ExampleClass.redis = config.redis
|
18
|
-
# end
|
19
|
-
# end
|
20
|
-
class Base
|
21
|
-
# @param _config [Karafka::Config] config instance
|
22
|
-
# This method needs to be implemented in a subclass
|
23
|
-
def self.setup(_config)
|
24
|
-
raise NotImplementedError
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Karafka
|
4
|
-
module Setup
|
5
|
-
class Configurators
|
6
|
-
# Karafka::Params::Params are dynamically built based on user defined parent class
|
7
|
-
# so we cannot just require it, we need to initialize it after user is done with
|
8
|
-
# the framework configuration. This is a configurator that does exactly that.
|
9
|
-
class Params < Base
|
10
|
-
# Builds up Karafka::Params::Params class with user defined parent class
|
11
|
-
# @param config [Karafka::Setup::Config] Config we can user to setup things
|
12
|
-
def self.setup(config)
|
13
|
-
return if defined? Karafka::Params::Params
|
14
|
-
|
15
|
-
Karafka::Params.const_set(
|
16
|
-
'Params',
|
17
|
-
Class
|
18
|
-
.new(config.params_base_class)
|
19
|
-
.tap { |klass| klass.include(Karafka::Params::Dsl) }
|
20
|
-
)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Non Ruby on Rails setup
|
4
|
-
ENV['RACK_ENV'] ||= 'development'
|
5
|
-
ENV['KARAFKA_ENV'] ||= ENV['RACK_ENV']
|
6
|
-
Bundler.require(:default, ENV['KARAFKA_ENV'])
|
7
|
-
Karafka::Loader.load(Karafka::App.root)
|
8
|
-
|
9
|
-
# Ruby on Rails setup
|
10
|
-
# Remove whole non-Rails setup that is above and uncomment the 4 lines below
|
11
|
-
# ENV['RAILS_ENV'] ||= 'development'
|
12
|
-
# ENV['KARAFKA_ENV'] = ENV['RAILS_ENV']
|
13
|
-
# require ::File.expand_path('../config/environment', __FILE__)
|
14
|
-
# Rails.application.eager_load!
|
15
|
-
|
16
|
-
class KarafkaApp < Karafka::App
|
17
|
-
setup do |config|
|
18
|
-
config.kafka.seed_brokers = %w[kafka://127.0.0.1:9092]
|
19
|
-
config.client_id = 'example_app'
|
20
|
-
config.backend = :inline
|
21
|
-
config.batch_fetching = true
|
22
|
-
# Uncomment this for Rails app integration
|
23
|
-
# config.logger = Rails.logger
|
24
|
-
end
|
25
|
-
|
26
|
-
after_init do |config|
|
27
|
-
# Put here all the things you want to do after the Karafka framework
|
28
|
-
# initialization
|
29
|
-
end
|
30
|
-
|
31
|
-
# Comment out this part if you are not using instrumentation and/or you are not
|
32
|
-
# interested in logging events for certain environments. Since instrumentation
|
33
|
-
# notifications add extra boilerplate, if you want to achieve max performance,
|
34
|
-
# listen to only what you really need for given environment.
|
35
|
-
Karafka.monitor.subscribe(Karafka::Instrumentation::Listener)
|
36
|
-
|
37
|
-
consumer_groups.draw do
|
38
|
-
# topic :example do
|
39
|
-
# consumer ExampleConsumer
|
40
|
-
# end
|
41
|
-
|
42
|
-
# consumer_group :bigger_group do
|
43
|
-
# topic :test do
|
44
|
-
# consumer TestConsumer
|
45
|
-
# end
|
46
|
-
#
|
47
|
-
# topic :test2 do
|
48
|
-
# consumer Test2Consumer
|
49
|
-
# end
|
50
|
-
# end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
KarafkaApp.boot!
|