karafka 2.0.0.beta1 → 2.0.0.beta4
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/.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
|