karafka 1.4.13 → 2.0.0
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 +3 -3
- data/.github/workflows/ci.yml +85 -30
- data/.ruby-version +1 -1
- data/CHANGELOG.md +268 -7
- data/CONTRIBUTING.md +10 -19
- data/Gemfile +6 -0
- data/Gemfile.lock +44 -87
- data/LICENSE +17 -0
- data/LICENSE-COMM +89 -0
- data/LICENSE-LGPL +165 -0
- data/README.md +44 -48
- data/bin/benchmarks +85 -0
- data/bin/create_token +22 -0
- data/bin/integrations +237 -0
- data/bin/karafka +4 -0
- data/bin/scenario +29 -0
- data/bin/stress_many +13 -0
- data/bin/stress_one +13 -0
- data/bin/wait_for_kafka +20 -0
- data/certs/karafka-pro.pem +11 -0
- data/config/errors.yml +55 -40
- data/docker-compose.yml +39 -3
- data/karafka.gemspec +11 -17
- data/lib/active_job/karafka.rb +21 -0
- data/lib/active_job/queue_adapters/karafka_adapter.rb +26 -0
- data/lib/karafka/active_job/consumer.rb +26 -0
- data/lib/karafka/active_job/dispatcher.rb +38 -0
- data/lib/karafka/active_job/job_extensions.rb +34 -0
- data/lib/karafka/active_job/job_options_contract.rb +21 -0
- data/lib/karafka/active_job/routing/extensions.rb +31 -0
- data/lib/karafka/app.rb +15 -20
- data/lib/karafka/base_consumer.rb +181 -31
- data/lib/karafka/cli/base.rb +4 -4
- data/lib/karafka/cli/info.rb +43 -9
- data/lib/karafka/cli/install.rb +19 -10
- data/lib/karafka/cli/server.rb +17 -42
- data/lib/karafka/cli.rb +4 -11
- data/lib/karafka/connection/client.rb +385 -90
- data/lib/karafka/connection/listener.rb +246 -38
- data/lib/karafka/connection/listeners_batch.rb +24 -0
- data/lib/karafka/connection/messages_buffer.rb +84 -0
- data/lib/karafka/connection/pauses_manager.rb +46 -0
- data/lib/karafka/connection/raw_messages_buffer.rb +101 -0
- data/lib/karafka/connection/rebalance_manager.rb +78 -0
- data/lib/karafka/contracts/base.rb +17 -0
- data/lib/karafka/contracts/config.rb +88 -11
- data/lib/karafka/contracts/consumer_group.rb +21 -189
- data/lib/karafka/contracts/consumer_group_topic.rb +34 -11
- data/lib/karafka/contracts/server_cli_options.rb +19 -18
- data/lib/karafka/contracts.rb +1 -1
- data/lib/karafka/env.rb +46 -0
- data/lib/karafka/errors.rb +21 -21
- data/lib/karafka/helpers/async.rb +33 -0
- data/lib/karafka/helpers/colorize.rb +20 -0
- data/lib/karafka/helpers/multi_delegator.rb +2 -2
- data/lib/karafka/instrumentation/callbacks/error.rb +40 -0
- data/lib/karafka/instrumentation/callbacks/statistics.rb +41 -0
- data/lib/karafka/instrumentation/logger_listener.rb +164 -0
- data/lib/karafka/instrumentation/monitor.rb +13 -61
- data/lib/karafka/instrumentation/notifications.rb +52 -0
- data/lib/karafka/instrumentation/proctitle_listener.rb +3 -3
- data/lib/karafka/instrumentation/vendors/datadog/dashboard.json +1 -0
- data/lib/karafka/instrumentation/vendors/datadog/listener.rb +232 -0
- data/lib/karafka/instrumentation.rb +21 -0
- data/lib/karafka/licenser.rb +75 -0
- data/lib/karafka/messages/batch_metadata.rb +45 -0
- data/lib/karafka/messages/builders/batch_metadata.rb +40 -0
- data/lib/karafka/messages/builders/message.rb +39 -0
- data/lib/karafka/messages/builders/messages.rb +32 -0
- data/lib/karafka/{params/params.rb → messages/message.rb} +7 -12
- data/lib/karafka/messages/messages.rb +64 -0
- data/lib/karafka/{params → messages}/metadata.rb +4 -6
- data/lib/karafka/messages/seek.rb +9 -0
- data/lib/karafka/patches/rdkafka/consumer.rb +22 -0
- data/lib/karafka/pro/active_job/consumer.rb +46 -0
- data/lib/karafka/pro/active_job/dispatcher.rb +61 -0
- data/lib/karafka/pro/active_job/job_options_contract.rb +32 -0
- data/lib/karafka/pro/base_consumer.rb +82 -0
- data/lib/karafka/pro/contracts/base.rb +21 -0
- data/lib/karafka/pro/contracts/consumer_group.rb +34 -0
- data/lib/karafka/pro/contracts/consumer_group_topic.rb +33 -0
- data/lib/karafka/pro/loader.rb +76 -0
- data/lib/karafka/pro/performance_tracker.rb +80 -0
- data/lib/karafka/pro/processing/coordinator.rb +72 -0
- data/lib/karafka/pro/processing/jobs/consume_non_blocking.rb +37 -0
- data/lib/karafka/pro/processing/jobs_builder.rb +32 -0
- data/lib/karafka/pro/processing/partitioner.rb +60 -0
- data/lib/karafka/pro/processing/scheduler.rb +56 -0
- data/lib/karafka/pro/routing/builder_extensions.rb +30 -0
- data/lib/karafka/pro/routing/topic_extensions.rb +38 -0
- data/lib/karafka/pro.rb +13 -0
- data/lib/karafka/process.rb +1 -0
- data/lib/karafka/processing/coordinator.rb +88 -0
- data/lib/karafka/processing/coordinators_buffer.rb +54 -0
- data/lib/karafka/processing/executor.rb +118 -0
- data/lib/karafka/processing/executors_buffer.rb +88 -0
- data/lib/karafka/processing/jobs/base.rb +51 -0
- data/lib/karafka/processing/jobs/consume.rb +42 -0
- data/lib/karafka/processing/jobs/revoked.rb +22 -0
- data/lib/karafka/processing/jobs/shutdown.rb +23 -0
- data/lib/karafka/processing/jobs_builder.rb +29 -0
- data/lib/karafka/processing/jobs_queue.rb +144 -0
- data/lib/karafka/processing/partitioner.rb +22 -0
- data/lib/karafka/processing/result.rb +29 -0
- data/lib/karafka/processing/scheduler.rb +22 -0
- data/lib/karafka/processing/worker.rb +88 -0
- data/lib/karafka/processing/workers_batch.rb +27 -0
- data/lib/karafka/railtie.rb +113 -0
- data/lib/karafka/routing/builder.rb +15 -24
- data/lib/karafka/routing/consumer_group.rb +11 -19
- data/lib/karafka/routing/consumer_mapper.rb +1 -2
- data/lib/karafka/routing/router.rb +1 -1
- data/lib/karafka/routing/subscription_group.rb +53 -0
- data/lib/karafka/routing/subscription_groups_builder.rb +53 -0
- data/lib/karafka/routing/topic.rb +61 -24
- data/lib/karafka/routing/topics.rb +38 -0
- data/lib/karafka/runner.rb +51 -0
- data/lib/karafka/serialization/json/deserializer.rb +6 -15
- data/lib/karafka/server.rb +67 -26
- data/lib/karafka/setup/config.rb +147 -175
- data/lib/karafka/status.rb +14 -5
- data/lib/karafka/templates/example_consumer.rb.erb +16 -0
- data/lib/karafka/templates/karafka.rb.erb +15 -51
- data/lib/karafka/time_trackers/base.rb +19 -0
- data/lib/karafka/time_trackers/pause.rb +92 -0
- data/lib/karafka/time_trackers/poll.rb +65 -0
- data/lib/karafka/version.rb +1 -1
- data/lib/karafka.rb +38 -17
- data.tar.gz.sig +0 -0
- metadata +118 -120
- metadata.gz.sig +0 -0
- data/MIT-LICENCE +0 -18
- data/lib/karafka/assignment_strategies/round_robin.rb +0 -13
- data/lib/karafka/attributes_map.rb +0 -63
- data/lib/karafka/backends/inline.rb +0 -16
- data/lib/karafka/base_responder.rb +0 -226
- data/lib/karafka/cli/flow.rb +0 -48
- data/lib/karafka/cli/missingno.rb +0 -19
- data/lib/karafka/code_reloader.rb +0 -67
- data/lib/karafka/connection/api_adapter.rb +0 -158
- data/lib/karafka/connection/batch_delegator.rb +0 -55
- data/lib/karafka/connection/builder.rb +0 -23
- data/lib/karafka/connection/message_delegator.rb +0 -36
- data/lib/karafka/consumers/batch_metadata.rb +0 -10
- data/lib/karafka/consumers/callbacks.rb +0 -71
- data/lib/karafka/consumers/includer.rb +0 -64
- data/lib/karafka/consumers/responders.rb +0 -24
- data/lib/karafka/consumers/single_params.rb +0 -15
- data/lib/karafka/contracts/responder_usage.rb +0 -54
- data/lib/karafka/fetcher.rb +0 -42
- data/lib/karafka/helpers/class_matcher.rb +0 -88
- data/lib/karafka/helpers/config_retriever.rb +0 -46
- data/lib/karafka/helpers/inflector.rb +0 -26
- data/lib/karafka/instrumentation/stdout_listener.rb +0 -140
- data/lib/karafka/params/batch_metadata.rb +0 -26
- data/lib/karafka/params/builders/batch_metadata.rb +0 -30
- data/lib/karafka/params/builders/params.rb +0 -38
- data/lib/karafka/params/builders/params_batch.rb +0 -25
- data/lib/karafka/params/params_batch.rb +0 -60
- data/lib/karafka/patches/ruby_kafka.rb +0 -47
- data/lib/karafka/persistence/client.rb +0 -29
- data/lib/karafka/persistence/consumers.rb +0 -45
- data/lib/karafka/persistence/topics.rb +0 -48
- data/lib/karafka/responders/builder.rb +0 -36
- data/lib/karafka/responders/topic.rb +0 -55
- data/lib/karafka/routing/topic_mapper.rb +0 -53
- data/lib/karafka/serialization/json/serializer.rb +0 -31
- data/lib/karafka/setup/configurators/water_drop.rb +0 -36
- data/lib/karafka/templates/application_responder.rb.erb +0 -11
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Karafka
|
|
4
|
-
module Params
|
|
5
|
-
module Builders
|
|
6
|
-
# Builder for creating params batch instances
|
|
7
|
-
module ParamsBatch
|
|
8
|
-
class << self
|
|
9
|
-
# Creates params batch with params inside based on the incoming messages
|
|
10
|
-
# and the topic from which it comes
|
|
11
|
-
# @param kafka_messages [Array<Kafka::FetchedMessage>] raw fetched messages
|
|
12
|
-
# @param topic [Karafka::Routing::Topic] topic for which we're received messages
|
|
13
|
-
# @return [Karafka::Params::ParamsBatch<Karafka::Params::Params>] batch with params
|
|
14
|
-
def from_kafka_messages(kafka_messages, topic)
|
|
15
|
-
params_array = kafka_messages.map do |message|
|
|
16
|
-
Karafka::Params::Builders::Params.from_kafka_message(message, topic)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
Karafka::Params::ParamsBatch.new(params_array).freeze
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Karafka
|
|
4
|
-
module Params
|
|
5
|
-
# Params batch represents a set of messages received from Kafka.
|
|
6
|
-
# @note Params internally are lazy loaded before first use. That way we can skip
|
|
7
|
-
# deserialization process if we have after_fetch that rejects some incoming messages
|
|
8
|
-
# without using params It can be also used when handling really heavy data.
|
|
9
|
-
class ParamsBatch
|
|
10
|
-
include Enumerable
|
|
11
|
-
|
|
12
|
-
# @param params_array [Array<Karafka::Params::Params>] array with karafka params
|
|
13
|
-
# @return [Karafka::Params::ParamsBatch] lazy evaluated params batch object
|
|
14
|
-
def initialize(params_array)
|
|
15
|
-
@params_array = params_array
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# @yieldparam [Karafka::Params::Params] each params instance
|
|
19
|
-
# @note Invocation of this method will not cause loading and deserializing each param after
|
|
20
|
-
# another.
|
|
21
|
-
def each
|
|
22
|
-
@params_array.each { |param| yield(param) }
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# @return [Array<Karafka::Params::Params>] returns all the params in a loaded state, so they
|
|
26
|
-
# can be used for batch insert, etc. Without invoking all, up until first use, they won't
|
|
27
|
-
# be deserialized
|
|
28
|
-
def deserialize!
|
|
29
|
-
each(&:payload)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# @return [Array<Object>] array with deserialized payloads. This method can be useful when
|
|
33
|
-
# we don't care about metadata and just want to extract all the data payloads from the
|
|
34
|
-
# batch
|
|
35
|
-
def payloads
|
|
36
|
-
map(&:payload)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# @return [Karafka::Params::Params] first element
|
|
40
|
-
def first
|
|
41
|
-
@params_array.first
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# @return [Karafka::Params::Params] last element
|
|
45
|
-
def last
|
|
46
|
-
@params_array.last
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# @return [Integer] number of messages in the batch
|
|
50
|
-
def size
|
|
51
|
-
@params_array.size
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# @return [Array<Karafka::Params::Params>] pure array with params
|
|
55
|
-
def to_a
|
|
56
|
-
@params_array
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Karafka
|
|
4
|
-
# Namespace for various other libs patches
|
|
5
|
-
module Patches
|
|
6
|
-
# Patches for Ruby Kafka gem
|
|
7
|
-
module RubyKafka
|
|
8
|
-
# This patch allows us to inject business logic in between fetches and before the consumer
|
|
9
|
-
# stop, so we can perform stop commit or anything else that we need since
|
|
10
|
-
# ruby-kafka fetch loop does not allow that directly
|
|
11
|
-
# We don't won't to use poll ruby-kafka api as it brings many more problems that we would
|
|
12
|
-
# have to take care of. That way, nothing like that ever happens but we get the control
|
|
13
|
-
# over the stopping process that we need (since we're the once that initiate it for each
|
|
14
|
-
# thread)
|
|
15
|
-
def consumer_loop
|
|
16
|
-
super do
|
|
17
|
-
consumers = Karafka::Persistence::Consumers
|
|
18
|
-
.current
|
|
19
|
-
.values
|
|
20
|
-
.flat_map(&:values)
|
|
21
|
-
.select { |consumer| consumer.class.respond_to?(:after_fetch) }
|
|
22
|
-
|
|
23
|
-
if Karafka::App.stopping?
|
|
24
|
-
publish_event(consumers, 'before_stop')
|
|
25
|
-
Karafka::Persistence::Client.read.stop
|
|
26
|
-
else
|
|
27
|
-
publish_event(consumers, 'before_poll')
|
|
28
|
-
yield
|
|
29
|
-
publish_event(consumers, 'after_poll')
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
private
|
|
35
|
-
|
|
36
|
-
# Notifies consumers about particular events happening
|
|
37
|
-
# @param consumers [Array<Object>] all consumers that want to be notified about an event
|
|
38
|
-
# @param event_name [String] name of the event that happened
|
|
39
|
-
def publish_event(consumers, event_name)
|
|
40
|
-
consumers.each do |consumer|
|
|
41
|
-
key = "consumers.#{Helpers::Inflector.map(consumer.class.to_s)}.#{event_name}"
|
|
42
|
-
Karafka::App.monitor.instrument(key, context: consumer)
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Karafka
|
|
4
|
-
module Persistence
|
|
5
|
-
# Persistence layer to store current thread messages consumer client for further use
|
|
6
|
-
class Client
|
|
7
|
-
# Thread.current key under which we store current thread messages consumer client
|
|
8
|
-
PERSISTENCE_SCOPE = :client
|
|
9
|
-
|
|
10
|
-
private_constant :PERSISTENCE_SCOPE
|
|
11
|
-
|
|
12
|
-
class << self
|
|
13
|
-
# @param client [Karafka::Connection::Client] messages consumer client of
|
|
14
|
-
# a current thread
|
|
15
|
-
# @return [Karafka::Connection::Client] persisted messages consumer client
|
|
16
|
-
def write(client)
|
|
17
|
-
Thread.current[PERSISTENCE_SCOPE] = client
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# @return [Karafka::Connection::Client] persisted messages consumer client
|
|
21
|
-
# @raise [Karafka::Errors::MissingClientError] raised when no thread messages consumer
|
|
22
|
-
# client but we try to use it anyway
|
|
23
|
-
def read
|
|
24
|
-
Thread.current[PERSISTENCE_SCOPE] || raise(Errors::MissingClientError)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Karafka
|
|
4
|
-
# Module used to provide a persistent cache layer for Karafka components that need to be
|
|
5
|
-
# shared inside of a same thread
|
|
6
|
-
module Persistence
|
|
7
|
-
# Module used to provide a persistent cache across batch requests for a given
|
|
8
|
-
# topic and partition to store some additional details when the persistent mode
|
|
9
|
-
# for a given topic is turned on
|
|
10
|
-
class Consumers
|
|
11
|
-
# Thread.current scope under which we store consumers data
|
|
12
|
-
PERSISTENCE_SCOPE = :consumers
|
|
13
|
-
|
|
14
|
-
private_constant :PERSISTENCE_SCOPE
|
|
15
|
-
|
|
16
|
-
class << self
|
|
17
|
-
# @return [Hash] current thread's persistence scope hash with all the consumers
|
|
18
|
-
def current
|
|
19
|
-
Thread.current[PERSISTENCE_SCOPE] ||= Concurrent::Hash.new do |hash, key|
|
|
20
|
-
hash[key] = Concurrent::Hash.new
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Used to build (if block given) and/or fetch a current consumer instance that will be
|
|
25
|
-
# used to process messages from a given topic and partition
|
|
26
|
-
# @param topic [Karafka::Routing::Topic] topic instance for which we might cache
|
|
27
|
-
# @param partition [Integer] number of partition for which we want to cache
|
|
28
|
-
# @return [Karafka::BaseConsumer] base consumer descendant
|
|
29
|
-
def fetch(topic, partition)
|
|
30
|
-
current[topic][partition] ||= topic.consumer.new(topic)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Removes all persisted instances of consumers from the consumer cache
|
|
34
|
-
# @note This is used to reload consumers instances when code reloading in development mode
|
|
35
|
-
# is present. This should not be used in production.
|
|
36
|
-
def clear
|
|
37
|
-
Thread
|
|
38
|
-
.list
|
|
39
|
-
.select { |thread| thread[PERSISTENCE_SCOPE] }
|
|
40
|
-
.each { |thread| thread[PERSISTENCE_SCOPE].clear }
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Karafka
|
|
4
|
-
module Persistence
|
|
5
|
-
# Local cache for routing topics
|
|
6
|
-
# We use it in order not to build string instances and remap incoming topic upon each
|
|
7
|
-
# message / message batches received
|
|
8
|
-
class Topics
|
|
9
|
-
# Thread.current scope under which we store topics data
|
|
10
|
-
PERSISTENCE_SCOPE = :topics
|
|
11
|
-
|
|
12
|
-
private_constant :PERSISTENCE_SCOPE
|
|
13
|
-
|
|
14
|
-
class << self
|
|
15
|
-
# @return [Concurrent::Hash] hash with all the topics from given groups
|
|
16
|
-
def current
|
|
17
|
-
Thread.current[PERSISTENCE_SCOPE] ||= Concurrent::Hash.new do |hash, key|
|
|
18
|
-
hash[key] = Concurrent::Hash.new
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# @param group_id [String] group id for which we fetch a topic representation
|
|
23
|
-
# @param raw_topic_name [String] raw topic name (before remapping) for which we fetch a
|
|
24
|
-
# topic representation
|
|
25
|
-
# @return [Karafka::Routing::Topics] remapped topic representation that can be used further
|
|
26
|
-
# on when working with given parameters
|
|
27
|
-
def fetch(group_id, raw_topic_name)
|
|
28
|
-
current[group_id][raw_topic_name] ||= begin
|
|
29
|
-
# We map from incoming topic name, as it might be namespaced, etc.
|
|
30
|
-
# @see topic_mapper internal docs
|
|
31
|
-
mapped_topic_name = Karafka::App.config.topic_mapper.incoming(raw_topic_name)
|
|
32
|
-
Routing::Router.find("#{group_id}_#{mapped_topic_name}")
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Clears the whole topics cache for all the threads
|
|
37
|
-
# This is used for in-development code reloading as we need to get rid of all the
|
|
38
|
-
# preloaded and cached instances of objects to make it work
|
|
39
|
-
def clear
|
|
40
|
-
Thread
|
|
41
|
-
.list
|
|
42
|
-
.select { |thread| thread[PERSISTENCE_SCOPE] }
|
|
43
|
-
.each { |thread| thread[PERSISTENCE_SCOPE].clear }
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Karafka
|
|
4
|
-
# Responders namespace encapsulates all the internal responder implementation parts
|
|
5
|
-
module Responders
|
|
6
|
-
# Responders builder is used for finding (based on the consumer class name) a responder
|
|
7
|
-
# that match the consumer. We use it when user does not provide a responder inside routing,
|
|
8
|
-
# but he still names responder with the same convention (and namespaces) as consumer
|
|
9
|
-
#
|
|
10
|
-
# @example Matching responder exists
|
|
11
|
-
# Karafka::Responder::Builder(NewEventsConsumer).build #=> NewEventsResponder
|
|
12
|
-
# @example Matching responder does not exist
|
|
13
|
-
# Karafka::Responder::Builder(NewBuildsConsumer).build #=> nil
|
|
14
|
-
class Builder
|
|
15
|
-
# @param consumer_class [Karafka::BaseConsumer, nil] descendant of
|
|
16
|
-
# Karafka::BaseConsumer
|
|
17
|
-
# @example Tries to find a responder that matches a given consumer. If nothing found,
|
|
18
|
-
# will return nil (nil is accepted, because it means that a given consumer don't
|
|
19
|
-
# pipe stuff further on)
|
|
20
|
-
def initialize(consumer_class)
|
|
21
|
-
@consumer_class = consumer_class
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Tries to figure out a responder based on a consumer class name
|
|
25
|
-
# @return [Class] Responder class (not an instance)
|
|
26
|
-
# @return [nil] or nil if there's no matching responding class
|
|
27
|
-
def build
|
|
28
|
-
Helpers::ClassMatcher.new(
|
|
29
|
-
@consumer_class,
|
|
30
|
-
from: 'Consumer',
|
|
31
|
-
to: 'Responder'
|
|
32
|
-
).match
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Karafka
|
|
4
|
-
module Responders
|
|
5
|
-
# Topic describes a single topic on which we want to respond with responding requirements
|
|
6
|
-
# @example Define topic (required by default)
|
|
7
|
-
# Karafka::Responders::Topic.new(:topic_name, {}) #=> #<Karafka::Responders::Topic...
|
|
8
|
-
# @example Define optional topic
|
|
9
|
-
# Karafka::Responders::Topic.new(:topic_name, required: false)
|
|
10
|
-
class Topic
|
|
11
|
-
# Name of the topic on which we want to respond
|
|
12
|
-
attr_reader :name
|
|
13
|
-
|
|
14
|
-
# @param name [Symbol, String] name of a topic on which we want to respond
|
|
15
|
-
# @param options [Hash] non-default options for this topic
|
|
16
|
-
# @return [Karafka::Responders::Topic] topic description object
|
|
17
|
-
def initialize(name, options)
|
|
18
|
-
@name = name.to_s
|
|
19
|
-
@options = options
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# @return [Boolean] is this a required topic (if not, it is optional)
|
|
23
|
-
def required?
|
|
24
|
-
@options.key?(:required) ? @options[:required] : true
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# @return [Boolean] was usage of this topic registered or not
|
|
28
|
-
def registered?
|
|
29
|
-
@options[:registered] == true
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# @return [Class] Class to use to serialize messages for this topic
|
|
33
|
-
def serializer
|
|
34
|
-
@options[:serializer]
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# @return [Boolean] do we want to use async producer. Defaults to false as the sync producer
|
|
38
|
-
# is safer and introduces less problems
|
|
39
|
-
def async?
|
|
40
|
-
@options.key?(:async) ? @options[:async] : false
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# @return [Hash] hash with this topic attributes and options
|
|
44
|
-
def to_h
|
|
45
|
-
{
|
|
46
|
-
name: name,
|
|
47
|
-
required: required?,
|
|
48
|
-
registered: registered?,
|
|
49
|
-
serializer: serializer,
|
|
50
|
-
async: async?
|
|
51
|
-
}
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Karafka
|
|
4
|
-
module Routing
|
|
5
|
-
# Default topic mapper that does not remap things
|
|
6
|
-
# Mapper can be used for Kafka providers that require namespaced topic names. Instead of being
|
|
7
|
-
# provider dependent, we can then define mapper and use internally "pure" topic names in
|
|
8
|
-
# routes and responders
|
|
9
|
-
#
|
|
10
|
-
# @example Mapper for mapping prefixed topics
|
|
11
|
-
# class MyMapper
|
|
12
|
-
# PREFIX = "my_user_name."
|
|
13
|
-
#
|
|
14
|
-
# def incoming(topic)
|
|
15
|
-
# topic.to_s.gsub(PREFIX, '')
|
|
16
|
-
# end
|
|
17
|
-
#
|
|
18
|
-
# def outgoing(topic)
|
|
19
|
-
# "#{PREFIX}#{topic}"
|
|
20
|
-
# end
|
|
21
|
-
# end
|
|
22
|
-
#
|
|
23
|
-
# @example Mapper for replacing "." with "_" in topic names
|
|
24
|
-
# class MyMapper
|
|
25
|
-
# PREFIX = "my_user_name."
|
|
26
|
-
#
|
|
27
|
-
# def incoming(topic)
|
|
28
|
-
# topic.to_s.gsub('.', '_')
|
|
29
|
-
# end
|
|
30
|
-
#
|
|
31
|
-
# def outgoing(topic)
|
|
32
|
-
# topic.to_s.gsub('_', '.')
|
|
33
|
-
# end
|
|
34
|
-
# end
|
|
35
|
-
class TopicMapper
|
|
36
|
-
# @param topic [String, Symbol] topic
|
|
37
|
-
# @return [String, Symbol] same topic as on input
|
|
38
|
-
# @example
|
|
39
|
-
# incoming('topic_name') #=> 'topic_name'
|
|
40
|
-
def incoming(topic)
|
|
41
|
-
topic
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# @param topic [String, Symbol] topic
|
|
45
|
-
# @return [String, Symbol] same topic as on input
|
|
46
|
-
# @example
|
|
47
|
-
# outgoing('topic_name') #=> 'topic_name'
|
|
48
|
-
def outgoing(topic)
|
|
49
|
-
topic
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Karafka
|
|
4
|
-
# Module for all supported by default serialization and deserialization ways
|
|
5
|
-
module Serialization
|
|
6
|
-
module Json
|
|
7
|
-
# Default Karafka Json serializer for serializing data
|
|
8
|
-
class Serializer
|
|
9
|
-
# @param content [Object] any object that we want to convert to a json string
|
|
10
|
-
# @return [String] Valid JSON string containing serialized data
|
|
11
|
-
# @raise [Karafka::Errors::SerializationError] raised when we don't have a way to
|
|
12
|
-
# serialize provided data to json
|
|
13
|
-
# @note When string is passed to this method, we assume that it is already a json
|
|
14
|
-
# string and we don't serialize it again. This allows us to serialize data before
|
|
15
|
-
# it is being forwarded to this serializer if we want to have a custom (not that simple)
|
|
16
|
-
# json serialization
|
|
17
|
-
#
|
|
18
|
-
# @example From an ActiveRecord object
|
|
19
|
-
# Serializer.call(Repository.first) #=> "{\"repository\":{\"id\":\"04b504e0\"}}"
|
|
20
|
-
# @example From a string (no changes)
|
|
21
|
-
# Serializer.call("{\"a\":1}") #=> "{\"a\":1}"
|
|
22
|
-
def call(content)
|
|
23
|
-
return content if content.is_a?(String)
|
|
24
|
-
return content.to_json if content.respond_to?(:to_json)
|
|
25
|
-
|
|
26
|
-
raise Karafka::Errors::SerializationError, content
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Karafka
|
|
4
|
-
module Setup
|
|
5
|
-
# Configurators are used to post setup some of the components of Karafka after the core
|
|
6
|
-
# framework is initialized
|
|
7
|
-
module Configurators
|
|
8
|
-
# Class responsible for setting up WaterDrop configuration
|
|
9
|
-
class WaterDrop
|
|
10
|
-
# Sets up a WaterDrop settings
|
|
11
|
-
# @param config [Karafka::Setup::Config] Config we can user to setup things
|
|
12
|
-
# @note This will also inject Karafka monitor as a default monitor into WaterDrop,
|
|
13
|
-
# so we have the same monitor within whole Karafka framework (same with logger)
|
|
14
|
-
def call(config)
|
|
15
|
-
::WaterDrop.setup do |water_config|
|
|
16
|
-
water_config.deliver = true
|
|
17
|
-
|
|
18
|
-
config.to_h.reject { |k, _v| k == :kafka }.each do |k, v|
|
|
19
|
-
key_assignment = :"#{k}="
|
|
20
|
-
next unless water_config.respond_to?(key_assignment)
|
|
21
|
-
|
|
22
|
-
water_config.public_send(key_assignment, v)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
config.kafka.to_h.each do |k, v|
|
|
26
|
-
key_assignment = :"#{k}="
|
|
27
|
-
next unless water_config.kafka.respond_to?(key_assignment)
|
|
28
|
-
|
|
29
|
-
water_config.kafka.public_send(key_assignment, v)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Application responder from which all Karafka responders should inherit
|
|
4
|
-
# You can rename it if it would conflict with your current code base (in case you're integrating
|
|
5
|
-
# Karafka with other frameworks)
|
|
6
|
-
class ApplicationResponder < Karafka::BaseResponder
|
|
7
|
-
# This method needs to be implemented in each of the responders
|
|
8
|
-
# def respond(data)
|
|
9
|
-
# respond_to :topic, data.to_json
|
|
10
|
-
# end
|
|
11
|
-
end
|