karafka 2.0.34 → 2.0.36
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/CHANGELOG.md +8 -0
- data/Gemfile.lock +5 -4
- data/config/locales/errors.yml +4 -0
- data/lib/karafka/cli/topics.rb +143 -0
- data/lib/karafka/helpers/colorize.rb +6 -0
- data/lib/karafka/pro/processing/strategies/aj_dlq_lrj_mom.rb +4 -2
- data/lib/karafka/routing/features/declaratives/config.rb +18 -0
- data/lib/karafka/routing/features/declaratives/contract.rb +30 -0
- data/lib/karafka/routing/features/declaratives/topic.rb +44 -0
- data/lib/karafka/routing/features/declaratives.rb +14 -0
- data/lib/karafka/templates/karafka.rb.erb +5 -0
- data/lib/karafka/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +7 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 128d19fa065cbb43fae7a23a424e44ec30077fe58c93d7c122da299ec5b98df1
|
4
|
+
data.tar.gz: 0b396fa75d93257f32a9ddf94f0dc89d2456b6ed07acad5c581908d148cf0a6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68d4da94eaf7a1033c95dd02bdc9a4bd8e69040df4db304dbcb6f8255997a40c003c999eea6442f6c1a1640c3e1ed44032c3826191e96085afbccc8600a8f2b6
|
7
|
+
data.tar.gz: 025fbc8edb26f6f8442e11ea90afdc3e07873efcba3f6778549cd66e0738dfec73d956d877c44ea39bc1064c22df9fca6d3c68a42ef97ad4438ed7812b690ea1
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Karafka framework changelog
|
2
2
|
|
3
|
+
## 2.0.36 (2023-03-17)
|
4
|
+
- [Refactor] Rename internal naming of `Structurable` to `Declaratives` for declarative topics feature.
|
5
|
+
- [Fix] AJ + DLQ + MOM + LRJ is pausing indefinitely after the first job (#1362)
|
6
|
+
|
7
|
+
## 2.0.35 (2023-03-13)
|
8
|
+
- **[Feature]** Allow for defining topics config via the DSL and its automatic creation via CLI command.
|
9
|
+
- **[Feature]** Allow for full topics reset and topics repartitioning via the CLI.
|
10
|
+
|
3
11
|
## 2.0.34 (2023-03-04)
|
4
12
|
- [Improvement] Attach an `embedded` tag to Karafka processes started using the embedded API.
|
5
13
|
- [Change] Renamed `Datadog::Listener` to `Datadog::MetricsListener` for consistency. (#1124)
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
karafka (2.0.
|
4
|
+
karafka (2.0.36)
|
5
5
|
karafka-core (>= 2.0.12, < 3.0.0)
|
6
6
|
thor (>= 0.20)
|
7
7
|
waterdrop (>= 2.4.10, < 3.0.0)
|
@@ -37,7 +37,7 @@ GEM
|
|
37
37
|
mini_portile2 (~> 2.6)
|
38
38
|
rake (> 12)
|
39
39
|
mini_portile2 (2.8.1)
|
40
|
-
minitest (5.
|
40
|
+
minitest (5.18.0)
|
41
41
|
rake (13.0.6)
|
42
42
|
rspec (3.12.0)
|
43
43
|
rspec-core (~> 3.12.0)
|
@@ -61,12 +61,13 @@ GEM
|
|
61
61
|
thor (1.2.1)
|
62
62
|
tzinfo (2.0.6)
|
63
63
|
concurrent-ruby (~> 1.0)
|
64
|
-
waterdrop (2.
|
64
|
+
waterdrop (2.5.0)
|
65
65
|
karafka-core (>= 2.0.12, < 3.0.0)
|
66
66
|
zeitwerk (~> 2.3)
|
67
67
|
zeitwerk (2.6.7)
|
68
68
|
|
69
69
|
PLATFORMS
|
70
|
+
arm64-darwin-21
|
70
71
|
x86_64-linux
|
71
72
|
|
72
73
|
DEPENDENCIES
|
@@ -78,4 +79,4 @@ DEPENDENCIES
|
|
78
79
|
simplecov
|
79
80
|
|
80
81
|
BUNDLED WITH
|
81
|
-
2.4.
|
82
|
+
2.4.7
|
data/config/locales/errors.yml
CHANGED
@@ -45,6 +45,10 @@ en:
|
|
45
45
|
dead_letter_queue.topic_format: 'needs to be a string with a Kafka accepted format'
|
46
46
|
dead_letter_queue.active_format: needs to be either true or false
|
47
47
|
active_format: needs to be either true or false
|
48
|
+
declaratives.partitions_format: needs to be more or equal to 1
|
49
|
+
declaratives.active_format: needs to be true
|
50
|
+
declaratives.replication_factor_format: needs to be more or equal to 1
|
51
|
+
declaratives.details_format: needs to be a hash with only symbol keys
|
48
52
|
inconsistent_namespacing: |
|
49
53
|
needs to be consistent namespacing style
|
50
54
|
disable this validation by setting config.strict_topics_namespacing to false
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
class Cli < Thor
|
5
|
+
# CLI actions related to Kafka cluster topics management
|
6
|
+
class Topics < Base
|
7
|
+
include Helpers::Colorize
|
8
|
+
|
9
|
+
desc 'Allows for the topics management (create, delete, reset, repartition)'
|
10
|
+
# @param action [String] action we want to take
|
11
|
+
def call(action = 'missing')
|
12
|
+
case action
|
13
|
+
when 'create'
|
14
|
+
create
|
15
|
+
when 'delete'
|
16
|
+
delete
|
17
|
+
when 'reset'
|
18
|
+
reset
|
19
|
+
when 'repartition'
|
20
|
+
repartition
|
21
|
+
when 'migrate'
|
22
|
+
migrate
|
23
|
+
else
|
24
|
+
raise ::ArgumentError, "Invalid topics action: #{action}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Creates topics based on the routing setup and configuration
|
31
|
+
def create
|
32
|
+
declaratives_routing_topics.each do |topic|
|
33
|
+
name = topic.name
|
34
|
+
|
35
|
+
if existing_topics_names.include?(name)
|
36
|
+
puts "#{yellow('Skipping')} because topic #{name} already exists."
|
37
|
+
else
|
38
|
+
puts "Creating topic #{name}..."
|
39
|
+
Admin.create_topic(
|
40
|
+
name,
|
41
|
+
topic.declaratives.partitions,
|
42
|
+
topic.declaratives.replication_factor,
|
43
|
+
topic.declaratives.details
|
44
|
+
)
|
45
|
+
puts "#{green('Created')} topic #{name}."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Deletes routing based topics
|
51
|
+
def delete
|
52
|
+
declaratives_routing_topics.each do |topic|
|
53
|
+
name = topic.name
|
54
|
+
|
55
|
+
if existing_topics_names.include?(name)
|
56
|
+
puts "Deleting topic #{name}..."
|
57
|
+
Admin.delete_topic(name)
|
58
|
+
puts "#{green('Deleted')} topic #{name}."
|
59
|
+
else
|
60
|
+
puts "#{yellow('Skipping')} because topic #{name} does not exist."
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Deletes routing based topics and re-creates them
|
66
|
+
def reset
|
67
|
+
delete
|
68
|
+
|
69
|
+
# We need to invalidate the metadata cache, otherwise we will think, that the topic
|
70
|
+
# already exists
|
71
|
+
@existing_topics = nil
|
72
|
+
|
73
|
+
create
|
74
|
+
end
|
75
|
+
|
76
|
+
# Creates missing topics and aligns the partitions count
|
77
|
+
def migrate
|
78
|
+
create
|
79
|
+
|
80
|
+
@existing_topics = nil
|
81
|
+
|
82
|
+
repartition
|
83
|
+
end
|
84
|
+
|
85
|
+
# Increases number of partitions on topics that have less partitions than defined
|
86
|
+
# Will **not** create topics if missing.
|
87
|
+
def repartition
|
88
|
+
existing_partitions = existing_topics.map do |topic|
|
89
|
+
[topic.fetch(:topic_name), topic.fetch(:partition_count)]
|
90
|
+
end.to_h
|
91
|
+
|
92
|
+
declaratives_routing_topics.each do |topic|
|
93
|
+
name = topic.name
|
94
|
+
|
95
|
+
desired_count = topic.config.partitions
|
96
|
+
existing_count = existing_partitions.fetch(name, false)
|
97
|
+
|
98
|
+
if existing_count && existing_count < desired_count
|
99
|
+
puts "Increasing number of partitions to #{desired_count} on topic #{name}..."
|
100
|
+
Admin.create_partitions(name, desired_count)
|
101
|
+
change = desired_count - existing_count
|
102
|
+
puts "#{green('Created')} #{change} additional partitions on topic #{name}."
|
103
|
+
elsif existing_count
|
104
|
+
puts "#{yellow('Skipping')} because topic #{name} has #{existing_count} partitions."
|
105
|
+
else
|
106
|
+
puts "#{yellow('Skipping')} because topic #{name} does not exist."
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [Array<Karafka::Routing::Topic>] all available topics that can be managed
|
112
|
+
# @note If topic is defined in multiple consumer groups, first config will be used. This
|
113
|
+
# means, that this CLI will not work for simultaneous management of multiple clusters from
|
114
|
+
# a single CLI command execution flow.
|
115
|
+
def declaratives_routing_topics
|
116
|
+
return @declaratives_routing_topics if @declaratives_routing_topics
|
117
|
+
|
118
|
+
collected_topics = {}
|
119
|
+
|
120
|
+
App.consumer_groups.each do |consumer_group|
|
121
|
+
consumer_group.topics.each do |topic|
|
122
|
+
# Skip topics that were explicitly disabled from management
|
123
|
+
next unless topic.declaratives.active?
|
124
|
+
|
125
|
+
collected_topics[topic.name] ||= topic
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
@declaratives_routing_topics = collected_topics.values
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [Array<Hash>] existing topics details
|
133
|
+
def existing_topics
|
134
|
+
@existing_topics ||= Admin.cluster_info.topics
|
135
|
+
end
|
136
|
+
|
137
|
+
# @return [Array<String>] names of already existing topics
|
138
|
+
def existing_topics_names
|
139
|
+
existing_topics.map { |topic| topic.fetch(:topic_name) }
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -15,6 +15,12 @@ module Karafka
|
|
15
15
|
def red(string)
|
16
16
|
"\033[0;31m#{string}\033[0m"
|
17
17
|
end
|
18
|
+
|
19
|
+
# @param string [String] string we want to have in yellow
|
20
|
+
# @return [String] yellow string
|
21
|
+
def yellow(string)
|
22
|
+
"\033[1;33m#{string}\033[0m"
|
23
|
+
end
|
18
24
|
end
|
19
25
|
end
|
20
26
|
end
|
@@ -23,8 +23,10 @@ module Karafka
|
|
23
23
|
# This case is a bit of special. Please see the `AjDlqMom` for explanation on how the
|
24
24
|
# offset management works in this case.
|
25
25
|
module AjDlqLrjMom
|
26
|
-
|
27
|
-
|
26
|
+
# We can use the same code as for VP because non VP behaves like:
|
27
|
+
# - with one virtual partition
|
28
|
+
# - with "never ending" collapse
|
29
|
+
include AjDlqLrjMomVp
|
28
30
|
|
29
31
|
# Features for this strategy
|
30
32
|
FEATURES = %i[
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Routing
|
5
|
+
module Features
|
6
|
+
class Declaratives < Base
|
7
|
+
# Config for declarative topics feature
|
8
|
+
Config = Struct.new(
|
9
|
+
:active,
|
10
|
+
:partitions,
|
11
|
+
:replication_factor,
|
12
|
+
:details,
|
13
|
+
keyword_init: true
|
14
|
+
) { alias_method :active?, :active }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Routing
|
5
|
+
module Features
|
6
|
+
class Declaratives < Base
|
7
|
+
# Basic validation of the Kafka expected config details
|
8
|
+
class Contract < Contracts::Base
|
9
|
+
configure do |config|
|
10
|
+
config.error_messages = YAML.safe_load(
|
11
|
+
File.read(
|
12
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'errors.yml')
|
13
|
+
)
|
14
|
+
).fetch('en').fetch('validations').fetch('topic')
|
15
|
+
end
|
16
|
+
|
17
|
+
nested :declaratives do
|
18
|
+
required(:active) { |val| [true, false].include?(val) }
|
19
|
+
required(:partitions) { |val| val.is_a?(Integer) && val.positive? }
|
20
|
+
required(:replication_factor) { |val| val.is_a?(Integer) && val.positive? }
|
21
|
+
required(:details) do |val|
|
22
|
+
val.is_a?(Hash) &&
|
23
|
+
val.keys.all? { |key| key.is_a?(Symbol) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Routing
|
5
|
+
module Features
|
6
|
+
class Declaratives < Base
|
7
|
+
# Extension for managing Kafka topic configuration
|
8
|
+
module Topic
|
9
|
+
# @param active [Boolean] is the topic structure management feature active
|
10
|
+
# @param partitions [Integer]
|
11
|
+
# @param replication_factor [Integer]
|
12
|
+
# @param details [Hash] extra configuration for the topic
|
13
|
+
# @return [Config] defined structure
|
14
|
+
def config(active: true, partitions: 1, replication_factor: 1, **details)
|
15
|
+
@declaratives ||= Config.new(
|
16
|
+
active: active,
|
17
|
+
partitions: partitions,
|
18
|
+
replication_factor: replication_factor,
|
19
|
+
details: details
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Config] config details
|
24
|
+
def declaratives
|
25
|
+
config
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [true] declaratives is always active
|
29
|
+
def declaratives?
|
30
|
+
declaratives.active?
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Hash] topic with all its native configuration options plus declaratives
|
34
|
+
# settings
|
35
|
+
def to_h
|
36
|
+
super.merge(
|
37
|
+
declaratives: declaratives.to_h
|
38
|
+
).freeze
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Routing
|
5
|
+
module Features
|
6
|
+
# This feature allows to store per topic structure that can be later on used to bootstrap
|
7
|
+
# topics structure for test/development, etc. This allows to share the same set of settings
|
8
|
+
# for topics despite the environment. Pretty much similar to how the `structure.sql` or
|
9
|
+
# `schema.rb` operate for SQL dbs.
|
10
|
+
class Declaratives < Base
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -53,6 +53,11 @@ class KarafkaApp < Karafka::App
|
|
53
53
|
# active_job_topic :default
|
54
54
|
<% end -%>
|
55
55
|
topic :example do
|
56
|
+
# Uncomment this if you want Karafka to manage your topics configuration
|
57
|
+
# Managing topics configuration via routing will allow you to ensure config consistency
|
58
|
+
# across multiple environments
|
59
|
+
#
|
60
|
+
# config(partitions: 2, 'cleanup.policy': 'compact')
|
56
61
|
consumer ExampleConsumer
|
57
62
|
end
|
58
63
|
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.
|
4
|
+
version: 2.0.36
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maciej Mensfeld
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
Qf04B9ceLUaC4fPVEz10FyobjaFoY4i32xRto3XnrzeAgfEe4swLq8bQsR3w/EF3
|
36
36
|
MGU0FeSV2Yj7Xc2x/7BzLK8xQn5l7Yy75iPF+KP3vVmDHnNl
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2023-03-
|
38
|
+
date: 2023-03-17 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: karafka-core
|
@@ -168,6 +168,7 @@ files:
|
|
168
168
|
- lib/karafka/cli/info.rb
|
169
169
|
- lib/karafka/cli/install.rb
|
170
170
|
- lib/karafka/cli/server.rb
|
171
|
+
- lib/karafka/cli/topics.rb
|
171
172
|
- lib/karafka/connection/client.rb
|
172
173
|
- lib/karafka/connection/consumer_group_coordinator.rb
|
173
174
|
- lib/karafka/connection/listener.rb
|
@@ -305,6 +306,10 @@ files:
|
|
305
306
|
- lib/karafka/routing/features/dead_letter_queue/config.rb
|
306
307
|
- lib/karafka/routing/features/dead_letter_queue/contract.rb
|
307
308
|
- lib/karafka/routing/features/dead_letter_queue/topic.rb
|
309
|
+
- lib/karafka/routing/features/declaratives.rb
|
310
|
+
- lib/karafka/routing/features/declaratives/config.rb
|
311
|
+
- lib/karafka/routing/features/declaratives/contract.rb
|
312
|
+
- lib/karafka/routing/features/declaratives/topic.rb
|
308
313
|
- lib/karafka/routing/features/manual_offset_management.rb
|
309
314
|
- lib/karafka/routing/features/manual_offset_management/config.rb
|
310
315
|
- lib/karafka/routing/features/manual_offset_management/contract.rb
|
metadata.gz.sig
CHANGED
Binary file
|