karafka 2.4.9 → 2.4.10
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/.ruby-version +1 -1
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +3 -3
- data/config/locales/errors.yml +1 -0
- data/config/locales/pro_errors.yml +17 -0
- data/lib/karafka/base_consumer.rb +23 -0
- data/lib/karafka/contracts/consumer_group.rb +17 -0
- data/lib/karafka/instrumentation/logger_listener.rb +3 -0
- data/lib/karafka/instrumentation/notifications.rb +3 -0
- data/lib/karafka/instrumentation/vendors/appsignal/client.rb +32 -11
- data/lib/karafka/instrumentation/vendors/appsignal/errors_listener.rb +1 -1
- data/lib/karafka/messages/message.rb +6 -0
- data/lib/karafka/pro/loader.rb +2 -1
- data/lib/karafka/pro/routing/features/recurring_tasks/builder.rb +9 -8
- data/lib/karafka/pro/routing/features/scheduled_messages/builder.rb +131 -0
- data/lib/karafka/pro/routing/features/scheduled_messages/config.rb +28 -0
- data/lib/karafka/pro/routing/features/scheduled_messages/contracts/topic.rb +40 -0
- data/lib/karafka/pro/routing/features/scheduled_messages/proxy.rb +27 -0
- data/lib/karafka/pro/routing/features/scheduled_messages/topic.rb +44 -0
- data/lib/karafka/pro/routing/features/scheduled_messages.rb +24 -0
- data/lib/karafka/pro/scheduled_messages/consumer.rb +185 -0
- data/lib/karafka/pro/scheduled_messages/contracts/config.rb +56 -0
- data/lib/karafka/pro/scheduled_messages/contracts/message.rb +61 -0
- data/lib/karafka/pro/scheduled_messages/daily_buffer.rb +79 -0
- data/lib/karafka/pro/scheduled_messages/day.rb +45 -0
- data/lib/karafka/pro/scheduled_messages/deserializers/headers.rb +46 -0
- data/lib/karafka/pro/scheduled_messages/deserializers/payload.rb +35 -0
- data/lib/karafka/pro/scheduled_messages/dispatcher.rb +122 -0
- data/lib/karafka/pro/scheduled_messages/errors.rb +28 -0
- data/lib/karafka/pro/scheduled_messages/max_epoch.rb +41 -0
- data/lib/karafka/pro/scheduled_messages/proxy.rb +176 -0
- data/lib/karafka/pro/scheduled_messages/schema_validator.rb +37 -0
- data/lib/karafka/pro/scheduled_messages/serializer.rb +55 -0
- data/lib/karafka/pro/scheduled_messages/setup/config.rb +60 -0
- data/lib/karafka/pro/scheduled_messages/state.rb +62 -0
- data/lib/karafka/pro/scheduled_messages/tracker.rb +64 -0
- data/lib/karafka/pro/scheduled_messages.rb +67 -0
- data/lib/karafka/processing/executor.rb +6 -0
- data/lib/karafka/processing/strategies/default.rb +10 -0
- data/lib/karafka/railtie.rb +0 -20
- data/lib/karafka/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +26 -3
- metadata.gz.sig +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7601c2daf3eaacae67697fe28dd403ba8bd41387df90da49691912dad7ba0963
|
4
|
+
data.tar.gz: 23d6763195d2e6bf17c573859d133637c21f849e3def1eb0f852d5cb4554ae17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56202acc444f3b69af7a8b643b9e28f77ffbcadeab70858b0ffaa4b4a7a264082c636ff5c0abbaba0ac1cd6f2fb72fd6924bf6e87fe3f6e57549d5f228786e91
|
7
|
+
data.tar.gz: b39d96ef2bcd09079b044321058b4a741797673b815ff6508a8123a7a513f08ca364d05aa22dc994a25fe8c64d959bcd19342301156e97bf0b7d005d7abcb7db
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.3.
|
1
|
+
3.3.5
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Karafka Framework Changelog
|
2
2
|
|
3
|
+
## 2.4.10 (2024-09-03)
|
4
|
+
- **[Feature]** Provide Kafka based Scheduled Messages to be able to send messages in the future via a proxy topic.
|
5
|
+
- [Enhancement] Introduce a `#assigned` hook for consumers to be able to trigger actions when consumer is built and assigned but before first consume/ticking, etc.
|
6
|
+
- [Enhancement] Provide `Karafka::Messages::Message#tombstone?` to be able to quickly check if a message is a tombstone message.
|
7
|
+
- [Enhancement] Provide more flexible API for Recurring Tasks topics reconfiguration.
|
8
|
+
- [Enhancement] Remove no longer needed Rails connection releaser.
|
9
|
+
- [Enhancement] Update AppSignal client to support newer versions (tombruijn and hieuk09).
|
10
|
+
- [Fix] Fix a case where there would be a way to define multiple subscription groups for same topic with different consumer.
|
11
|
+
|
3
12
|
## 2.4.9 (2024-08-23)
|
4
13
|
- **[Feature]** Provide Kafka based Recurring (Cron) Tasks.
|
5
14
|
- [Enhancement] Wrap worker work with Rails Reloader/Executor (fusion2004)
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
karafka (2.4.
|
4
|
+
karafka (2.4.10)
|
5
5
|
base64 (~> 0.2)
|
6
6
|
karafka-core (>= 2.4.3, < 2.5.0)
|
7
7
|
karafka-rdkafka (>= 0.17.2)
|
@@ -55,9 +55,9 @@ GEM
|
|
55
55
|
karafka-testing (2.4.6)
|
56
56
|
karafka (>= 2.4.0, < 2.5.0)
|
57
57
|
waterdrop (>= 2.7.0)
|
58
|
-
karafka-web (0.10.
|
58
|
+
karafka-web (0.10.1)
|
59
59
|
erubi (~> 1.4)
|
60
|
-
karafka (>= 2.4.
|
60
|
+
karafka (>= 2.4.9, < 2.5.0)
|
61
61
|
karafka-core (>= 2.4.0, < 2.5.0)
|
62
62
|
roda (~> 3.68, >= 3.69)
|
63
63
|
tilt (~> 2.0)
|
data/config/locales/errors.yml
CHANGED
@@ -140,6 +140,7 @@ en:
|
|
140
140
|
consumer_group:
|
141
141
|
missing: needs to be present
|
142
142
|
topics_names_not_unique: all topic names within a single consumer group must be unique
|
143
|
+
topics_many_consumers_same_topic: 'topic within a single consumer group cannot have distinct consumers'
|
143
144
|
id_format: 'needs to be a string with a Kafka accepted format'
|
144
145
|
topics_format: needs to be a non-empty array
|
145
146
|
topics_namespaced_names_not_unique: |
|
@@ -64,6 +64,8 @@ en:
|
|
64
64
|
swarm_nodes_with_non_existent_nodes: includes unreachable nodes ids
|
65
65
|
|
66
66
|
recurring_tasks.active_format: 'needs to be boolean'
|
67
|
+
scheduled_messages.active_format: 'needs to be boolean'
|
68
|
+
scheduled_messages.active_missing: 'needs to be boolean'
|
67
69
|
|
68
70
|
direct_assignments.active_missing: needs to be present
|
69
71
|
direct_assignments.active_format: 'needs to be boolean'
|
@@ -109,6 +111,15 @@ en:
|
|
109
111
|
recurring_tasks.deserializer_format: 'needs to be configured'
|
110
112
|
recurring_tasks.logging_format: needs to be a boolean
|
111
113
|
|
114
|
+
scheduled_messages.consumer_class_format: 'must be a class'
|
115
|
+
scheduled_messages.dispatcher_class_format: 'must be a class'
|
116
|
+
scheduled_messages.flush_batch_size_format: needs to be an integer bigger than 0
|
117
|
+
scheduled_messages.interval_format: needs to be an integer bigger or equal to 1000
|
118
|
+
scheduled_messages.deserializers.headers_format: cannot be nil
|
119
|
+
scheduled_messages.deserializers.payload_format: cannot be nil
|
120
|
+
scheduled_messages.group_id_format: 'needs to be a string with a Kafka accepted format'
|
121
|
+
scheduled_messages.states_postfix_format: 'needs to be a string with a Kafka accepted format'
|
122
|
+
|
112
123
|
routing:
|
113
124
|
swarm_nodes_not_used: 'At least one of the nodes has no assignments'
|
114
125
|
|
@@ -118,3 +129,9 @@ en:
|
|
118
129
|
enabled_format: needs to be a boolean
|
119
130
|
changed_format: needs to be a boolean
|
120
131
|
previous_time_format: needs to be a numerical or time
|
132
|
+
|
133
|
+
scheduled_messages_message:
|
134
|
+
key_missing: must be present and should be unique within the partition
|
135
|
+
key_format: needs to be a non-empty string unique within the partition
|
136
|
+
headers_schedule_target_epoch_in_the_past: 'scheduling cannot happen in the past'
|
137
|
+
headers_format: are not correct
|
@@ -31,6 +31,20 @@ module Karafka
|
|
31
31
|
@used = false
|
32
32
|
end
|
33
33
|
|
34
|
+
# Trigger method running after consumer is fully initialized.
|
35
|
+
#
|
36
|
+
# @private
|
37
|
+
def on_initialized
|
38
|
+
handle_initialized
|
39
|
+
rescue StandardError => e
|
40
|
+
Karafka.monitor.instrument(
|
41
|
+
'error.occurred',
|
42
|
+
error: e,
|
43
|
+
caller: self,
|
44
|
+
type: 'consumer.initialized.error'
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
34
48
|
# Can be used to run preparation code prior to the job being enqueued
|
35
49
|
#
|
36
50
|
# @private
|
@@ -176,6 +190,15 @@ module Karafka
|
|
176
190
|
|
177
191
|
private
|
178
192
|
|
193
|
+
# Method called post-initialization of a consumer when all basic things are assigned.
|
194
|
+
# Since initialization via `#initialize` is complex and some states are set a bit later, this
|
195
|
+
# hook allows to initialize resources once at a time when topic, partition and other things
|
196
|
+
# are assigned to the consumer
|
197
|
+
#
|
198
|
+
# @note Please keep in mind that it will run many times when persistence is off. Basically once
|
199
|
+
# each batch.
|
200
|
+
def initialized; end
|
201
|
+
|
179
202
|
# Method that will perform business logic and on data received from Kafka (it will consume
|
180
203
|
# the data)
|
181
204
|
# @note This method needs to be implemented in a subclass. We stub it here as a failover if
|
@@ -25,6 +25,23 @@ module Karafka
|
|
25
25
|
[[%i[topics], :names_not_unique]]
|
26
26
|
end
|
27
27
|
|
28
|
+
# Prevent same topics subscriptions in one CG with different consumer classes
|
29
|
+
# This should prevent users from accidentally creating multi-sg one CG setup with weird
|
30
|
+
# different consumer usage. If you need to consume same topic twice, use distinct CGs.
|
31
|
+
virtual do |data, errors|
|
32
|
+
next unless errors.empty?
|
33
|
+
|
34
|
+
topics_consumers = Hash.new { |h, k| h[k] = Set.new }
|
35
|
+
|
36
|
+
data.fetch(:topics).map do |topic|
|
37
|
+
topics_consumers[topic[:name]] << topic[:consumer]
|
38
|
+
end
|
39
|
+
|
40
|
+
next if topics_consumers.values.map(&:size).all? { |count| count == 1 }
|
41
|
+
|
42
|
+
[[%i[topics], :many_consumers_same_topic]]
|
43
|
+
end
|
44
|
+
|
28
45
|
virtual do |data, errors|
|
29
46
|
next unless errors.empty?
|
30
47
|
next unless ::Karafka::App.config.strict_topics_namespacing
|
@@ -275,6 +275,9 @@ module Karafka
|
|
275
275
|
details = (error.backtrace || []).join("\n")
|
276
276
|
|
277
277
|
case type
|
278
|
+
when 'consumer.initialized.error'
|
279
|
+
error "Consumer initialized error: #{error}"
|
280
|
+
error details
|
278
281
|
when 'consumer.consume.error'
|
279
282
|
error "Consumer consuming error: #{error}"
|
280
283
|
error details
|
@@ -23,11 +23,16 @@ module Karafka
|
|
23
23
|
# @param action_name [String] action name. For processing this should be equal to
|
24
24
|
# consumer class + method name
|
25
25
|
def start_transaction(action_name)
|
26
|
-
transaction =
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
transaction =
|
27
|
+
if version_4_or_newer?
|
28
|
+
::Appsignal::Transaction.create(namespace_name)
|
29
|
+
else
|
30
|
+
::Appsignal::Transaction.create(
|
31
|
+
SecureRandom.uuid,
|
32
|
+
namespace_name,
|
33
|
+
::Appsignal::Transaction::GenericRequest.new({})
|
34
|
+
)
|
35
|
+
end
|
31
36
|
|
32
37
|
transaction.set_action_if_nil(action_name)
|
33
38
|
end
|
@@ -45,10 +50,10 @@ module Karafka
|
|
45
50
|
def metadata=(metadata_hash)
|
46
51
|
return unless transaction?
|
47
52
|
|
48
|
-
|
53
|
+
current_transaction = transaction
|
49
54
|
|
50
55
|
stringify_hash(metadata_hash).each do |key, value|
|
51
|
-
|
56
|
+
current_transaction.set_metadata(key, value)
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
@@ -78,15 +83,20 @@ module Karafka
|
|
78
83
|
)
|
79
84
|
end
|
80
85
|
|
81
|
-
#
|
86
|
+
# Report the error that occurred to Appsignal
|
82
87
|
#
|
83
88
|
# @param error [Object] error we want to ship to Appsignal
|
84
|
-
def
|
89
|
+
def report_error(error)
|
90
|
+
if ::Appsignal.respond_to?(:report_error)
|
91
|
+
# This helper will always report the error
|
92
|
+
::Appsignal.report_error(error) do |transaction|
|
93
|
+
transaction.set_namespace(namespace_name)
|
94
|
+
end
|
85
95
|
# If we have an active transaction we should use it instead of creating a generic one
|
86
96
|
# That way proper namespace and other data may be transferred
|
87
97
|
#
|
88
98
|
# In case there is no transaction, a new generic background job one will be used
|
89
|
-
|
99
|
+
elsif transaction?
|
90
100
|
transaction.set_error(error)
|
91
101
|
else
|
92
102
|
::Appsignal.send_error(error) do |transaction|
|
@@ -99,7 +109,11 @@ module Karafka
|
|
99
109
|
# @param name [Symbol] probe name
|
100
110
|
# @param probe [Proc] code to run every minute
|
101
111
|
def register_probe(name, probe)
|
102
|
-
::Appsignal::
|
112
|
+
if ::Appsignal::Probes.respond_to?(:register)
|
113
|
+
::Appsignal::Probes.register(name, probe)
|
114
|
+
else
|
115
|
+
::Appsignal::Minutely.probes.register(name, probe)
|
116
|
+
end
|
103
117
|
end
|
104
118
|
|
105
119
|
private
|
@@ -129,6 +143,13 @@ module Karafka
|
|
129
143
|
def namespace_name
|
130
144
|
@namespace_name ||= ::Appsignal::Transaction::BACKGROUND_JOB
|
131
145
|
end
|
146
|
+
|
147
|
+
# @return [Boolean] is this v4+ version of Appsignal gem or older. Used for backwards
|
148
|
+
# compatibility checks.
|
149
|
+
def version_4_or_newer?
|
150
|
+
@version_4_or_newer ||=
|
151
|
+
Gem::Version.new(Appsignal::VERSION) >= Gem::Version.new('4.0.0')
|
152
|
+
end
|
132
153
|
end
|
133
154
|
end
|
134
155
|
end
|
@@ -51,6 +51,12 @@ module Karafka
|
|
51
51
|
@deserialized
|
52
52
|
end
|
53
53
|
|
54
|
+
# @return [Boolean] true if the message has a key and raw payload is nil, it is a tombstone
|
55
|
+
# event. Otherwise it is not.
|
56
|
+
def tombstone?
|
57
|
+
!raw_key.nil? && @raw_payload.nil?
|
58
|
+
end
|
59
|
+
|
54
60
|
private
|
55
61
|
|
56
62
|
# @return [Object] deserialized data
|
data/lib/karafka/pro/loader.rb
CHANGED
@@ -22,9 +22,7 @@ module Karafka
|
|
22
22
|
#
|
23
23
|
# @param active [Boolean] should recurring tasks be active. We use a boolean flag to
|
24
24
|
# have API consistency in the system, so it matches other routing related APIs.
|
25
|
-
# @param block [Proc] optional reconfiguration of the
|
26
|
-
# @note Since we cannot provide two blocks, reconfiguration of logs topic can be only
|
27
|
-
# done if user explicitly redefines it in the routing.
|
25
|
+
# @param block [Proc] optional reconfiguration of the topics definitions.
|
28
26
|
def recurring_tasks(active = false, &block)
|
29
27
|
return unless active
|
30
28
|
|
@@ -39,7 +37,7 @@ module Karafka
|
|
39
37
|
consumer_group tasks_cfg.group_id do
|
40
38
|
# Registers the primary topic that we use to control schedules execution. This is
|
41
39
|
# the one that we use to trigger recurring tasks.
|
42
|
-
topic(topics_cfg.schedules) do
|
40
|
+
schedules_topic = topic(topics_cfg.schedules) do
|
43
41
|
consumer tasks_cfg.consumer_class
|
44
42
|
deserializer tasks_cfg.deserializer
|
45
43
|
# Because the topic method name as well as builder proxy method name is the same
|
@@ -85,14 +83,15 @@ module Karafka
|
|
85
83
|
during_retry: false
|
86
84
|
)
|
87
85
|
|
88
|
-
|
89
|
-
|
90
|
-
|
86
|
+
# If this is the direct schedules redefinition style, we run it
|
87
|
+
# The second one (see end of this method) allows for linear reconfiguration of
|
88
|
+
# both the topics
|
89
|
+
instance_eval(&block) if block && block.arity.zero?
|
91
90
|
end
|
92
91
|
|
93
92
|
# This topic is to store logs that we can then inspect either from the admin or via
|
94
93
|
# the Web UI
|
95
|
-
topic(topics_cfg.logs) do
|
94
|
+
logs_topic = topic(topics_cfg.logs) do
|
96
95
|
active(false)
|
97
96
|
deserializer tasks_cfg.deserializer
|
98
97
|
target.recurring_tasks(true)
|
@@ -104,6 +103,8 @@ module Karafka
|
|
104
103
|
'retention.ms': 604_800_000
|
105
104
|
)
|
106
105
|
end
|
106
|
+
|
107
|
+
yield(schedules_topic, logs_topic) if block && block.arity.positive?
|
107
108
|
end
|
108
109
|
end
|
109
110
|
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Pro
|
16
|
+
module Routing
|
17
|
+
module Features
|
18
|
+
class ScheduledMessages < Base
|
19
|
+
# Routing extensions for scheduled messages
|
20
|
+
module Builder
|
21
|
+
# Enabled scheduled messages operations and adds needed topics and other stuff.
|
22
|
+
#
|
23
|
+
# @param group_name [String, false] name for scheduled messages topic that is also used
|
24
|
+
# as a group identifier. Users can have multiple schedule topics flows to prevent key
|
25
|
+
# collisions, prioritize and do other stuff. `false` if not active.
|
26
|
+
# @param block [Proc] optional reconfiguration of the topics definitions.
|
27
|
+
# @note Namespace for topics should include the divider as it is not automatically
|
28
|
+
# added.
|
29
|
+
def scheduled_messages(group_name = false, &block)
|
30
|
+
return unless group_name
|
31
|
+
|
32
|
+
# Load zlib only if user enables scheduled messages
|
33
|
+
require 'zlib'
|
34
|
+
|
35
|
+
# We set it to 5 so we have enough space to handle more events. All related topics
|
36
|
+
# should have same partition count.
|
37
|
+
default_partitions = 5
|
38
|
+
msg_cfg = App.config.scheduled_messages
|
39
|
+
|
40
|
+
consumer_group msg_cfg.group_id do
|
41
|
+
# Registers the primary topic that we use to control schedules execution. This is
|
42
|
+
# the one that we use to trigger scheduled messages.
|
43
|
+
messages_topic = topic(group_name) do
|
44
|
+
instance_eval(&block) if block && block.arity.zero?
|
45
|
+
|
46
|
+
consumer msg_cfg.consumer_class
|
47
|
+
|
48
|
+
deserializers(
|
49
|
+
headers: msg_cfg.deserializers.headers
|
50
|
+
)
|
51
|
+
|
52
|
+
# Because the topic method name as well as builder proxy method name is the same
|
53
|
+
# we need to reference it via target directly
|
54
|
+
target.scheduled_messages(true)
|
55
|
+
|
56
|
+
# We manage offsets directly because messages can have both schedules and
|
57
|
+
# commands and we need to apply them only when we need to
|
58
|
+
manual_offset_management(true)
|
59
|
+
|
60
|
+
# We use multi-batch operations and in-memory state for schedules. This needs to
|
61
|
+
# always operate without re-creation.
|
62
|
+
consumer_persistence(true)
|
63
|
+
|
64
|
+
# This needs to be enabled for the eof to work correctly
|
65
|
+
kafka('enable.partition.eof': true, inherit: true)
|
66
|
+
eofed(true)
|
67
|
+
|
68
|
+
# Since this is a topic that gets replayed because of schedule management, we do
|
69
|
+
# want to get more data faster during recovery
|
70
|
+
max_messages(10_000)
|
71
|
+
|
72
|
+
max_wait_time(1_000)
|
73
|
+
|
74
|
+
# This is a setup that should allow messages to be compacted fairly fast. Since
|
75
|
+
# each dispatched message should be removed via tombstone, they do not have to
|
76
|
+
# be present in the topic for too long.
|
77
|
+
config(
|
78
|
+
partitions: default_partitions,
|
79
|
+
# Will ensure, that after tombstone is present, given scheduled message, that
|
80
|
+
# has been dispatched is removed by Kafka
|
81
|
+
'cleanup.policy': 'compact',
|
82
|
+
# When 10% or more dispatches are done, compact data
|
83
|
+
'min.cleanable.dirty.ratio': 0.1,
|
84
|
+
# Frequent segment rotation to support intense compaction
|
85
|
+
'segment.ms': 3_600_000,
|
86
|
+
'delete.retention.ms': 3_600_000,
|
87
|
+
'segment.bytes': 52_428_800
|
88
|
+
)
|
89
|
+
|
90
|
+
# This is the core of execution. Since we dispatch data in time intervals, we
|
91
|
+
# need to be able to do this even when no new data is coming
|
92
|
+
periodic(
|
93
|
+
interval: msg_cfg.interval,
|
94
|
+
during_pause: false,
|
95
|
+
during_retry: false
|
96
|
+
)
|
97
|
+
|
98
|
+
# If this is the direct schedules redefinition style, we run it
|
99
|
+
# The second one (see end of this method) allows for linear reconfiguration of
|
100
|
+
# both the topics
|
101
|
+
instance_eval(&block) if block && block.arity.zero?
|
102
|
+
end
|
103
|
+
|
104
|
+
# Holds states of scheduler per each of the partitions since they tick
|
105
|
+
# independently. We only hold future statistics not to have to deal with
|
106
|
+
# any type of state restoration
|
107
|
+
states_topic = topic("#{group_name}#{msg_cfg.states_postfix}") do
|
108
|
+
active(false)
|
109
|
+
target.scheduled_messages(true)
|
110
|
+
config(
|
111
|
+
partitions: default_partitions,
|
112
|
+
'cleanup.policy': 'compact',
|
113
|
+
'min.cleanable.dirty.ratio': 0.1,
|
114
|
+
'segment.ms': 3_600_000,
|
115
|
+
'delete.retention.ms': 3_600_000,
|
116
|
+
'segment.bytes': 52_428_800
|
117
|
+
)
|
118
|
+
deserializers(
|
119
|
+
payload: msg_cfg.deserializers.payload
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
yield(messages_topic, states_topic) if block && block.arity.positive?
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Pro
|
16
|
+
module Routing
|
17
|
+
module Features
|
18
|
+
class ScheduledMessages < Base
|
19
|
+
# Scheduled messages configuration
|
20
|
+
Config = Struct.new(
|
21
|
+
:active,
|
22
|
+
keyword_init: true
|
23
|
+
) { alias_method :active?, :active }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Pro
|
16
|
+
module Routing
|
17
|
+
module Features
|
18
|
+
class ScheduledMessages < Base
|
19
|
+
# Namespace for scheduled messages contracts
|
20
|
+
module Contracts
|
21
|
+
# Rules around scheduled messages settings
|
22
|
+
class Topic < Karafka::Contracts::Base
|
23
|
+
configure do |config|
|
24
|
+
config.error_messages = YAML.safe_load(
|
25
|
+
File.read(
|
26
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
|
27
|
+
)
|
28
|
+
).fetch('en').fetch('validations').fetch('topic')
|
29
|
+
end
|
30
|
+
|
31
|
+
nested(:scheduled_messages) do
|
32
|
+
required(:active) { |val| [true, false].include?(val) }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Pro
|
16
|
+
module Routing
|
17
|
+
module Features
|
18
|
+
class ScheduledMessages < Base
|
19
|
+
# Routing proxy extensions for scheduled messages
|
20
|
+
module Proxy
|
21
|
+
include Builder
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Pro
|
16
|
+
module Routing
|
17
|
+
module Features
|
18
|
+
class ScheduledMessages < Base
|
19
|
+
# Topic extensions to be able to check if given topic is a scheduled messages topic
|
20
|
+
# Please note, that this applies to both the schedules topic and logs topic
|
21
|
+
module Topic
|
22
|
+
# @param active [Boolean] should this topic be considered related to scheduled messages
|
23
|
+
def scheduled_messages(active = false)
|
24
|
+
@scheduled_messages ||= Config.new(active: active)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Boolean] is this an ActiveJob topic
|
28
|
+
def scheduled_messages?
|
29
|
+
scheduled_messages.active?
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Hash] topic with all its native configuration options plus scheduled
|
33
|
+
# messages namespace settings
|
34
|
+
def to_h
|
35
|
+
super.merge(
|
36
|
+
scheduled_messages: scheduled_messages.to_h
|
37
|
+
).freeze
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
5
|
+
#
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
7
|
+
# repository and their usage requires commercial license agreement.
|
8
|
+
#
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
10
|
+
#
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
12
|
+
# your code to Maciej Mensfeld.
|
13
|
+
|
14
|
+
module Karafka
|
15
|
+
module Pro
|
16
|
+
module Routing
|
17
|
+
module Features
|
18
|
+
# Scheduled messages functionality routing namespace
|
19
|
+
class ScheduledMessages < Base
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|