rimless 2.8.0 → 3.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
- data/Appraisals +2 -2
- data/CHANGELOG.md +71 -0
- data/Gemfile +0 -1
- data/README.md +64 -62
- data/Rakefile +13 -4
- data/UPGRADING.md +491 -0
- data/doc/upgrade-guide-sources/README.md +221 -0
- data/doc/upgrade-guide-sources/dep-avro_turf-1.20.md +23 -0
- data/doc/upgrade-guide-sources/dep-karafka-2.0.md +117 -0
- data/doc/upgrade-guide-sources/dep-waterdrop-2.8.md +30 -0
- data/gemfiles/rails_8.0.gemfile +1 -1
- data/gemfiles/rails_8.1.gemfile +1 -1
- data/lib/rimless/compatibility/.gitkeep +0 -0
- data/lib/rimless/configuration.rb +80 -6
- data/lib/rimless/consumer/app.rb +182 -0
- data/lib/rimless/{karafka → consumer}/avro_deserializer.rb +8 -6
- data/lib/rimless/consumer/base.rb +118 -0
- data/lib/rimless/consumer/job.rb +35 -0
- data/lib/rimless/consumer/job_bridge.rb +113 -0
- data/lib/rimless/extensions/avro_helpers.rb +83 -0
- data/lib/rimless/extensions/configuration_handling.rb +77 -0
- data/lib/rimless/extensions/consumer.rb +20 -0
- data/lib/rimless/extensions/dependencies.rb +84 -0
- data/lib/rimless/extensions/kafka_helpers.rb +46 -0
- data/lib/rimless/extensions/producer.rb +103 -0
- data/lib/rimless/initializers/compatibility.rb +3 -4
- data/lib/rimless/railtie.rb +7 -7
- data/lib/rimless/rspec/helpers.rb +53 -13
- data/lib/rimless/rspec/matchers.rb +14 -11
- data/lib/rimless/rspec.rb +13 -29
- data/lib/rimless/tasks/consumer.rake +18 -6
- data/lib/rimless/tasks/templates/application_consumer.rb +1 -1
- data/lib/rimless/tasks/templates/custom_consumer.rb +1 -1
- data/lib/rimless/tasks/templates/custom_consumer_spec.rb +5 -4
- data/lib/rimless/tasks/templates/karafka.rb +5 -4
- data/lib/rimless/version.rb +3 -1
- data/lib/rimless.rb +12 -14
- data/rimless.gemspec +8 -10
- metadata +43 -72
- data/lib/rimless/avro_helpers.rb +0 -81
- data/lib/rimless/base_consumer.rb +0 -30
- data/lib/rimless/compatibility/karafka_1_4.rb +0 -52
- data/lib/rimless/configuration_handling.rb +0 -82
- data/lib/rimless/consumer.rb +0 -209
- data/lib/rimless/consumer_job.rb +0 -10
- data/lib/rimless/dependencies.rb +0 -69
- data/lib/rimless/kafka_helpers.rb +0 -104
- data/lib/rimless/karafka/base64_interchanger.rb +0 -32
- data/lib/rimless/karafka/passthrough_mapper.rb +0 -29
- data/lib/rimless/tasks/stats.rake +0 -22
data/lib/rimless/consumer.rb
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rimless
|
|
4
|
-
# The global rimless Apache Kafka consumer application based on
|
|
5
|
-
# the Karafka framework.
|
|
6
|
-
#
|
|
7
|
-
# rubocop:disable Style/ClassVars -- because we just work as a singleton
|
|
8
|
-
class ConsumerApp < ::Karafka::App
|
|
9
|
-
# We track our own initialization with this class variable
|
|
10
|
-
@@rimless_initialized = false
|
|
11
|
-
|
|
12
|
-
class << self
|
|
13
|
-
# Initialize the Karafka framework and our global consumer application
|
|
14
|
-
# with all our conventions/opinions.
|
|
15
|
-
#
|
|
16
|
-
# @return [Rimless::ConsumerApp] our self for chaining
|
|
17
|
-
def initialize!
|
|
18
|
-
# When already initialized, skip it
|
|
19
|
-
return self if @@rimless_initialized
|
|
20
|
-
|
|
21
|
-
# Initialize all the parts one by one
|
|
22
|
-
initialize_rails!
|
|
23
|
-
initialize_monitors!
|
|
24
|
-
initialize_karafka!
|
|
25
|
-
initialize_logger!
|
|
26
|
-
initialize_code_reload!
|
|
27
|
-
|
|
28
|
-
# Load the custom Karafka boot file when it exists, it contains
|
|
29
|
-
# custom configurations and the topic/consumer routing table
|
|
30
|
-
require ::Karafka.boot_file if ::Karafka.boot_file.exist?
|
|
31
|
-
|
|
32
|
-
# Set our custom initialization process as completed to
|
|
33
|
-
# skip subsequent calls
|
|
34
|
-
@@rimless_initialized = true
|
|
35
|
-
self
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# Check if Rails is available and not already initialized, then
|
|
39
|
-
# initialize it.
|
|
40
|
-
def initialize_rails!
|
|
41
|
-
rails_env = ::Karafka.root.join('config', 'environment.rb')
|
|
42
|
-
|
|
43
|
-
# Stop, when Rails is already initialized
|
|
44
|
-
return if defined? Rails
|
|
45
|
-
|
|
46
|
-
# Stop, when there is no Rails at all
|
|
47
|
-
return unless rails_env.exist?
|
|
48
|
-
|
|
49
|
-
ENV['RAILS_ENV'] ||= 'development'
|
|
50
|
-
ENV['KARAFKA_ENV'] = ENV.fetch('RAILS_ENV', nil)
|
|
51
|
-
|
|
52
|
-
# This is relevant for Karafka server processes, as the +karafka.rb+
|
|
53
|
-
# root file just requires +rimless+ and then we require
|
|
54
|
-
# +karafka-sidekiq-backend+ which in fact requires +sidekiq+ before
|
|
55
|
-
# +rails+ was required. We cannot change the order here, but we can
|
|
56
|
-
# explicitly load the Sidekiq/Rails integration as we know at this
|
|
57
|
-
# point that we should load Rails and we're going to use Sidekiq, too.
|
|
58
|
-
# See: https://bit.ly/3D8ZHj3
|
|
59
|
-
require 'sidekiq/rails'
|
|
60
|
-
|
|
61
|
-
require rails_env
|
|
62
|
-
require 'rimless/railtie'
|
|
63
|
-
Rails.application.eager_load!
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# We like to listen to instrumentation and logging events to allow our
|
|
67
|
-
# users to handle them like they need.
|
|
68
|
-
def initialize_monitors!
|
|
69
|
-
[
|
|
70
|
-
WaterDrop::Instrumentation::StdoutListener.new,
|
|
71
|
-
::Karafka::Instrumentation::StdoutListener.new,
|
|
72
|
-
::Karafka::Instrumentation::ProctitleListener.new
|
|
73
|
-
].each do |listener|
|
|
74
|
-
::Karafka.monitor.subscribe(listener)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# Configure the pure basics on the Karafka application.
|
|
79
|
-
def initialize_karafka!
|
|
80
|
-
setup do |config|
|
|
81
|
-
mapper = Rimless::Karafka::PassthroughMapper.new
|
|
82
|
-
config.consumer_mapper = config.topic_mapper = mapper
|
|
83
|
-
config.deserializer = Rimless::Karafka::AvroDeserializer.new
|
|
84
|
-
config.kafka.seed_brokers = Rimless.configuration.kafka_brokers
|
|
85
|
-
config.client_id = Rimless.configuration.client_id
|
|
86
|
-
config.logger = Rimless.logger
|
|
87
|
-
config.backend = :sidekiq
|
|
88
|
-
config.batch_fetching = true
|
|
89
|
-
config.batch_consuming = false
|
|
90
|
-
config.shutdown_timeout = 10
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# When we run in development mode, we want to write the logs
|
|
95
|
-
# to file and to stdout.
|
|
96
|
-
def initialize_logger!
|
|
97
|
-
# Skip when configured not to extend the logger
|
|
98
|
-
return unless Rimless.configuration.extend_dev_logger
|
|
99
|
-
|
|
100
|
-
# Skip when not in development environment or in the server process
|
|
101
|
-
return unless Rimless.env.development? && server?
|
|
102
|
-
|
|
103
|
-
$stdout.sync = true
|
|
104
|
-
Rimless.logger.extend(ActiveSupport::Logger.broadcast(
|
|
105
|
-
ActiveSupport::Logger.new($stdout)
|
|
106
|
-
))
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# Perform code hot-reloading when we are in Rails and in development
|
|
110
|
-
# mode.
|
|
111
|
-
def initialize_code_reload!
|
|
112
|
-
return unless defined?(Rails) && Rails.env.development?
|
|
113
|
-
|
|
114
|
-
::Karafka.monitor.subscribe(::Karafka::CodeReloader.new(
|
|
115
|
-
*Rails.application.reloaders
|
|
116
|
-
))
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# Allows the user to re-configure the Karafka application if this is
|
|
120
|
-
# needed. (eg. to set some ruby-kafka driver default settings, etc)
|
|
121
|
-
#
|
|
122
|
-
# @return [Rimless::ConsumerApp] our self for chaining
|
|
123
|
-
def configure(&)
|
|
124
|
-
setup(&)
|
|
125
|
-
self
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
# Configure the topics-consumer routing table in a lean way.
|
|
129
|
-
#
|
|
130
|
-
# Examples:
|
|
131
|
-
#
|
|
132
|
-
# topics({ app: :test_app, name: :admins } => YourConsumer)
|
|
133
|
-
# topics({ app: :test_app, names: %i[users admins] } => YourConsumer)
|
|
134
|
-
#
|
|
135
|
-
# Examples:
|
|
136
|
-
#
|
|
137
|
-
# topics do
|
|
138
|
-
# topic('name') do
|
|
139
|
-
# consumer CustomConsumer
|
|
140
|
-
# end
|
|
141
|
-
# end
|
|
142
|
-
#
|
|
143
|
-
# @param topics [Hash{Hash => Class}] the topic to consumer mapping
|
|
144
|
-
# @yield the given block on the routing table
|
|
145
|
-
def topics(topics = [], &block)
|
|
146
|
-
consumer_groups.draw do
|
|
147
|
-
consumer_group(Rimless.configuration.client_id) do
|
|
148
|
-
instance_exec(&block) if block_given?
|
|
149
|
-
|
|
150
|
-
topics.each do |topic_parts, dest_consumer|
|
|
151
|
-
Rimless.consumer.topic_names(topic_parts).each do |topic_name|
|
|
152
|
-
topic(topic_name) do
|
|
153
|
-
consumer dest_consumer
|
|
154
|
-
worker Rimless::ConsumerJob
|
|
155
|
-
interchanger Rimless::Karafka::Base64Interchanger.new
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
self
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
# Build the conventional Apache Kafka topic names from the given parts.
|
|
166
|
-
# This allows various forms like single strings/symbols and a hash in the
|
|
167
|
-
# form of +{ app: [String, Symbol], name: [String, Symbol], names:
|
|
168
|
-
# [Array<String, Symbol>] }+. This allows the maximum of flexibility.
|
|
169
|
-
#
|
|
170
|
-
# @param parts [String, Symbol, Hash{Symbol => Mixed}] the topic
|
|
171
|
-
# name parts
|
|
172
|
-
# @return [Array<String>] the full topic names
|
|
173
|
-
def topic_names(parts)
|
|
174
|
-
# We have a single app, but multiple names so we handle them
|
|
175
|
-
if parts.is_a?(Hash) && parts.key?(:names)
|
|
176
|
-
return parts[:names].map do |name|
|
|
177
|
-
Rimless.topic(parts.merge(name: name))
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
# We cannot handle the given input
|
|
182
|
-
[Rimless.topic(parts)]
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
# Check if we run as the Karafka server (consumer) process or not.
|
|
186
|
-
#
|
|
187
|
-
# @return [Boolean] whenever we run as the Karafka server or not
|
|
188
|
-
def server?
|
|
189
|
-
$PROGRAM_NAME.end_with?('karafka') && ARGV.include?('server')
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
# rubocop:enable Style/ClassVars
|
|
194
|
-
|
|
195
|
-
# A rimless top-level concern which adds lean access to
|
|
196
|
-
# the consumer application.
|
|
197
|
-
module Consumer
|
|
198
|
-
extend ActiveSupport::Concern
|
|
199
|
-
|
|
200
|
-
class_methods do
|
|
201
|
-
# A simple shortcut to fetch the Karafka consumer application.
|
|
202
|
-
#
|
|
203
|
-
# @return [Rimless::ConsumerApp] the Karafka consumer application class
|
|
204
|
-
def consumer
|
|
205
|
-
ConsumerApp.initialize!
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
end
|
|
209
|
-
end
|
data/lib/rimless/consumer_job.rb
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rimless
|
|
4
|
-
# The base consumer job where each message is processed asynchronous via
|
|
5
|
-
# Sidekiq. We need to inherit the Karafka base worker class into a custom
|
|
6
|
-
# one, otherwise it fails.
|
|
7
|
-
class ConsumerJob < ::Karafka::BaseWorker
|
|
8
|
-
sidekiq_options queue: Rimless.configuration.consumer_job_queue
|
|
9
|
-
end
|
|
10
|
-
end
|
data/lib/rimless/dependencies.rb
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rimless
|
|
4
|
-
# The top-level dependencies helpers.
|
|
5
|
-
module Dependencies
|
|
6
|
-
extend ActiveSupport::Concern
|
|
7
|
-
|
|
8
|
-
class_methods do
|
|
9
|
-
# (Re)configure our gem dependencies. We take care of setting up
|
|
10
|
-
# +WaterDrop+, our Apache Kafka driver and +AvroTurf+, our Confluent
|
|
11
|
-
# Schema Registry driver.
|
|
12
|
-
def configure_dependencies
|
|
13
|
-
configure_waterdrop
|
|
14
|
-
configure_avro_turf
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Set sensible defaults for the +WaterDrop+ gem.
|
|
18
|
-
def configure_waterdrop
|
|
19
|
-
# Skip WaterDrop configuration when no brokers/client id is available,
|
|
20
|
-
# because it will raise. Its fine to have none available for situations
|
|
21
|
-
# like Rails asset precompilations, etc. - on runtime the settings
|
|
22
|
-
# should be available, otherwise the message producing just
|
|
23
|
-
# fails/raise.
|
|
24
|
-
return if Rimless.configuration.kafka_brokers.empty? \
|
|
25
|
-
|| Rimless.configuration.client_id.blank?
|
|
26
|
-
|
|
27
|
-
WaterDrop.setup do |config|
|
|
28
|
-
# Activate message delivery and use the default logger
|
|
29
|
-
config.deliver = true
|
|
30
|
-
config.logger = Rimless.logger
|
|
31
|
-
# An optional identifier of a Kafka consumer (in a consumer group)
|
|
32
|
-
# that is passed to a Kafka broker with every request. A logical
|
|
33
|
-
# application name to be included in Kafka logs and monitoring
|
|
34
|
-
# aggregates.
|
|
35
|
-
config.client_id = Rimless.configuration.client_id
|
|
36
|
-
# All the known brokers, at least one. The ruby-kafka driver will
|
|
37
|
-
# discover the whole cluster structure once and when issues occur to
|
|
38
|
-
# dynamically adjust scaling operations.
|
|
39
|
-
config.kafka.seed_brokers = Rimless.configuration.kafka_brokers
|
|
40
|
-
# All brokers MUST acknowledge a new message
|
|
41
|
-
config.kafka.required_acks = -1
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Set sensible defaults for the +AvroTurf+ gem and (re)compile the Apache
|
|
46
|
-
# Avro schema templates (ERB), so the gem can handle them properly.
|
|
47
|
-
def configure_avro_turf
|
|
48
|
-
# No need to configure AvroTurf when no schema registry URL is
|
|
49
|
-
# available. Its fine to skip this for scenarios where not the full
|
|
50
|
-
# application configuration is available (eg. on Rails asset
|
|
51
|
-
# precompilations, etc)
|
|
52
|
-
return if Rimless.configuration.schema_registry_url.blank?
|
|
53
|
-
|
|
54
|
-
# Setup a global available Apache Avro decoder/encoder with support for
|
|
55
|
-
# the Confluent Schema Registry, but first create a helper instance
|
|
56
|
-
Rimless.avro_utils = Rimless::AvroUtils.new
|
|
57
|
-
# Compile our Avro schema templates to ready-to-consume Avro schemas
|
|
58
|
-
Rimless.avro_utils.recompile_schemas
|
|
59
|
-
# Register a global Avro messaging instance
|
|
60
|
-
Rimless.avro = AvroTurf::Messaging.new(
|
|
61
|
-
logger: Rimless.logger,
|
|
62
|
-
namespace: Rimless.avro_utils.namespace,
|
|
63
|
-
schemas_path: Rimless.avro_utils.output_path,
|
|
64
|
-
registry_url: Rimless.configuration.schema_registry_url
|
|
65
|
-
)
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rimless
|
|
4
|
-
# The top-level Apache Kafka helpers.
|
|
5
|
-
module KafkaHelpers
|
|
6
|
-
extend ActiveSupport::Concern
|
|
7
|
-
|
|
8
|
-
class_methods do
|
|
9
|
-
# Generate a common topic name for Apache Kafka while taking care of
|
|
10
|
-
# configured prefixes.
|
|
11
|
-
#
|
|
12
|
-
# @param args [Array<Mixed>] the relative topic name
|
|
13
|
-
# @return [String] the complete topic name
|
|
14
|
-
#
|
|
15
|
-
# @example Name only
|
|
16
|
-
# Rimless.topic(:users)
|
|
17
|
-
# @example Name with app
|
|
18
|
-
# Rimless.topic(:users, app: 'test-api')
|
|
19
|
-
# @example Mix and match
|
|
20
|
-
# Rimless.topic(name: 'test', app: :fancy_app)
|
|
21
|
-
# @example Full name - use as is
|
|
22
|
-
# Rimless.topic(full_name: 'my.custom.topic.name')
|
|
23
|
-
def topic(*args)
|
|
24
|
-
opts = args.last
|
|
25
|
-
name = args.first if [String, Symbol].member?(args.first.class)
|
|
26
|
-
|
|
27
|
-
if opts.is_a?(Hash)
|
|
28
|
-
# When we got a full name, we use it as is
|
|
29
|
-
return opts[:full_name] if opts.key? :full_name
|
|
30
|
-
|
|
31
|
-
name = opts[:name] if opts.key?(:name)
|
|
32
|
-
app = opts[:app] if opts.key?(:app)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
name ||= nil
|
|
36
|
-
app ||= Rimless.configuration.app_name
|
|
37
|
-
|
|
38
|
-
raise ArgumentError, 'No name given' if name.nil?
|
|
39
|
-
|
|
40
|
-
"#{Rimless.topic_prefix(app)}#{name}".tr('_', '-')
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Send a single message to Apache Kafka. The data is encoded according to
|
|
44
|
-
# the given Apache Avro schema. The destination Kafka topic may be a
|
|
45
|
-
# relative name, or a hash which is passed to the +.topic+ method to
|
|
46
|
-
# manipulate the application details. The message is send is a
|
|
47
|
-
# synchronous, blocking way.
|
|
48
|
-
#
|
|
49
|
-
# @param data [Hash{Symbol => Mixed}] the raw data, unencoded
|
|
50
|
-
# @param schema [String, Symbol] the Apache Avro schema to use
|
|
51
|
-
# @param topic [String, Symbol, Hash{Symbol => Mixed}] the destination
|
|
52
|
-
# Apache Kafka topic
|
|
53
|
-
def sync_message(data:, schema:, topic:, **args)
|
|
54
|
-
encoded = Rimless.encode(data, schema: schema)
|
|
55
|
-
sync_raw_message(data: encoded, topic: topic, **args)
|
|
56
|
-
end
|
|
57
|
-
alias_method :message, :sync_message
|
|
58
|
-
|
|
59
|
-
# Send a single message to Apache Kafka. The data is encoded according to
|
|
60
|
-
# the given Apache Avro schema. The destination Kafka topic may be a
|
|
61
|
-
# relative name, or a hash which is passed to the +.topic+ method to
|
|
62
|
-
# manipulate the application details. The message is send is an
|
|
63
|
-
# asynchronous, non-blocking way.
|
|
64
|
-
#
|
|
65
|
-
# @param data [Hash{Symbol => Mixed}] the raw data, unencoded
|
|
66
|
-
# @param schema [String, Symbol] the Apache Avro schema to use
|
|
67
|
-
# @param topic [String, Symbol, Hash{Symbol => Mixed}] the destination
|
|
68
|
-
# Apache Kafka topic
|
|
69
|
-
def async_message(data:, schema:, topic:, **args)
|
|
70
|
-
encoded = Rimless.encode(data, schema: schema)
|
|
71
|
-
async_raw_message(data: encoded, topic: topic, **args)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Send a single message to Apache Kafka. The data is not touched, so you
|
|
75
|
-
# need to encode it yourself before you pass it in. The destination Kafka
|
|
76
|
-
# topic may be a relative name, or a hash which is passed to the +.topic+
|
|
77
|
-
# method to manipulate the application details. The message is send is a
|
|
78
|
-
# synchronous, blocking way.
|
|
79
|
-
#
|
|
80
|
-
# @param data [Hash{Symbol => Mixed}] the raw data, unencoded
|
|
81
|
-
# @param topic [String, Symbol, Hash{Symbol => Mixed}] the destination
|
|
82
|
-
# Apache Kafka topic
|
|
83
|
-
def sync_raw_message(data:, topic:, **args)
|
|
84
|
-
args = args.merge(topic: topic(topic))
|
|
85
|
-
WaterDrop::SyncProducer.call(data, **args)
|
|
86
|
-
end
|
|
87
|
-
alias_method :raw_message, :sync_raw_message
|
|
88
|
-
|
|
89
|
-
# Send a single message to Apache Kafka. The data is not touched, so you
|
|
90
|
-
# need to encode it yourself before you pass it in. The destination Kafka
|
|
91
|
-
# topic may be a relative name, or a hash which is passed to the +.topic+
|
|
92
|
-
# method to manipulate the application details. The message is send is an
|
|
93
|
-
# asynchronous, non-blocking way.
|
|
94
|
-
#
|
|
95
|
-
# @param data [Hash{Symbol => Mixed}] the raw data, unencoded
|
|
96
|
-
# @param topic [String, Symbol, Hash{Symbol => Mixed}] the destination
|
|
97
|
-
# Apache Kafka topic
|
|
98
|
-
def async_raw_message(data:, topic:, **args)
|
|
99
|
-
args = args.merge(topic: topic(topic))
|
|
100
|
-
WaterDrop::AsyncProducer.call(data, **args)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rimless
|
|
4
|
-
module Karafka
|
|
5
|
-
# Allow the +karafka-sidekiq-backend+ gem to transfer binary Apache Kafka
|
|
6
|
-
# messages to the actual Sidekiq job.
|
|
7
|
-
#
|
|
8
|
-
# rubocop:disable Security/MarshalLoad -- because we encode/decode the
|
|
9
|
-
# messages in our own controlled context
|
|
10
|
-
class Base64Interchanger < ::Karafka::Interchanger
|
|
11
|
-
# Encode a binary Apache Kafka message(s) so they can be passed to the
|
|
12
|
-
# Sidekiq +Rimless::ConsumerJob+.
|
|
13
|
-
#
|
|
14
|
-
# @param params_batch [Karafka::Params::ParamsBatch] the karafka params
|
|
15
|
-
# batch object
|
|
16
|
-
# @return [String] the marshaled+base64 encoded data
|
|
17
|
-
def encode(params_batch)
|
|
18
|
-
Base64.encode64(Marshal.dump(super))
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Decode the binary Apache Kafka message(s) so they can be processed by
|
|
22
|
-
# the Sidekiq +Rimless::ConsumerJob+.
|
|
23
|
-
#
|
|
24
|
-
# @param params_string [String] the marshaled+base64 encoded data
|
|
25
|
-
# @return [Array<Hash>] the unmarshaled+base64 decoded data
|
|
26
|
-
def decode(params_batch)
|
|
27
|
-
super(Marshal.load(Base64.decode64(params_batch))).map(&:stringify_keys)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
# rubocop:enable Security/MarshalLoad
|
|
31
|
-
end
|
|
32
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rimless
|
|
4
|
-
module Karafka
|
|
5
|
-
# The Karafka framework makes some assumptions about the consumer group and
|
|
6
|
-
# topic names. We have our own opinions/conventions, so we just pass them
|
|
7
|
-
# through unmodified.
|
|
8
|
-
class PassthroughMapper
|
|
9
|
-
# We do not want to modify the given consumer group name, so we
|
|
10
|
-
# pass it through.
|
|
11
|
-
#
|
|
12
|
-
# @param raw_consumer_group_name [String, Symbol] the original
|
|
13
|
-
# consumer group name
|
|
14
|
-
# @return [String, Symbol] the original consumer group name
|
|
15
|
-
def call(raw_consumer_group_name)
|
|
16
|
-
raw_consumer_group_name
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# We do not want to modify the given topic name, so we pass it through.
|
|
20
|
-
#
|
|
21
|
-
# @param topic [String, Symbol] the original topic name
|
|
22
|
-
# @return [String, Symbol] the original topic name
|
|
23
|
-
def incoming(topic)
|
|
24
|
-
topic
|
|
25
|
-
end
|
|
26
|
-
alias outgoing incoming
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# TODO: Remove this file, when Rails >= 8.0 is the minimum requirement
|
|
4
|
-
if defined?(Rails) && Rails.env.development? && Rails::VERSION::STRING < '8.0.0'
|
|
5
|
-
require 'rspec/core/rake_task'
|
|
6
|
-
|
|
7
|
-
# rubocop:disable Rails/RakeEnvironment -- because this is just an helper
|
|
8
|
-
# command, no need for an application bootstrap
|
|
9
|
-
task :stats do
|
|
10
|
-
require 'rails/code_statistics'
|
|
11
|
-
|
|
12
|
-
[
|
|
13
|
-
[:unshift, 'Consumer', 'app/consumers']
|
|
14
|
-
].each do |method, type, dir|
|
|
15
|
-
next unless File.directory? dir
|
|
16
|
-
|
|
17
|
-
STATS_DIRECTORIES.send(method, [type, dir])
|
|
18
|
-
CodeStatistics::TEST_TYPES << type if type.include? 'specs'
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
# rubocop:enable Rails/RakeEnvironment
|
|
22
|
-
end
|