karafka 2.0.0.beta4 → 2.0.0.rc2
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 +18 -1
- data/CHANGELOG.md +30 -0
- data/CONTRIBUTING.md +0 -5
- data/Gemfile.lock +12 -42
- data/README.md +2 -12
- data/bin/benchmarks +2 -2
- data/bin/integrations +10 -3
- data/bin/{stress → stress_many} +1 -1
- data/bin/stress_one +13 -0
- data/config/errors.yml +48 -5
- data/docker-compose.yml +27 -18
- data/karafka.gemspec +2 -4
- data/lib/karafka/active_job/job_options_contract.rb +8 -2
- data/lib/karafka/active_job/routing/extensions.rb +1 -1
- data/lib/karafka/app.rb +2 -1
- data/lib/karafka/base_consumer.rb +24 -19
- data/lib/karafka/cli/install.rb +15 -2
- data/lib/karafka/cli/server.rb +4 -2
- data/lib/karafka/connection/client.rb +40 -17
- data/lib/karafka/connection/listener.rb +37 -11
- data/lib/karafka/connection/rebalance_manager.rb +20 -19
- data/lib/karafka/contracts/base.rb +2 -8
- data/lib/karafka/contracts/config.rb +71 -38
- data/lib/karafka/contracts/consumer_group.rb +25 -18
- data/lib/karafka/contracts/consumer_group_topic.rb +30 -16
- data/lib/karafka/contracts/server_cli_options.rb +18 -7
- data/lib/karafka/errors.rb +3 -0
- data/lib/karafka/helpers/colorize.rb +20 -0
- data/lib/karafka/pro/active_job/consumer.rb +1 -8
- data/lib/karafka/pro/active_job/job_options_contract.rb +10 -6
- data/lib/karafka/pro/base_consumer.rb +27 -21
- data/lib/karafka/pro/loader.rb +13 -6
- data/lib/karafka/pro/processing/coordinator.rb +63 -0
- data/lib/karafka/pro/processing/jobs_builder.rb +3 -2
- data/lib/karafka/pro/processing/partitioner.rb +41 -0
- data/lib/karafka/pro/processing/scheduler.rb +56 -0
- data/lib/karafka/pro/routing/extensions.rb +6 -0
- data/lib/karafka/processing/coordinator.rb +88 -0
- data/lib/karafka/processing/coordinators_buffer.rb +54 -0
- data/lib/karafka/processing/executor.rb +7 -17
- data/lib/karafka/processing/executors_buffer.rb +46 -15
- data/lib/karafka/processing/jobs/consume.rb +4 -2
- data/lib/karafka/processing/jobs_builder.rb +3 -2
- data/lib/karafka/processing/partitioner.rb +22 -0
- data/lib/karafka/processing/result.rb +0 -5
- data/lib/karafka/processing/scheduler.rb +22 -0
- data/lib/karafka/routing/consumer_group.rb +1 -1
- data/lib/karafka/routing/topic.rb +9 -0
- data/lib/karafka/setup/config.rb +26 -12
- data/lib/karafka/templates/example_consumer.rb.erb +2 -2
- data/lib/karafka/version.rb +1 -1
- data/lib/karafka.rb +0 -2
- data.tar.gz.sig +0 -0
- metadata +15 -36
- metadata.gz.sig +0 -0
- data/lib/karafka/pro/scheduler.rb +0 -54
- data/lib/karafka/scheduler.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4103f2661316cc4e24aab8bf9715472c04f6911b3e56bb3ecdab775a0e32139
|
4
|
+
data.tar.gz: 0174d1cd163ac4fd046e4d432c0a4e2a07e2d57494ada9846ec61b6c73c2e434
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3214a7e89730e932dbfbd3e5463ab0ce592d06589b5940f0987ded07f738d1f13557ae1d8251d8971beae7334c91bc655a8f64dd83049520d7ca889b2519e69
|
7
|
+
data.tar.gz: 803ae22e05ad14025dc4bda185571c586727227154e201d979052223b8270b157d7bd8a9588c0aa074c9d5bf0ef31dba6a1a696c7c392171c585945343d2fd10
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.github/workflows/ci.yml
CHANGED
@@ -8,6 +8,10 @@ on:
|
|
8
8
|
schedule:
|
9
9
|
- cron: '0 1 * * *'
|
10
10
|
|
11
|
+
env:
|
12
|
+
BUNDLE_RETRY: 6
|
13
|
+
BUNDLE_JOBS: 4
|
14
|
+
|
11
15
|
jobs:
|
12
16
|
diffend:
|
13
17
|
runs-on: ubuntu-latest
|
@@ -17,13 +21,16 @@ jobs:
|
|
17
21
|
- uses: actions/checkout@v2
|
18
22
|
with:
|
19
23
|
fetch-depth: 0
|
24
|
+
|
20
25
|
- name: Set up Ruby
|
21
26
|
uses: ruby/setup-ruby@v1
|
22
27
|
with:
|
23
28
|
ruby-version: 3.1
|
24
29
|
bundler-cache: true
|
30
|
+
|
25
31
|
- name: Install Diffend plugin
|
26
32
|
run: bundle plugin install diffend
|
33
|
+
|
27
34
|
- name: Bundle Secure
|
28
35
|
run: bundle secure
|
29
36
|
|
@@ -101,7 +108,17 @@ jobs:
|
|
101
108
|
uses: ruby/setup-ruby@v1
|
102
109
|
with:
|
103
110
|
ruby-version: ${{matrix.ruby}}
|
104
|
-
|
111
|
+
|
112
|
+
- name: Install latest Bundler
|
113
|
+
run: |
|
114
|
+
gem install bundler --no-document
|
115
|
+
gem update --system --no-document
|
116
|
+
bundle config set without 'tools benchmarks docs'
|
117
|
+
|
118
|
+
- name: Bundle install
|
119
|
+
run: |
|
120
|
+
bundle config set without development
|
121
|
+
bundle install
|
105
122
|
|
106
123
|
- name: Ensure all needed Kafka topics are created and wait if not
|
107
124
|
run: |
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,35 @@
|
|
1
1
|
# Karafka framework changelog
|
2
2
|
|
3
|
+
## 2.0.0.rc2 (2022-07-19)
|
4
|
+
- Fix `example_consumer.rb.erb` `#shutdown` and `#revoked` signatures to correct once.
|
5
|
+
- Improve the install user experience (print status and created files).
|
6
|
+
- Change default `max_wait_time` from 10s to 5s.
|
7
|
+
- Remove direct dependency on `dry-configurable` in favour of a home-brew.
|
8
|
+
- Remove direct dependency on `dry-validation` in favour of a home-brew.
|
9
|
+
|
10
|
+
## 2.0.0-rc1 (2022-07-08)
|
11
|
+
- Extract consumption partitioner out of listener inline code.
|
12
|
+
- Introduce virtual partitioner concept for parallel processing of data from a single topic partition.
|
13
|
+
- Improve stability when there kafka internal errors occur while polling.
|
14
|
+
- Fix a case where we would resume a LRJ partition upon rebalance where we would reclaim the partition while job was still running.
|
15
|
+
- Do not revoke pauses for lost partitions. This will allow to un-pause reclaimed partitions when LRJ jobs are done.
|
16
|
+
- Fail integrations by default (unless configured otherwise) if any errors occur during Karafka server execution.
|
17
|
+
|
18
|
+
## 2.0.0-beta5 (2022-07-05)
|
19
|
+
- Always resume processing of a revoked partition upon assignment.
|
20
|
+
- Improve specs stability.
|
21
|
+
- Fix a case where revocation job would be executed on partition for which we never did any work.
|
22
|
+
- Introduce a jobs group coordinator for easier jobs management.
|
23
|
+
- Improve stability of resuming paused partitions that were revoked and re-assigned.
|
24
|
+
- Optimize reaction time on partition ownership changes.
|
25
|
+
- Fix a bug where despite setting long max wait time, we would return messages prior to it while not reaching the desired max messages count.
|
26
|
+
- Add more integration specs related to polling limits.
|
27
|
+
- Remove auto-detection of re-assigned partitions upon rebalance as for too fast rebalances it could not be accurate enough. It would also mess up in case of rebalances that would happen right after a `#seek` was issued for a partition.
|
28
|
+
- Optimize the removal of pre-buffered lost partitions data.
|
29
|
+
- Always rune `#revoked` when rebalance with revocation happens.
|
30
|
+
- Evict executors upon rebalance, to prevent race-conditions.
|
31
|
+
- Align topics names for integration specs.
|
32
|
+
|
3
33
|
## 2.0.0-beta4 (2022-06-20)
|
4
34
|
- Rename job internal api methods from `#prepare` to `#before_call` and from `#teardown` to `#after_call` to abstract away jobs execution from any type of executors and consumers logic
|
5
35
|
- Remove ability of running `before_consume` and `after_consume` completely. Those should be for internal usage only.
|
data/CONTRIBUTING.md
CHANGED
@@ -34,8 +34,3 @@ By sending a pull request to the pro components, you are agreeing to transfer th
|
|
34
34
|
|
35
35
|
If you have any questions, create an [issue](issue) (protip: do a quick search first to see if someone else didn't ask the same question before!).
|
36
36
|
You can also reach us at hello@karafka.opencollective.com.
|
37
|
-
|
38
|
-
## Credits
|
39
|
-
|
40
|
-
Thank you to all the people who have already contributed to karafka!
|
41
|
-
<a href="graphs/contributors"><img src="https://opencollective.com/karafka/contributors.svg?width=890" /></a>
|
data/Gemfile.lock
CHANGED
@@ -1,22 +1,20 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
karafka (2.0.0.
|
5
|
-
dry-configurable (~> 0.13)
|
4
|
+
karafka (2.0.0.rc2)
|
6
5
|
dry-monitor (~> 0.5)
|
7
|
-
dry-validation (~> 1.7)
|
8
6
|
rdkafka (>= 0.10)
|
9
7
|
thor (>= 0.20)
|
10
|
-
waterdrop (>= 2.3.
|
8
|
+
waterdrop (>= 2.3.3, < 3.0.0)
|
11
9
|
zeitwerk (~> 2.3)
|
12
10
|
|
13
11
|
GEM
|
14
12
|
remote: https://rubygems.org/
|
15
13
|
specs:
|
16
|
-
activejob (7.0.3)
|
17
|
-
activesupport (= 7.0.3)
|
14
|
+
activejob (7.0.3.1)
|
15
|
+
activesupport (= 7.0.3.1)
|
18
16
|
globalid (>= 0.3.6)
|
19
|
-
activesupport (7.0.3)
|
17
|
+
activesupport (7.0.3.1)
|
20
18
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
21
19
|
i18n (>= 1.6, < 2)
|
22
20
|
minitest (>= 5.1)
|
@@ -28,51 +26,25 @@ GEM
|
|
28
26
|
dry-configurable (0.15.0)
|
29
27
|
concurrent-ruby (~> 1.0)
|
30
28
|
dry-core (~> 0.6)
|
31
|
-
dry-
|
32
|
-
concurrent-ruby (~> 1.0)
|
33
|
-
dry-configurable (~> 0.13, >= 0.13.0)
|
34
|
-
dry-core (0.7.1)
|
29
|
+
dry-core (0.8.0)
|
35
30
|
concurrent-ruby (~> 1.0)
|
36
31
|
dry-events (0.3.0)
|
37
32
|
concurrent-ruby (~> 1.0)
|
38
33
|
dry-core (~> 0.5, >= 0.5)
|
39
|
-
dry-
|
40
|
-
dry-initializer (3.1.1)
|
41
|
-
dry-logic (1.2.0)
|
42
|
-
concurrent-ruby (~> 1.0)
|
43
|
-
dry-core (~> 0.5, >= 0.5)
|
44
|
-
dry-monitor (0.5.0)
|
34
|
+
dry-monitor (0.6.1)
|
45
35
|
dry-configurable (~> 0.13, >= 0.13.0)
|
46
36
|
dry-core (~> 0.5, >= 0.5)
|
47
37
|
dry-events (~> 0.2)
|
48
|
-
|
49
|
-
concurrent-ruby (~> 1.0)
|
50
|
-
dry-configurable (~> 0.13, >= 0.13.0)
|
51
|
-
dry-core (~> 0.5, >= 0.5)
|
52
|
-
dry-initializer (~> 3.0)
|
53
|
-
dry-logic (~> 1.0)
|
54
|
-
dry-types (~> 1.5)
|
55
|
-
dry-types (1.5.1)
|
56
|
-
concurrent-ruby (~> 1.0)
|
57
|
-
dry-container (~> 0.3)
|
58
|
-
dry-core (~> 0.5, >= 0.5)
|
59
|
-
dry-inflector (~> 0.1, >= 0.1.2)
|
60
|
-
dry-logic (~> 1.0, >= 1.0.2)
|
61
|
-
dry-validation (1.8.1)
|
62
|
-
concurrent-ruby (~> 1.0)
|
63
|
-
dry-container (~> 0.7, >= 0.7.1)
|
64
|
-
dry-core (~> 0.5, >= 0.5)
|
65
|
-
dry-initializer (~> 3.0)
|
66
|
-
dry-schema (~> 1.8, >= 1.8.0)
|
38
|
+
zeitwerk (~> 2.5)
|
67
39
|
factory_bot (6.2.1)
|
68
40
|
activesupport (>= 5.0.0)
|
69
41
|
ffi (1.15.5)
|
70
42
|
globalid (1.0.0)
|
71
43
|
activesupport (>= 5.0)
|
72
|
-
i18n (1.
|
44
|
+
i18n (1.12.0)
|
73
45
|
concurrent-ruby (~> 1.0)
|
74
46
|
mini_portile2 (2.8.0)
|
75
|
-
minitest (5.
|
47
|
+
minitest (5.16.2)
|
76
48
|
rake (13.0.6)
|
77
49
|
rdkafka (0.12.0)
|
78
50
|
ffi (~> 1.15)
|
@@ -100,11 +72,9 @@ GEM
|
|
100
72
|
thor (1.2.1)
|
101
73
|
tzinfo (2.0.4)
|
102
74
|
concurrent-ruby (~> 1.0)
|
103
|
-
waterdrop (2.3.
|
75
|
+
waterdrop (2.3.3)
|
104
76
|
concurrent-ruby (>= 1.1)
|
105
|
-
dry-configurable (~> 0.13)
|
106
77
|
dry-monitor (~> 0.5)
|
107
|
-
dry-validation (~> 1.7)
|
108
78
|
rdkafka (>= 0.10)
|
109
79
|
zeitwerk (~> 2.3)
|
110
80
|
zeitwerk (2.6.0)
|
@@ -121,4 +91,4 @@ DEPENDENCIES
|
|
121
91
|
simplecov
|
122
92
|
|
123
93
|
BUNDLED WITH
|
124
|
-
2.3.
|
94
|
+
2.3.15
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
|
9
9
|
## About Karafka
|
10
10
|
|
11
|
-
Karafka is a framework used to simplify Apache Kafka based Ruby and Ruby on Rails applications development.
|
11
|
+
Karafka is a multi-threaded framework used to simplify Apache Kafka based Ruby and Ruby on Rails applications development.
|
12
12
|
|
13
13
|
```ruby
|
14
14
|
# Define what topics you want to consume with which consumers in karafka.rb
|
@@ -28,8 +28,6 @@ class EventsConsumer < ApplicationConsumer
|
|
28
28
|
end
|
29
29
|
```
|
30
30
|
|
31
|
-
Karafka allows you to capture everything that happens in your systems in large scale, providing you with a seamless and stable core for consuming, processing and producing data, without having to focus on things that are not your business domain.
|
32
|
-
|
33
31
|
Karafka **uses** threads to handle many messages at the same time in the same process. It does not require Rails but will integrate tightly with any Ruby on Rails applications to make event processing dead simple.
|
34
32
|
|
35
33
|
## Getting started
|
@@ -45,7 +43,7 @@ We also maintain many [integration specs](https://github.com/karafka/karafka/tre
|
|
45
43
|
|
46
44
|
## Want to Upgrade? LGPL is not for you? Want to help?
|
47
45
|
|
48
|
-
I also sell Karafka Pro subscription. It includes commercial-friendly license, priority support, architecture consultations and high throughput data processing-related features (
|
46
|
+
I also sell Karafka Pro subscription. It includes commercial-friendly license, priority support, architecture consultations and high throughput data processing-related features (virtual partitions, long running jobs and more).
|
49
47
|
|
50
48
|
**20%** of the income will be distributed back to other OSS projects that Karafka uses under the hood.
|
51
49
|
|
@@ -56,11 +54,3 @@ Help me provide high-quality open-source software. Please see the Karafka [homep
|
|
56
54
|
Karafka has [Wiki pages](https://github.com/karafka/karafka/wiki) for almost everything and a pretty decent [FAQ](https://github.com/karafka/karafka/wiki/FAQ). It covers the whole installation, setup and deployment along with other useful details on how to run Karafka.
|
57
55
|
|
58
56
|
If you have any questions about using Karafka, feel free to join our [Slack](https://slack.karafka.io) channel.
|
59
|
-
|
60
|
-
## Note on contributions
|
61
|
-
|
62
|
-
First, thank you for considering contributing to the Karafka ecosystem! It's people like you that make the open source community such a great community!
|
63
|
-
|
64
|
-
Each pull request must pass all the RSpec specs, integration tests and meet our quality requirements.
|
65
|
-
|
66
|
-
Fork it, update and wait for the Github Actions results.
|
data/bin/benchmarks
CHANGED
@@ -39,8 +39,8 @@ if ENV['SEED']
|
|
39
39
|
|
40
40
|
# We do not populate data of benchmarks_0_10 as we use it with life-stream data only
|
41
41
|
%w[
|
42
|
-
|
43
|
-
|
42
|
+
benchmarks_00_01
|
43
|
+
benchmarks_00_05
|
44
44
|
].each do |topic_name|
|
45
45
|
partitions_count = topic_name.split('_').last.to_i
|
46
46
|
|
data/bin/integrations
CHANGED
@@ -21,6 +21,9 @@ ROOT_PATH = Pathname.new(File.expand_path(File.join(File.dirname(__FILE__), '../
|
|
21
21
|
# of CPU
|
22
22
|
CONCURRENCY = ENV.key?('CI') ? 5 : Etc.nprocessors * 2
|
23
23
|
|
24
|
+
# How may bytes do we want to keep from the stdout in the buffer for when we need to print it
|
25
|
+
MAX_BUFFER_OUTPUT = 10_240
|
26
|
+
|
24
27
|
# Abstraction around a single test scenario execution process
|
25
28
|
class Scenario
|
26
29
|
# How long a scenario can run before we kill it
|
@@ -84,9 +87,9 @@ class Scenario
|
|
84
87
|
# We read it so it won't grow as we use our default logger that prints to both test.log and
|
85
88
|
# to stdout. Otherwise after reaching the buffer size, it would hang
|
86
89
|
buffer = ''
|
87
|
-
@stdout.read_nonblock(
|
90
|
+
@stdout.read_nonblock(MAX_BUFFER_OUTPUT, buffer, exception: false)
|
88
91
|
@stdout_tail << buffer
|
89
|
-
@stdout_tail = @stdout_tail[-
|
92
|
+
@stdout_tail = @stdout_tail[-MAX_BUFFER_OUTPUT..-1] || @stdout_tail
|
90
93
|
|
91
94
|
!@wait_thr.alive?
|
92
95
|
end
|
@@ -114,11 +117,15 @@ class Scenario
|
|
114
117
|
if success?
|
115
118
|
print "\e[#{32}m#{'.'}\e[0m"
|
116
119
|
else
|
120
|
+
buffer = ''
|
121
|
+
|
122
|
+
@stderr.read_nonblock(MAX_BUFFER_OUTPUT, buffer, exception: false)
|
123
|
+
|
117
124
|
puts
|
118
125
|
puts "\e[#{31}m#{'[FAILED]'}\e[0m #{name}"
|
119
126
|
puts "Exit code: #{exit_code}"
|
120
127
|
puts @stdout_tail
|
121
|
-
puts
|
128
|
+
puts buffer
|
122
129
|
puts
|
123
130
|
end
|
124
131
|
end
|
data/bin/{stress → stress_many}
RENAMED
data/bin/stress_one
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# Runs a single integration spec in an endless loop
|
4
|
+
# This allows us to ensure (after long enough time) that the integration spec is stable and
|
5
|
+
# that there are no anomalies when running it for a long period of time
|
6
|
+
|
7
|
+
set -e
|
8
|
+
|
9
|
+
while :
|
10
|
+
do
|
11
|
+
clear
|
12
|
+
bin/scenario $1
|
13
|
+
done
|
data/config/errors.yml
CHANGED
@@ -1,9 +1,52 @@
|
|
1
1
|
en:
|
2
|
-
|
3
|
-
|
2
|
+
validations:
|
3
|
+
config:
|
4
|
+
missing: needs to be present
|
5
|
+
client_id_format: 'needs to be a string with a Kafka accepted format'
|
6
|
+
license.entity_format: needs to be a string
|
7
|
+
license.token_format: needs to be either false or a string
|
8
|
+
license.expires_on_format: needs to be a valid date
|
9
|
+
concurrency_format: needs to be an integer bigger than 0
|
10
|
+
consumer_mapper_format: needs to be present
|
11
|
+
consumer_persistence_format: needs to be either true or false
|
12
|
+
pause_timeout_format: needs to be an integer bigger than 0
|
13
|
+
pause_max_timeout_format: needs to be an integer bigger than 0
|
14
|
+
pause_with_exponential_backoff_format: needs to be either true or false
|
15
|
+
shutdown_timeout_format: needs to be an integer bigger than 0
|
16
|
+
max_wait_time_format: needs to be an integer bigger than 0
|
17
|
+
kafka_format: needs to be a filled hash
|
18
|
+
internal.status_format: needs to be present
|
19
|
+
internal.process_format: needs to be present
|
20
|
+
internal.routing.builder_format: needs to be present
|
21
|
+
internal.routing.subscription_groups_builder_format: needs to be present
|
22
|
+
key_must_be_a_symbol: All keys under the kafka settings scope need to be symbols
|
4
23
|
max_timeout_vs_pause_max_timeout: pause_timeout must be less or equal to pause_max_timeout
|
5
24
|
shutdown_timeout_vs_max_wait_time: shutdown_timeout must be more than max_wait_time
|
6
|
-
|
7
|
-
|
25
|
+
|
26
|
+
server_cli_options:
|
27
|
+
missing: needs to be present
|
8
28
|
consumer_groups_inclusion: Unknown consumer group
|
9
|
-
|
29
|
+
|
30
|
+
consumer_group_topic:
|
31
|
+
missing: needs to be present
|
32
|
+
name_format: 'needs to be a string with a Kafka accepted format'
|
33
|
+
deserializer_format: needs to be present
|
34
|
+
manual_offset_management_format: needs to be either true or false
|
35
|
+
consumer_format: needs to be present
|
36
|
+
id_format: 'needs to be a string with a Kafka accepted format'
|
37
|
+
initial_offset_format: needs to be either earliest or latest
|
38
|
+
|
39
|
+
consumer_group:
|
40
|
+
missing: needs to be present
|
41
|
+
topics_names_not_unique: all topic names within a single consumer group must be unique
|
42
|
+
id_format: 'needs to be a string with a Kafka accepted format'
|
43
|
+
topics_format: needs to be a non-empty array
|
44
|
+
|
45
|
+
job_options:
|
46
|
+
missing: needs to be present
|
47
|
+
dispatch_method_format: needs to be either :produce_async or :produce_sync
|
48
|
+
partitioner_format: 'needs to respond to #call'
|
49
|
+
|
50
|
+
test:
|
51
|
+
missing: needs to be present
|
52
|
+
id_format: needs to be a String
|
data/docker-compose.yml
CHANGED
@@ -16,26 +16,35 @@ services:
|
|
16
16
|
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
|
17
17
|
KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'
|
18
18
|
KAFKA_CREATE_TOPICS:
|
19
|
-
"
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
19
|
+
"integrations_00_02:2:1,\
|
20
|
+
integrations_01_02:2:1,\
|
21
|
+
integrations_02_02:2:1,\
|
22
|
+
integrations_03_02:2:1,\
|
23
|
+
integrations_04_02:2:1,\
|
24
|
+
integrations_05_02:2:1,\
|
25
|
+
integrations_06_02:2:1,\
|
26
|
+
integrations_07_02:2:1,\
|
27
|
+
integrations_08_02:2:1,\
|
28
|
+
integrations_09_02:2:1,\
|
29
29
|
integrations_10_02:2:1,\
|
30
30
|
integrations_11_02:2:1,\
|
31
31
|
integrations_12_02:2:1,\
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
integrations_13_02:2:1,\
|
33
|
+
integrations_14_02:2:1,\
|
34
|
+
integrations_15_02:2:1,\
|
35
|
+
integrations_16_02:2:1,\
|
36
|
+
integrations_17_02:2:1,\
|
37
|
+
integrations_18_02:2:1,\
|
38
|
+
integrations_19_02:2:1,\
|
39
|
+
integrations_00_03:3:1,\
|
40
|
+
integrations_01_03:3:1,\
|
41
|
+
integrations_02_03:3:1,\
|
42
|
+
integrations_03_03:3:1,\
|
43
|
+
integrations_00_10:10:1,\
|
44
|
+
integrations_01_10:10:1,\
|
45
|
+
benchmarks_00_01:1:1,\
|
46
|
+
benchmarks_00_05:5:1,\
|
47
|
+
benchmarks_01_05:5:1,\
|
48
|
+
benchmarks_00_10:10:1"
|
40
49
|
volumes:
|
41
50
|
- /var/run/docker.sock:/var/run/docker.sock
|
data/karafka.gemspec
CHANGED
@@ -12,16 +12,14 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.authors = ['Maciej Mensfeld']
|
13
13
|
spec.email = %w[maciej@mensfeld.pl]
|
14
14
|
spec.homepage = 'https://karafka.io'
|
15
|
-
spec.summary = 'Ruby
|
15
|
+
spec.summary = 'Ruby framework for working with Apache Kafka'
|
16
16
|
spec.description = 'Framework used to simplify Apache Kafka based Ruby applications development'
|
17
17
|
spec.licenses = ['LGPL-3.0', 'Commercial']
|
18
18
|
|
19
|
-
spec.add_dependency 'dry-configurable', '~> 0.13'
|
20
19
|
spec.add_dependency 'dry-monitor', '~> 0.5'
|
21
|
-
spec.add_dependency 'dry-validation', '~> 1.7'
|
22
20
|
spec.add_dependency 'rdkafka', '>= 0.10'
|
23
21
|
spec.add_dependency 'thor', '>= 0.20'
|
24
|
-
spec.add_dependency 'waterdrop', '>= 2.3.
|
22
|
+
spec.add_dependency 'waterdrop', '>= 2.3.3', '< 3.0.0'
|
25
23
|
spec.add_dependency 'zeitwerk', '~> 2.3'
|
26
24
|
|
27
25
|
spec.required_ruby_version = '>= 2.6.0'
|
@@ -7,9 +7,15 @@ module Karafka
|
|
7
7
|
# we want to keep ActiveJob related Karafka components outside of the core Karafka code and
|
8
8
|
# all in the same place
|
9
9
|
class JobOptionsContract < Contracts::Base
|
10
|
-
|
11
|
-
|
10
|
+
configure do |config|
|
11
|
+
config.error_messages = YAML.safe_load(
|
12
|
+
File.read(
|
13
|
+
File.join(Karafka.gem_root, 'config', 'errors.yml')
|
14
|
+
)
|
15
|
+
).fetch('en').fetch('validations').fetch('job_options')
|
12
16
|
end
|
17
|
+
|
18
|
+
optional(:dispatch_method) { |val| %i[produce_async produce_sync].include?(val) }
|
13
19
|
end
|
14
20
|
end
|
15
21
|
end
|
@@ -13,7 +13,7 @@ module Karafka
|
|
13
13
|
# @param block [Proc] block that we can use for some extra configuration
|
14
14
|
def active_job_topic(name, &block)
|
15
15
|
topic(name) do
|
16
|
-
consumer App.config.internal.active_job.
|
16
|
+
consumer App.config.internal.active_job.consumer_class
|
17
17
|
|
18
18
|
next unless block
|
19
19
|
|
data/lib/karafka/app.rb
CHANGED
@@ -10,17 +10,11 @@ module Karafka
|
|
10
10
|
attr_accessor :messages
|
11
11
|
# @return [Karafka::Connection::Client] kafka connection client
|
12
12
|
attr_accessor :client
|
13
|
-
# @return [Karafka::
|
14
|
-
attr_accessor :
|
13
|
+
# @return [Karafka::Processing::Coordinator] coordinator
|
14
|
+
attr_accessor :coordinator
|
15
15
|
# @return [Waterdrop::Producer] producer instance
|
16
16
|
attr_accessor :producer
|
17
17
|
|
18
|
-
def initialize
|
19
|
-
# We re-use one to save on object allocation
|
20
|
-
# It also allows us to transfer the consumption notion to another batch
|
21
|
-
@consumption = Processing::Result.new
|
22
|
-
end
|
23
|
-
|
24
18
|
# Can be used to run preparation code
|
25
19
|
#
|
26
20
|
# @private
|
@@ -41,9 +35,9 @@ module Karafka
|
|
41
35
|
consume
|
42
36
|
end
|
43
37
|
|
44
|
-
|
38
|
+
coordinator.consumption(self).success!
|
45
39
|
rescue StandardError => e
|
46
|
-
|
40
|
+
coordinator.consumption(self).failure!
|
47
41
|
|
48
42
|
Karafka.monitor.instrument(
|
49
43
|
'error.occurred',
|
@@ -51,14 +45,19 @@ module Karafka
|
|
51
45
|
caller: self,
|
52
46
|
type: 'consumer.consume.error'
|
53
47
|
)
|
48
|
+
ensure
|
49
|
+
# We need to decrease number of jobs that this coordinator coordinates as it has finished
|
50
|
+
coordinator.decrement
|
54
51
|
end
|
55
52
|
|
56
53
|
# @private
|
57
54
|
# @note This should not be used by the end users as it is part of the lifecycle of things but
|
58
55
|
# not as part of the public api.
|
59
56
|
def on_after_consume
|
60
|
-
if
|
61
|
-
|
57
|
+
return if revoked?
|
58
|
+
|
59
|
+
if coordinator.success?
|
60
|
+
coordinator.pause_tracker.reset
|
62
61
|
|
63
62
|
# Mark as consumed only if manual offset management is not on
|
64
63
|
return if topic.manual_offset_management?
|
@@ -75,6 +74,8 @@ module Karafka
|
|
75
74
|
#
|
76
75
|
# @private
|
77
76
|
def on_revoked
|
77
|
+
coordinator.revoke
|
78
|
+
|
78
79
|
Karafka.monitor.instrument('consumer.revoked', caller: self) do
|
79
80
|
revoked
|
80
81
|
end
|
@@ -132,9 +133,11 @@ module Karafka
|
|
132
133
|
# processed but rather at the next one. This applies to both sync and async versions of this
|
133
134
|
# method.
|
134
135
|
def mark_as_consumed(message)
|
135
|
-
|
136
|
+
unless client.mark_as_consumed(message)
|
137
|
+
coordinator.revoke
|
136
138
|
|
137
|
-
|
139
|
+
return false
|
140
|
+
end
|
138
141
|
|
139
142
|
@seek_offset = message.offset + 1
|
140
143
|
|
@@ -147,9 +150,11 @@ module Karafka
|
|
147
150
|
# @return [Boolean] true if we were able to mark the offset, false otherwise. False indicates
|
148
151
|
# that we were not able and that we have lost the partition.
|
149
152
|
def mark_as_consumed!(message)
|
150
|
-
|
153
|
+
unless client.mark_as_consumed!(message)
|
154
|
+
coordinator.revoke
|
151
155
|
|
152
|
-
|
156
|
+
return false
|
157
|
+
end
|
153
158
|
|
154
159
|
@seek_offset = message.offset + 1
|
155
160
|
|
@@ -163,7 +168,7 @@ module Karafka
|
|
163
168
|
# @param timeout [Integer, nil] how long in milliseconds do we want to pause or nil to use the
|
164
169
|
# default exponential pausing strategy defined for retries
|
165
170
|
def pause(offset, timeout = nil)
|
166
|
-
timeout ? pause_tracker.pause(timeout) : pause_tracker.pause
|
171
|
+
timeout ? coordinator.pause_tracker.pause(timeout) : coordinator.pause_tracker.pause
|
167
172
|
|
168
173
|
client.pause(
|
169
174
|
messages.metadata.topic,
|
@@ -176,7 +181,7 @@ module Karafka
|
|
176
181
|
def resume
|
177
182
|
# This is sufficient to expire a partition pause, as with it will be resumed by the listener
|
178
183
|
# thread before the next poll.
|
179
|
-
pause_tracker.expire
|
184
|
+
coordinator.pause_tracker.expire
|
180
185
|
end
|
181
186
|
|
182
187
|
# Seeks in the context of current topic and partition
|
@@ -196,7 +201,7 @@ module Karafka
|
|
196
201
|
# @note We know that partition got revoked because when we try to mark message as consumed,
|
197
202
|
# unless if is successful, it will return false
|
198
203
|
def revoked?
|
199
|
-
|
204
|
+
coordinator.revoked?
|
200
205
|
end
|
201
206
|
end
|
202
207
|
end
|
data/lib/karafka/cli/install.rb
CHANGED
@@ -7,6 +7,8 @@ module Karafka
|
|
7
7
|
class Cli < Thor
|
8
8
|
# Install Karafka Cli action
|
9
9
|
class Install < Base
|
10
|
+
include Helpers::Colorize
|
11
|
+
|
10
12
|
desc 'Install all required things for Karafka application in current directory'
|
11
13
|
|
12
14
|
# Directories created by default
|
@@ -42,14 +44,25 @@ module Karafka
|
|
42
44
|
FileUtils.mkdir_p Karafka.root.join(dir)
|
43
45
|
end
|
44
46
|
|
47
|
+
puts
|
48
|
+
puts 'Installing Karafka framework...'
|
49
|
+
puts 'Ruby on Rails detected...' if rails?
|
50
|
+
puts
|
51
|
+
|
45
52
|
INSTALL_FILES_MAP.each do |source, target|
|
46
|
-
|
53
|
+
pathed_target = Karafka.root.join(target)
|
47
54
|
|
48
55
|
template = File.read(Karafka.core_root.join("templates/#{source}"))
|
49
56
|
render = ::ERB.new(template, trim_mode: '-').result(binding)
|
50
57
|
|
51
|
-
File.open(
|
58
|
+
File.open(pathed_target, 'w') { |file| file.write(render) }
|
59
|
+
|
60
|
+
puts "#{green('Created')} #{target}"
|
52
61
|
end
|
62
|
+
|
63
|
+
puts
|
64
|
+
puts("Installation #{green('completed')}. Have fun!")
|
65
|
+
puts
|
53
66
|
end
|
54
67
|
|
55
68
|
# @return [Boolean] true if we have Rails loaded
|