karafka 2.0.0.beta1 → 2.0.0.beta4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ci.yml +9 -23
- data/CHANGELOG.md +47 -0
- data/Gemfile.lock +8 -8
- data/bin/integrations +36 -14
- data/bin/scenario +29 -0
- data/bin/wait_for_kafka +20 -0
- data/config/errors.yml +1 -0
- data/docker-compose.yml +12 -0
- data/karafka.gemspec +2 -2
- data/lib/active_job/karafka.rb +2 -2
- data/lib/karafka/active_job/routing/extensions.rb +31 -0
- data/lib/karafka/base_consumer.rb +65 -42
- data/lib/karafka/connection/client.rb +65 -19
- data/lib/karafka/connection/listener.rb +99 -34
- data/lib/karafka/connection/listeners_batch.rb +24 -0
- data/lib/karafka/connection/messages_buffer.rb +50 -54
- data/lib/karafka/connection/raw_messages_buffer.rb +101 -0
- data/lib/karafka/contracts/config.rb +9 -1
- data/lib/karafka/helpers/async.rb +33 -0
- data/lib/karafka/instrumentation/logger_listener.rb +34 -10
- data/lib/karafka/instrumentation/monitor.rb +3 -1
- data/lib/karafka/licenser.rb +26 -7
- data/lib/karafka/messages/batch_metadata.rb +26 -3
- data/lib/karafka/messages/builders/batch_metadata.rb +17 -29
- data/lib/karafka/messages/builders/message.rb +1 -0
- data/lib/karafka/messages/builders/messages.rb +4 -12
- data/lib/karafka/pro/active_job/consumer.rb +49 -0
- data/lib/karafka/pro/active_job/dispatcher.rb +10 -10
- data/lib/karafka/pro/active_job/job_options_contract.rb +9 -9
- data/lib/karafka/pro/base_consumer.rb +76 -0
- data/lib/karafka/pro/loader.rb +30 -13
- data/lib/karafka/pro/performance_tracker.rb +9 -9
- data/lib/karafka/pro/processing/jobs/consume_non_blocking.rb +37 -0
- data/lib/karafka/pro/processing/jobs_builder.rb +31 -0
- data/lib/karafka/pro/routing/extensions.rb +32 -0
- data/lib/karafka/pro/scheduler.rb +54 -0
- data/lib/karafka/processing/executor.rb +34 -7
- data/lib/karafka/processing/executors_buffer.rb +15 -7
- data/lib/karafka/processing/jobs/base.rb +21 -4
- data/lib/karafka/processing/jobs/consume.rb +12 -5
- data/lib/karafka/processing/jobs_builder.rb +28 -0
- data/lib/karafka/processing/jobs_queue.rb +15 -12
- data/lib/karafka/processing/result.rb +34 -0
- data/lib/karafka/processing/worker.rb +23 -17
- data/lib/karafka/processing/workers_batch.rb +5 -0
- data/lib/karafka/routing/consumer_group.rb +1 -1
- data/lib/karafka/routing/subscription_group.rb +2 -2
- data/lib/karafka/routing/subscription_groups_builder.rb +3 -2
- data/lib/karafka/routing/topic.rb +5 -0
- data/lib/karafka/routing/topics.rb +38 -0
- data/lib/karafka/runner.rb +19 -27
- data/lib/karafka/scheduler.rb +10 -11
- data/lib/karafka/server.rb +24 -23
- data/lib/karafka/setup/config.rb +4 -1
- data/lib/karafka/status.rb +1 -3
- data/lib/karafka/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +20 -5
- metadata.gz.sig +0 -0
- data/lib/karafka/active_job/routing_extensions.rb +0 -18
data/lib/karafka/runner.rb
CHANGED
@@ -3,32 +3,37 @@
|
|
3
3
|
module Karafka
|
4
4
|
# Class used to run the Karafka listeners in separate threads
|
5
5
|
class Runner
|
6
|
-
# Starts listening on all the listeners asynchronously
|
7
|
-
#
|
6
|
+
# Starts listening on all the listeners asynchronously and handles the jobs queue closing
|
7
|
+
# after listeners are done with their work.
|
8
8
|
def call
|
9
9
|
# Despite possibility of having several independent listeners, we aim to have one queue for
|
10
10
|
# jobs across and one workers poll for that
|
11
11
|
jobs_queue = Processing::JobsQueue.new
|
12
12
|
|
13
13
|
workers = Processing::WorkersBatch.new(jobs_queue)
|
14
|
-
|
14
|
+
listeners = Connection::ListenersBatch.new(jobs_queue)
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
# each listener running in separate threads, so the exceptions should never leak
|
19
|
-
# and if that happens, it means that something really bad happened and we should stop
|
20
|
-
# the whole process
|
21
|
-
Thread
|
22
|
-
.new { listener.call }
|
23
|
-
.tap { |thread| thread.abort_on_exception = true }
|
24
|
-
end
|
16
|
+
workers.each(&:async_call)
|
17
|
+
listeners.each(&:async_call)
|
25
18
|
|
26
19
|
# We aggregate threads here for a supervised shutdown process
|
27
|
-
Karafka::Server.
|
20
|
+
Karafka::Server.workers = workers
|
21
|
+
Karafka::Server.listeners = listeners
|
28
22
|
|
29
23
|
# All the listener threads need to finish
|
30
|
-
|
24
|
+
listeners.each(&:join)
|
25
|
+
|
26
|
+
# We close the jobs queue only when no listener threads are working.
|
27
|
+
# This ensures, that everything was closed prior to us not accepting anymore jobs and that
|
28
|
+
# no more jobs will be enqueued. Since each listener waits for jobs to finish, once those
|
29
|
+
# are done, we can close.
|
30
|
+
jobs_queue.close
|
31
|
+
|
31
32
|
# All the workers need to stop processing anything before we can stop the runner completely
|
33
|
+
# This ensures that even async long-running jobs have time to finish before we are done
|
34
|
+
# with everything. One thing worth keeping in mind though: It is the end user responsibility
|
35
|
+
# to handle the shutdown detection in their long-running processes. Otherwise if timeout
|
36
|
+
# is exceeded, there will be a forced shutdown.
|
32
37
|
workers.each(&:join)
|
33
38
|
# If anything crashes here, we need to raise the error and crush the runner because it means
|
34
39
|
# that something terrible happened
|
@@ -42,18 +47,5 @@ module Karafka
|
|
42
47
|
Karafka::App.stop!
|
43
48
|
raise e
|
44
49
|
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
# @param jobs_queue [Processing::JobsQueue] the main processing queue
|
49
|
-
# @return [Array<Karafka::Connection::Listener>] listeners that will consume messages for each
|
50
|
-
# of the subscription groups
|
51
|
-
def listeners(jobs_queue)
|
52
|
-
App
|
53
|
-
.subscription_groups
|
54
|
-
.map do |subscription_group|
|
55
|
-
Karafka::Connection::Listener.new(subscription_group, jobs_queue)
|
56
|
-
end
|
57
|
-
end
|
58
50
|
end
|
59
51
|
end
|
data/lib/karafka/scheduler.rb
CHANGED
@@ -3,19 +3,18 @@
|
|
3
3
|
module Karafka
|
4
4
|
# FIFO scheduler for messages coming from various topics and partitions
|
5
5
|
class Scheduler
|
6
|
-
#
|
6
|
+
# Schedules jobs in the fifo order
|
7
7
|
#
|
8
|
-
# @param
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def call(messages_buffer)
|
14
|
-
messages_buffer.each do |topic, partitions|
|
15
|
-
partitions.each do |partition, messages|
|
16
|
-
yield(topic, partition, messages)
|
17
|
-
end
|
8
|
+
# @param queue [Karafka::Processing::JobsQueue] queue where we want to put the jobs
|
9
|
+
# @param jobs_array [Array<Karafka::Processing::Jobs::Base>] jobs we want to schedule
|
10
|
+
def schedule_consumption(queue, jobs_array)
|
11
|
+
jobs_array.each do |job|
|
12
|
+
queue << job
|
18
13
|
end
|
19
14
|
end
|
15
|
+
|
16
|
+
# Both revocation and shutdown jobs can also run in fifo by default
|
17
|
+
alias schedule_revocation schedule_consumption
|
18
|
+
alias schedule_shutdown schedule_consumption
|
20
19
|
end
|
21
20
|
end
|
data/lib/karafka/server.rb
CHANGED
@@ -15,7 +15,7 @@ module Karafka
|
|
15
15
|
|
16
16
|
class << self
|
17
17
|
# Set of consuming threads. Each consumer thread contains a single consumer
|
18
|
-
attr_accessor :
|
18
|
+
attr_accessor :listeners
|
19
19
|
|
20
20
|
# Set of workers
|
21
21
|
attr_accessor :workers
|
@@ -25,9 +25,12 @@ module Karafka
|
|
25
25
|
|
26
26
|
# Method which runs app
|
27
27
|
def run
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
# Since we do a lot of threading and queuing, we don't want to stop from the trap context
|
29
|
+
# as some things may not work there as expected, that is why we spawn a separate thread to
|
30
|
+
# handle the stopping process
|
31
|
+
process.on_sigint { Thread.new { stop } }
|
32
|
+
process.on_sigquit { Thread.new { stop } }
|
33
|
+
process.on_sigterm { Thread.new { stop } }
|
31
34
|
|
32
35
|
# Start is blocking until stop is called and when we stop, it will wait until
|
33
36
|
# all of the things are ready to stop
|
@@ -35,6 +38,8 @@ module Karafka
|
|
35
38
|
|
36
39
|
# We always need to wait for Karafka to stop here since we should wait for the stop running
|
37
40
|
# in a separate thread (or trap context) to indicate everything is closed
|
41
|
+
# Since `#start` is blocking, we were get here only after the runner is done. This will
|
42
|
+
# not add any performance degradation because of that.
|
38
43
|
Thread.pass until Karafka::App.stopped?
|
39
44
|
# Try its best to shutdown underlying components before re-raising
|
40
45
|
# rubocop:disable Lint/RescueException
|
@@ -70,16 +75,16 @@ module Karafka
|
|
70
75
|
def stop
|
71
76
|
Karafka::App.stop!
|
72
77
|
|
73
|
-
timeout =
|
78
|
+
timeout = Karafka::App.config.shutdown_timeout
|
74
79
|
|
75
80
|
# We check from time to time (for the timeout period) if all the threads finished
|
76
81
|
# their work and if so, we can just return and normal shutdown process will take place
|
77
82
|
# We divide it by 1000 because we use time in ms.
|
78
83
|
((timeout / 1_000) * SUPERVISION_CHECK_FACTOR).to_i.times do
|
79
|
-
if
|
84
|
+
if listeners.count(&:alive?).zero? &&
|
80
85
|
workers.count(&:alive?).zero?
|
81
86
|
|
82
|
-
|
87
|
+
Karafka::App.producer.close
|
83
88
|
|
84
89
|
return
|
85
90
|
end
|
@@ -89,22 +94,18 @@ module Karafka
|
|
89
94
|
|
90
95
|
raise Errors::ForcefulShutdownError
|
91
96
|
rescue Errors::ForcefulShutdownError => e
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
Karafka::App.producer.close
|
105
|
-
end
|
106
|
-
|
107
|
-
thread.join
|
97
|
+
Karafka.monitor.instrument(
|
98
|
+
'error.occurred',
|
99
|
+
caller: self,
|
100
|
+
error: e,
|
101
|
+
type: 'app.stopping.error'
|
102
|
+
)
|
103
|
+
|
104
|
+
# We're done waiting, lets kill them!
|
105
|
+
workers.each(&:terminate)
|
106
|
+
listeners.each(&:terminate)
|
107
|
+
|
108
|
+
Karafka::App.producer.close
|
108
109
|
|
109
110
|
# exit! is not within the instrumentation as it would not trigger due to exit
|
110
111
|
Kernel.exit! FORCEFUL_EXIT_CODE
|
data/lib/karafka/setup/config.rb
CHANGED
@@ -83,7 +83,7 @@ module Karafka
|
|
83
83
|
# @see https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md
|
84
84
|
setting :kafka, default: {}
|
85
85
|
|
86
|
-
# Namespace for internal settings that should not be modified
|
86
|
+
# Namespace for internal settings that should not be modified directly
|
87
87
|
setting :internal do
|
88
88
|
# option routing_builder [Karafka::Routing::Builder] builder instance
|
89
89
|
setting :routing_builder, default: Routing::Builder.new
|
@@ -98,6 +98,8 @@ module Karafka
|
|
98
98
|
setting :subscription_groups_builder, default: Routing::SubscriptionGroupsBuilder.new
|
99
99
|
# option scheduler [Class] scheduler we will be using
|
100
100
|
setting :scheduler, default: Scheduler.new
|
101
|
+
# option jobs_builder [Class] jobs builder we want to use
|
102
|
+
setting :jobs_builder, default: Processing::JobsBuilder.new
|
101
103
|
|
102
104
|
# Karafka components for ActiveJob
|
103
105
|
setting :active_job do
|
@@ -117,6 +119,7 @@ module Karafka
|
|
117
119
|
def setup(&block)
|
118
120
|
configure(&block)
|
119
121
|
merge_kafka_defaults!(config)
|
122
|
+
|
120
123
|
Contracts::Config.new.validate!(config.to_h)
|
121
124
|
|
122
125
|
# Check the license presence (if needed) and
|
data/lib/karafka/status.rb
CHANGED
@@ -31,9 +31,7 @@ module Karafka
|
|
31
31
|
# We skip as during this state we do not have yet a monitor
|
32
32
|
return if initializing?
|
33
33
|
|
34
|
-
|
35
|
-
# so the state changes are executed from a separate thread
|
36
|
-
Thread.new { Karafka.monitor.instrument("app.#{state}") }.join
|
34
|
+
Karafka.monitor.instrument("app.#{state}")
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
data/lib/karafka/version.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: karafka
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.beta4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maciej Mensfeld
|
@@ -34,7 +34,7 @@ cert_chain:
|
|
34
34
|
R2P11bWoCtr70BsccVrN8jEhzwXngMyI2gVt750Y+dbTu1KgRqZKp/ECe7ZzPzXj
|
35
35
|
pIy9vHxTANKYVyI4qj8OrFdEM5BQNu8oQpL0iQ==
|
36
36
|
-----END CERTIFICATE-----
|
37
|
-
date: 2022-
|
37
|
+
date: 2022-06-20 00:00:00.000000000 Z
|
38
38
|
dependencies:
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: dry-configurable
|
@@ -112,7 +112,7 @@ dependencies:
|
|
112
112
|
requirements:
|
113
113
|
- - ">="
|
114
114
|
- !ruby/object:Gem::Version
|
115
|
-
version: 2.3.
|
115
|
+
version: 2.3.1
|
116
116
|
- - "<"
|
117
117
|
- !ruby/object:Gem::Version
|
118
118
|
version: 3.0.0
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
requirements:
|
123
123
|
- - ">="
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: 2.3.
|
125
|
+
version: 2.3.1
|
126
126
|
- - "<"
|
127
127
|
- !ruby/object:Gem::Version
|
128
128
|
version: 3.0.0
|
@@ -171,7 +171,9 @@ files:
|
|
171
171
|
- bin/create_token
|
172
172
|
- bin/integrations
|
173
173
|
- bin/karafka
|
174
|
+
- bin/scenario
|
174
175
|
- bin/stress
|
176
|
+
- bin/wait_for_kafka
|
175
177
|
- certs/karafka-pro.pem
|
176
178
|
- certs/mensfeld.pem
|
177
179
|
- config/errors.yml
|
@@ -184,7 +186,7 @@ files:
|
|
184
186
|
- lib/karafka/active_job/dispatcher.rb
|
185
187
|
- lib/karafka/active_job/job_extensions.rb
|
186
188
|
- lib/karafka/active_job/job_options_contract.rb
|
187
|
-
- lib/karafka/active_job/
|
189
|
+
- lib/karafka/active_job/routing/extensions.rb
|
188
190
|
- lib/karafka/app.rb
|
189
191
|
- lib/karafka/base_consumer.rb
|
190
192
|
- lib/karafka/cli.rb
|
@@ -195,8 +197,10 @@ files:
|
|
195
197
|
- lib/karafka/cli/server.rb
|
196
198
|
- lib/karafka/connection/client.rb
|
197
199
|
- lib/karafka/connection/listener.rb
|
200
|
+
- lib/karafka/connection/listeners_batch.rb
|
198
201
|
- lib/karafka/connection/messages_buffer.rb
|
199
202
|
- lib/karafka/connection/pauses_manager.rb
|
203
|
+
- lib/karafka/connection/raw_messages_buffer.rb
|
200
204
|
- lib/karafka/connection/rebalance_manager.rb
|
201
205
|
- lib/karafka/contracts.rb
|
202
206
|
- lib/karafka/contracts/base.rb
|
@@ -206,6 +210,7 @@ files:
|
|
206
210
|
- lib/karafka/contracts/server_cli_options.rb
|
207
211
|
- lib/karafka/env.rb
|
208
212
|
- lib/karafka/errors.rb
|
213
|
+
- lib/karafka/helpers/async.rb
|
209
214
|
- lib/karafka/helpers/multi_delegator.rb
|
210
215
|
- lib/karafka/instrumentation.rb
|
211
216
|
- lib/karafka/instrumentation/callbacks/error.rb
|
@@ -225,10 +230,16 @@ files:
|
|
225
230
|
- lib/karafka/messages/seek.rb
|
226
231
|
- lib/karafka/patches/rdkafka/consumer.rb
|
227
232
|
- lib/karafka/pro.rb
|
233
|
+
- lib/karafka/pro/active_job/consumer.rb
|
228
234
|
- lib/karafka/pro/active_job/dispatcher.rb
|
229
235
|
- lib/karafka/pro/active_job/job_options_contract.rb
|
236
|
+
- lib/karafka/pro/base_consumer.rb
|
230
237
|
- lib/karafka/pro/loader.rb
|
231
238
|
- lib/karafka/pro/performance_tracker.rb
|
239
|
+
- lib/karafka/pro/processing/jobs/consume_non_blocking.rb
|
240
|
+
- lib/karafka/pro/processing/jobs_builder.rb
|
241
|
+
- lib/karafka/pro/routing/extensions.rb
|
242
|
+
- lib/karafka/pro/scheduler.rb
|
232
243
|
- lib/karafka/process.rb
|
233
244
|
- lib/karafka/processing/executor.rb
|
234
245
|
- lib/karafka/processing/executors_buffer.rb
|
@@ -236,7 +247,9 @@ files:
|
|
236
247
|
- lib/karafka/processing/jobs/consume.rb
|
237
248
|
- lib/karafka/processing/jobs/revoked.rb
|
238
249
|
- lib/karafka/processing/jobs/shutdown.rb
|
250
|
+
- lib/karafka/processing/jobs_builder.rb
|
239
251
|
- lib/karafka/processing/jobs_queue.rb
|
252
|
+
- lib/karafka/processing/result.rb
|
240
253
|
- lib/karafka/processing/worker.rb
|
241
254
|
- lib/karafka/processing/workers_batch.rb
|
242
255
|
- lib/karafka/railtie.rb
|
@@ -248,6 +261,7 @@ files:
|
|
248
261
|
- lib/karafka/routing/subscription_group.rb
|
249
262
|
- lib/karafka/routing/subscription_groups_builder.rb
|
250
263
|
- lib/karafka/routing/topic.rb
|
264
|
+
- lib/karafka/routing/topics.rb
|
251
265
|
- lib/karafka/runner.rb
|
252
266
|
- lib/karafka/scheduler.rb
|
253
267
|
- lib/karafka/serialization/json/deserializer.rb
|
@@ -266,6 +280,7 @@ files:
|
|
266
280
|
homepage: https://karafka.io
|
267
281
|
licenses:
|
268
282
|
- LGPL-3.0
|
283
|
+
- Commercial
|
269
284
|
metadata:
|
270
285
|
source_code_uri: https://github.com/karafka/karafka
|
271
286
|
rubygems_mfa_required: 'true'
|
metadata.gz.sig
CHANGED
Binary file
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Karafka
|
4
|
-
# ActiveJob related Karafka stuff
|
5
|
-
module ActiveJob
|
6
|
-
# Routing extensions for ActiveJob
|
7
|
-
module RoutingExtensions
|
8
|
-
# This method simplifies routes definition for ActiveJob topics / queues by auto-injecting
|
9
|
-
# the consumer class
|
10
|
-
# @param name [String, Symbol] name of the topic where ActiveJobs jobs should go
|
11
|
-
def active_job_topic(name)
|
12
|
-
topic(name) do
|
13
|
-
consumer App.config.internal.active_job.consumer
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|