karafka 2.0.0 → 2.1.0
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/FUNDING.yml +1 -0
- data/.github/workflows/ci.yml +40 -16
- data/.rspec +4 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +459 -796
- data/Gemfile +3 -2
- data/Gemfile.lock +44 -32
- data/LICENSE +1 -1
- data/README.md +22 -17
- data/bin/integrations +86 -26
- data/bin/karafka +1 -13
- data/bin/rspecs +6 -0
- data/bin/verify_license_integrity +37 -0
- data/certs/cert_chain.pem +26 -0
- data/config/{errors.yml → locales/errors.yml} +34 -6
- data/config/locales/pro_errors.yml +34 -0
- data/docker-compose.yml +4 -30
- data/karafka.gemspec +17 -10
- data/lib/active_job/karafka.rb +3 -7
- data/lib/active_job/queue_adapters/karafka_adapter.rb +7 -1
- data/lib/karafka/active_job/consumer.rb +29 -6
- data/lib/karafka/active_job/current_attributes/loading.rb +36 -0
- data/lib/karafka/active_job/current_attributes/persistence.rb +28 -0
- data/lib/karafka/active_job/current_attributes.rb +42 -0
- data/lib/karafka/active_job/dispatcher.rb +34 -3
- data/lib/karafka/active_job/job_options_contract.rb +13 -2
- data/lib/karafka/admin.rb +246 -0
- data/lib/karafka/app.rb +30 -7
- data/lib/karafka/base_consumer.rb +124 -82
- data/lib/karafka/cli/base.rb +20 -0
- data/lib/karafka/cli/console.rb +13 -8
- data/lib/karafka/cli/info.rb +3 -2
- data/lib/karafka/cli/server.rb +55 -8
- data/lib/karafka/cli/topics.rb +146 -0
- data/lib/karafka/connection/client.rb +118 -61
- data/lib/karafka/connection/consumer_group_coordinator.rb +48 -0
- data/lib/karafka/connection/listener.rb +78 -30
- data/lib/karafka/connection/listeners_batch.rb +18 -2
- data/lib/karafka/connection/rebalance_manager.rb +3 -0
- data/lib/karafka/contracts/config.rb +1 -1
- data/lib/karafka/contracts/consumer_group.rb +22 -9
- data/lib/karafka/contracts/server_cli_options.rb +71 -11
- data/lib/karafka/contracts/topic.rb +65 -0
- data/lib/karafka/contracts.rb +1 -1
- data/lib/karafka/embedded.rb +36 -0
- data/lib/karafka/errors.rb +6 -4
- data/lib/karafka/helpers/colorize.rb +6 -0
- data/lib/karafka/instrumentation/callbacks/error.rb +3 -4
- data/lib/karafka/instrumentation/callbacks/statistics.rb +14 -4
- data/lib/karafka/instrumentation/logger_listener.rb +151 -22
- data/lib/karafka/instrumentation/notifications.rb +26 -7
- data/lib/karafka/instrumentation/proctitle_listener.rb +7 -16
- data/lib/karafka/instrumentation/vendors/datadog/dashboard.json +1 -1
- data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +153 -0
- data/lib/karafka/instrumentation/vendors/datadog/{listener.rb → metrics_listener.rb} +62 -35
- data/lib/karafka/instrumentation/vendors/kubernetes/liveness_listener.rb +166 -0
- data/lib/karafka/licenser.rb +53 -50
- data/lib/karafka/messages/builders/batch_metadata.rb +8 -8
- data/lib/karafka/messages/builders/messages.rb +6 -2
- data/lib/karafka/messages/message.rb +14 -2
- data/lib/karafka/messages/messages.rb +5 -0
- data/lib/karafka/messages/parser.rb +14 -0
- data/lib/karafka/patches/rdkafka/bindings.rb +132 -0
- data/lib/karafka/pro/active_job/consumer.rb +10 -9
- data/lib/karafka/pro/active_job/dispatcher.rb +28 -3
- data/lib/karafka/pro/active_job/job_options_contract.rb +16 -3
- data/lib/karafka/pro/encryption/cipher.rb +58 -0
- data/lib/karafka/pro/encryption/contracts/config.rb +79 -0
- data/lib/karafka/pro/encryption/errors.rb +24 -0
- data/lib/karafka/pro/encryption/messages/middleware.rb +46 -0
- data/lib/karafka/pro/encryption/messages/parser.rb +56 -0
- data/lib/karafka/pro/encryption/setup/config.rb +48 -0
- data/lib/karafka/pro/encryption.rb +47 -0
- data/lib/karafka/pro/iterator.rb +253 -0
- data/lib/karafka/pro/loader.rb +52 -26
- data/lib/karafka/pro/performance_tracker.rb +10 -6
- data/lib/karafka/pro/processing/collapser.rb +62 -0
- data/lib/karafka/pro/processing/coordinator.rb +92 -16
- data/lib/karafka/pro/processing/filters/base.rb +61 -0
- data/lib/karafka/pro/processing/filters/delayer.rb +70 -0
- data/lib/karafka/pro/processing/filters/expirer.rb +51 -0
- data/lib/karafka/pro/processing/filters/throttler.rb +84 -0
- data/lib/karafka/pro/processing/filters/virtual_limiter.rb +52 -0
- data/lib/karafka/pro/processing/filters_applier.rb +104 -0
- data/lib/karafka/pro/processing/jobs/consume_non_blocking.rb +7 -5
- data/lib/karafka/pro/processing/jobs/revoked_non_blocking.rb +37 -0
- data/lib/karafka/pro/processing/jobs_builder.rb +22 -4
- data/lib/karafka/pro/processing/partitioner.rb +33 -24
- data/lib/karafka/pro/processing/scheduler.rb +27 -8
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom.rb +68 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom_vp.rb +74 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom.rb +72 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom_vp.rb +76 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom.rb +64 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom_vp.rb +68 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_mom.rb +64 -0
- data/lib/karafka/pro/processing/strategies/aj/dlq_mom_vp.rb +69 -0
- data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom.rb +38 -0
- data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom_vp.rb +64 -0
- data/lib/karafka/pro/processing/strategies/aj/ftr_mom.rb +38 -0
- data/lib/karafka/pro/processing/strategies/aj/ftr_mom_vp.rb +58 -0
- data/lib/karafka/pro/processing/strategies/aj/lrj_mom.rb +37 -0
- data/lib/karafka/pro/processing/strategies/aj/lrj_mom_vp.rb +79 -0
- data/lib/karafka/pro/processing/strategies/aj/mom.rb +36 -0
- data/lib/karafka/pro/processing/strategies/aj/mom_vp.rb +52 -0
- data/lib/karafka/pro/processing/strategies/base.rb +26 -0
- data/lib/karafka/pro/processing/strategies/default.rb +105 -0
- data/lib/karafka/pro/processing/strategies/dlq/default.rb +131 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr.rb +61 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj.rb +75 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom.rb +71 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom_vp.rb +43 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_vp.rb +41 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_mom.rb +69 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_mom_vp.rb +41 -0
- data/lib/karafka/pro/processing/strategies/dlq/ftr_vp.rb +40 -0
- data/lib/karafka/pro/processing/strategies/dlq/lrj.rb +63 -0
- data/lib/karafka/pro/processing/strategies/dlq/lrj_mom.rb +63 -0
- data/lib/karafka/pro/processing/strategies/dlq/lrj_mom_vp.rb +36 -0
- data/lib/karafka/pro/processing/strategies/dlq/lrj_vp.rb +39 -0
- data/lib/karafka/pro/processing/strategies/dlq/mom.rb +68 -0
- data/lib/karafka/pro/processing/strategies/dlq/mom_vp.rb +37 -0
- data/lib/karafka/pro/processing/strategies/dlq/vp.rb +40 -0
- data/lib/karafka/pro/processing/strategies/ftr/default.rb +104 -0
- data/lib/karafka/pro/processing/strategies/ftr/vp.rb +40 -0
- data/lib/karafka/pro/processing/strategies/lrj/default.rb +87 -0
- data/lib/karafka/pro/processing/strategies/lrj/ftr.rb +69 -0
- data/lib/karafka/pro/processing/strategies/lrj/ftr_mom.rb +67 -0
- data/lib/karafka/pro/processing/strategies/lrj/ftr_mom_vp.rb +40 -0
- data/lib/karafka/pro/processing/strategies/lrj/ftr_vp.rb +39 -0
- data/lib/karafka/pro/processing/strategies/lrj/mom.rb +80 -0
- data/lib/karafka/pro/processing/strategies/lrj/mom_vp.rb +38 -0
- data/lib/karafka/pro/processing/strategies/lrj/vp.rb +36 -0
- data/lib/karafka/pro/processing/strategies/mom/default.rb +46 -0
- data/lib/karafka/pro/processing/strategies/mom/ftr.rb +53 -0
- data/lib/karafka/pro/processing/strategies/mom/ftr_vp.rb +37 -0
- data/lib/karafka/pro/processing/strategies/mom/vp.rb +35 -0
- data/lib/karafka/pro/processing/strategies/vp/default.rb +104 -0
- data/lib/karafka/pro/{contracts/base.rb → processing/strategies.rb} +6 -5
- data/lib/karafka/pro/processing/strategy_selector.rb +84 -0
- data/lib/karafka/pro/processing/virtual_offset_manager.rb +147 -0
- data/lib/karafka/pro/routing/features/base.rb +24 -0
- data/lib/karafka/pro/routing/features/dead_letter_queue/contract.rb +50 -0
- data/lib/karafka/pro/routing/features/dead_letter_queue.rb +27 -0
- data/lib/karafka/pro/routing/{builder_extensions.rb → features/delaying/config.rb} +8 -11
- data/lib/karafka/pro/routing/features/delaying/contract.rb +38 -0
- data/lib/karafka/pro/routing/features/delaying/topic.rb +59 -0
- data/lib/karafka/pro/routing/features/delaying.rb +29 -0
- data/lib/karafka/pro/routing/features/expiring/config.rb +27 -0
- data/lib/karafka/pro/routing/features/expiring/contract.rb +38 -0
- data/lib/karafka/pro/routing/features/expiring/topic.rb +59 -0
- data/lib/karafka/pro/routing/features/expiring.rb +27 -0
- data/lib/karafka/pro/routing/features/filtering/config.rb +40 -0
- data/lib/karafka/pro/routing/features/filtering/contract.rb +41 -0
- data/lib/karafka/pro/routing/features/filtering/topic.rb +51 -0
- data/lib/karafka/pro/routing/features/filtering.rb +27 -0
- data/lib/karafka/pro/routing/features/long_running_job/config.rb +28 -0
- data/lib/karafka/pro/routing/features/long_running_job/contract.rb +37 -0
- data/lib/karafka/pro/routing/features/long_running_job/topic.rb +42 -0
- data/lib/karafka/pro/routing/features/long_running_job.rb +28 -0
- data/lib/karafka/pro/routing/features/throttling/config.rb +32 -0
- data/lib/karafka/pro/routing/features/throttling/contract.rb +41 -0
- data/lib/karafka/pro/routing/features/throttling/topic.rb +69 -0
- data/lib/karafka/pro/routing/features/throttling.rb +30 -0
- data/lib/karafka/pro/routing/features/virtual_partitions/config.rb +30 -0
- data/lib/karafka/pro/routing/features/virtual_partitions/contract.rb +52 -0
- data/lib/karafka/pro/routing/features/virtual_partitions/topic.rb +56 -0
- data/lib/karafka/pro/routing/features/virtual_partitions.rb +27 -0
- data/lib/karafka/process.rb +23 -8
- data/lib/karafka/processing/coordinator.rb +102 -23
- data/lib/karafka/processing/coordinators_buffer.rb +5 -1
- data/lib/karafka/processing/executor.rb +51 -21
- data/lib/karafka/processing/executors_buffer.rb +10 -26
- data/lib/karafka/processing/jobs/base.rb +6 -2
- data/lib/karafka/processing/jobs/consume.rb +8 -5
- data/lib/karafka/processing/jobs/idle.rb +24 -0
- data/lib/karafka/processing/jobs_builder.rb +2 -3
- data/lib/karafka/processing/jobs_queue.rb +14 -8
- data/lib/karafka/processing/partitioner.rb +3 -1
- data/lib/karafka/processing/result.rb +14 -1
- data/lib/karafka/processing/strategies/aj_dlq_mom.rb +44 -0
- data/lib/karafka/processing/strategies/aj_mom.rb +21 -0
- data/lib/karafka/processing/strategies/base.rb +52 -0
- data/lib/karafka/processing/strategies/default.rb +142 -0
- data/lib/karafka/processing/strategies/dlq.rb +88 -0
- data/lib/karafka/processing/strategies/dlq_mom.rb +49 -0
- data/lib/karafka/processing/strategies/mom.rb +29 -0
- data/lib/karafka/processing/strategy_selector.rb +47 -0
- data/lib/karafka/processing/worker.rb +8 -3
- data/lib/karafka/railtie.rb +24 -12
- data/lib/karafka/routing/activity_manager.rb +84 -0
- data/lib/karafka/routing/builder.rb +20 -0
- data/lib/karafka/routing/consumer_group.rb +38 -4
- data/lib/karafka/routing/consumer_mapper.rb +0 -10
- data/lib/karafka/routing/features/active_job/builder.rb +33 -0
- data/lib/karafka/routing/features/active_job/config.rb +15 -0
- data/lib/karafka/routing/features/active_job/contract.rb +41 -0
- data/lib/karafka/routing/features/active_job/topic.rb +33 -0
- data/lib/karafka/routing/features/active_job.rb +13 -0
- data/lib/karafka/routing/features/base/expander.rb +53 -0
- data/lib/karafka/routing/features/base.rb +34 -0
- data/lib/karafka/routing/features/dead_letter_queue/config.rb +19 -0
- data/lib/karafka/routing/features/dead_letter_queue/contract.rb +42 -0
- data/lib/karafka/routing/features/dead_letter_queue/topic.rb +41 -0
- data/lib/karafka/routing/features/dead_letter_queue.rb +16 -0
- 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/routing/features/manual_offset_management/config.rb +15 -0
- data/lib/karafka/routing/features/manual_offset_management/contract.rb +24 -0
- data/lib/karafka/routing/features/manual_offset_management/topic.rb +35 -0
- data/lib/karafka/routing/features/manual_offset_management.rb +18 -0
- data/lib/karafka/routing/proxy.rb +18 -20
- data/lib/karafka/routing/router.rb +27 -2
- data/lib/karafka/routing/subscription_group.rb +43 -5
- data/lib/karafka/routing/subscription_groups_builder.rb +6 -1
- data/lib/karafka/routing/topic.rb +17 -5
- data/lib/karafka/routing/topics.rb +8 -0
- data/lib/karafka/runner.rb +1 -0
- data/lib/karafka/serialization/json/deserializer.rb +1 -0
- data/lib/karafka/server.rb +58 -28
- data/lib/karafka/setup/attributes_map.rb +344 -0
- data/lib/karafka/setup/config.rb +48 -19
- data/lib/karafka/status.rb +35 -7
- data/lib/karafka/templates/karafka.rb.erb +14 -6
- data/lib/karafka/time_trackers/base.rb +1 -6
- data/lib/karafka/time_trackers/pause.rb +49 -19
- data/lib/karafka/time_trackers/poll.rb +7 -3
- data/lib/karafka/version.rb +1 -1
- data/lib/karafka.rb +56 -3
- data/renovate.json +6 -0
- data.tar.gz.sig +0 -0
- metadata +189 -61
- metadata.gz.sig +0 -0
- data/bin/wait_for_kafka +0 -20
- data/certs/mensfeld.pem +0 -25
- data/lib/karafka/active_job/routing/extensions.rb +0 -31
- data/lib/karafka/contracts/consumer_group_topic.rb +0 -42
- data/lib/karafka/instrumentation.rb +0 -21
- data/lib/karafka/pro/base_consumer.rb +0 -82
- data/lib/karafka/pro/contracts/consumer_group.rb +0 -34
- data/lib/karafka/pro/contracts/consumer_group_topic.rb +0 -33
- data/lib/karafka/pro/routing/topic_extensions.rb +0 -38
|
@@ -0,0 +1,147 @@
|
|
|
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 Processing
|
|
17
|
+
# Manager that keeps track of our offsets with the virtualization layer that are local
|
|
18
|
+
# to given partition assignment. It allows for easier offset management for virtual
|
|
19
|
+
# virtual partition cases as it provides us ability to mark as consumed and move the
|
|
20
|
+
# real offset behind as expected.
|
|
21
|
+
#
|
|
22
|
+
# @note We still use the regular coordinator "real" offset management as we want to have
|
|
23
|
+
# them as separated as possible because the real seek offset management is also used for
|
|
24
|
+
# pausing, filtering and others and should not be impacted by the virtual one
|
|
25
|
+
#
|
|
26
|
+
# @note This manager is **not** thread-safe by itself. It should operate from coordinator
|
|
27
|
+
# locked locations.
|
|
28
|
+
class VirtualOffsetManager
|
|
29
|
+
attr_reader :groups
|
|
30
|
+
|
|
31
|
+
# @param topic [String]
|
|
32
|
+
# @param partition [Integer]
|
|
33
|
+
#
|
|
34
|
+
# @note We need topic and partition because we use a seek message (virtual) for real offset
|
|
35
|
+
# management. We could keep real message reference but this can be memory consuming
|
|
36
|
+
# and not worth it.
|
|
37
|
+
def initialize(topic, partition)
|
|
38
|
+
@topic = topic
|
|
39
|
+
@partition = partition
|
|
40
|
+
@groups = []
|
|
41
|
+
@marked = {}
|
|
42
|
+
@real_offset = -1
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Clears the manager for a next collective operation
|
|
46
|
+
def clear
|
|
47
|
+
@groups.clear
|
|
48
|
+
@marked = {}
|
|
49
|
+
@real_offset = -1
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Registers an offset group coming from one virtual consumer. In order to move the real
|
|
53
|
+
# underlying offset accordingly, we need to make sure to track the virtual consumers
|
|
54
|
+
# offsets groups independently and only materialize the end result.
|
|
55
|
+
#
|
|
56
|
+
# @param offsets_group [Array<Integer>] offsets from one virtual consumer
|
|
57
|
+
def register(offsets_group)
|
|
58
|
+
@groups << offsets_group
|
|
59
|
+
|
|
60
|
+
offsets_group.each { |offset| @marked[offset] = false }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Marks given message as marked (virtually consumed).
|
|
64
|
+
# We mark given message offset and other earlier offsets from the same group as done
|
|
65
|
+
# and we can refresh our real offset representation based on that as it might have changed
|
|
66
|
+
# to a newer real offset.
|
|
67
|
+
# @param message [Karafka::Messages::Message] message coming from VP we want to mark
|
|
68
|
+
def mark(message)
|
|
69
|
+
offset = message.offset
|
|
70
|
+
|
|
71
|
+
group = @groups.find { |reg_group| reg_group.include?(offset) }
|
|
72
|
+
|
|
73
|
+
# This case can happen when someone uses MoM and wants to mark message from a previous
|
|
74
|
+
# batch as consumed. We can add it, since the real offset refresh will point to it
|
|
75
|
+
unless group
|
|
76
|
+
group = [offset]
|
|
77
|
+
@groups << group
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
position = group.index(offset)
|
|
81
|
+
|
|
82
|
+
# Mark all previous messages from the same group also as virtually consumed
|
|
83
|
+
group[0..position].each do |markable_offset|
|
|
84
|
+
@marked[markable_offset] = true
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Recompute the real offset representation
|
|
88
|
+
materialize_real_offset
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Mark all from all groups including the `message`.
|
|
92
|
+
# Useful when operating in a collapsed state for marking
|
|
93
|
+
# @param message [Karafka::Messages::Message]
|
|
94
|
+
def mark_until(message)
|
|
95
|
+
mark(message)
|
|
96
|
+
|
|
97
|
+
@groups.each do |group|
|
|
98
|
+
group.each do |offset|
|
|
99
|
+
next if offset > message.offset
|
|
100
|
+
|
|
101
|
+
@marked[offset] = true
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
materialize_real_offset
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# @return [Array<Integer>] Offsets of messages already marked as consumed virtually
|
|
109
|
+
def marked
|
|
110
|
+
@marked.select { |_, status| status }.map(&:first).sort
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Is there a real offset we can mark as consumed
|
|
114
|
+
# @return [Boolean]
|
|
115
|
+
def markable?
|
|
116
|
+
!@real_offset.negative?
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# @return [Messages::Seek] markable message for real offset marking
|
|
120
|
+
def markable
|
|
121
|
+
raise Errors::InvalidRealOffsetUsage unless markable?
|
|
122
|
+
|
|
123
|
+
Messages::Seek.new(
|
|
124
|
+
@topic,
|
|
125
|
+
@partition,
|
|
126
|
+
@real_offset
|
|
127
|
+
)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private
|
|
131
|
+
|
|
132
|
+
# Recomputes the biggest possible real offset we can have.
|
|
133
|
+
# It picks the the biggest offset that has uninterrupted stream of virtually marked as
|
|
134
|
+
# consumed because this will be the collective offset.
|
|
135
|
+
def materialize_real_offset
|
|
136
|
+
@marked.to_a.sort_by(&:first).each do |offset, marked|
|
|
137
|
+
break unless marked
|
|
138
|
+
|
|
139
|
+
@real_offset = offset
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
@real_offset = (@marked.keys.min - 1) if @real_offset.negative?
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
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
|
+
# Base class for all the Pro features
|
|
19
|
+
class Base < Karafka::Routing::Features::Base
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
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 DeadLetterQueue < Base
|
|
19
|
+
# Extended rules for dead letter queue settings
|
|
20
|
+
class Contract < Contracts::Base
|
|
21
|
+
configure do |config|
|
|
22
|
+
config.error_messages = YAML.safe_load(
|
|
23
|
+
File.read(
|
|
24
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
|
|
25
|
+
)
|
|
26
|
+
).fetch('en').fetch('validations').fetch('topic')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Make sure that when we use virtual partitions with DLQ, at least one retry is set
|
|
30
|
+
# We cannot use VP with DLQ without retries as we in order to provide ordering
|
|
31
|
+
# warranties on errors with VP, we need to collapse the VPs concurrency and retry
|
|
32
|
+
# without any indeterministic work
|
|
33
|
+
virtual do |data, errors|
|
|
34
|
+
next unless errors.empty?
|
|
35
|
+
|
|
36
|
+
dead_letter_queue = data[:dead_letter_queue]
|
|
37
|
+
virtual_partitions = data[:virtual_partitions]
|
|
38
|
+
|
|
39
|
+
next unless dead_letter_queue[:active]
|
|
40
|
+
next unless virtual_partitions[:active]
|
|
41
|
+
next if dead_letter_queue[:max_retries].positive?
|
|
42
|
+
|
|
43
|
+
[[%i[dead_letter_queue], :with_virtual_partitions]]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
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
|
+
# Enhanced Dead Letter Queue
|
|
19
|
+
#
|
|
20
|
+
# This version behaves similar to the regular version but provides ordering warranties and
|
|
21
|
+
# allows for batch skipping
|
|
22
|
+
class DeadLetterQueue < Base
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# This Karafka component is a Pro component.
|
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
|
5
|
+
#
|
|
4
6
|
# All of the commercial components are present in the lib/karafka/pro directory of this
|
|
5
7
|
# repository and their usage requires commercial license agreement.
|
|
6
8
|
#
|
|
@@ -11,17 +13,12 @@
|
|
|
11
13
|
|
|
12
14
|
module Karafka
|
|
13
15
|
module Pro
|
|
14
|
-
# Pro routing components
|
|
15
16
|
module Routing
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
super
|
|
22
|
-
|
|
23
|
-
each do |consumer_group|
|
|
24
|
-
::Karafka::Pro::Contracts::ConsumerGroup.new.validate!(consumer_group.to_h)
|
|
17
|
+
module Features
|
|
18
|
+
class Delaying < Base
|
|
19
|
+
# Delaying feature configuration
|
|
20
|
+
Config = Struct.new(:active, :delay, keyword_init: true) do
|
|
21
|
+
alias_method :active?, :active
|
|
25
22
|
end
|
|
26
23
|
end
|
|
27
24
|
end
|
|
@@ -0,0 +1,38 @@
|
|
|
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 Delaying < Base
|
|
19
|
+
# Contract to validate configuration of the expiring feature
|
|
20
|
+
class Contract < Contracts::Base
|
|
21
|
+
configure do |config|
|
|
22
|
+
config.error_messages = YAML.safe_load(
|
|
23
|
+
File.read(
|
|
24
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
|
|
25
|
+
)
|
|
26
|
+
).fetch('en').fetch('validations').fetch('topic')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
nested(:delaying) do
|
|
30
|
+
required(:active) { |val| [true, false].include?(val) }
|
|
31
|
+
required(:delay) { |val| val.nil? || (val.is_a?(Integer) && val.positive?) }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
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 Delaying < Base
|
|
19
|
+
# Topic delaying API extensions
|
|
20
|
+
module Topic
|
|
21
|
+
# @param delay [Integer, nil] minimum age of a message we want to process
|
|
22
|
+
def delaying(delay = nil)
|
|
23
|
+
# Those settings are used for validation
|
|
24
|
+
@delaying ||= begin
|
|
25
|
+
config = Config.new(active: !delay.nil?, delay: delay)
|
|
26
|
+
|
|
27
|
+
if config.active?
|
|
28
|
+
factory = ->(*) { Pro::Processing::Filters::Delayer.new(delay) }
|
|
29
|
+
filter(factory)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
config
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Just an alias for nice API
|
|
37
|
+
#
|
|
38
|
+
# @param args [Array] Anything `#delaying` accepts
|
|
39
|
+
def delay_by(*args)
|
|
40
|
+
delaying(*args)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @return [Boolean] is a given job delaying
|
|
44
|
+
def delaying?
|
|
45
|
+
delaying.active?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @return [Hash] topic with all its native configuration options plus delaying
|
|
49
|
+
def to_h
|
|
50
|
+
super.merge(
|
|
51
|
+
delaying: delaying.to_h
|
|
52
|
+
).freeze
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
# Delaying allows us to delay processing of certain topics. This is useful when we want
|
|
19
|
+
# to for any reason to wait until processing data from a topic. It does not sleep and
|
|
20
|
+
# instead uses pausing to manage delays. This allows us to free up processing resources
|
|
21
|
+
# and not block the polling thread.
|
|
22
|
+
#
|
|
23
|
+
# Delaying is a virtual feature realized via the filters
|
|
24
|
+
class Delaying < Base
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
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 Expiring < Base
|
|
19
|
+
# Expiring feature configuration
|
|
20
|
+
Config = Struct.new(:active, :ttl, keyword_init: true) do
|
|
21
|
+
alias_method :active?, :active
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
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 Expiring < Base
|
|
19
|
+
# Contract to validate configuration of the expiring feature
|
|
20
|
+
class Contract < Contracts::Base
|
|
21
|
+
configure do |config|
|
|
22
|
+
config.error_messages = YAML.safe_load(
|
|
23
|
+
File.read(
|
|
24
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
|
|
25
|
+
)
|
|
26
|
+
).fetch('en').fetch('validations').fetch('topic')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
nested(:expiring) do
|
|
30
|
+
required(:active) { |val| [true, false].include?(val) }
|
|
31
|
+
required(:ttl) { |val| val.nil? || (val.is_a?(Integer) && val.positive?) }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
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 Expiring < Base
|
|
19
|
+
# Topic expiring API extensions
|
|
20
|
+
module Topic
|
|
21
|
+
# @param ttl [Integer, nil] maximum time in ms a message is considered alive
|
|
22
|
+
def expiring(ttl = nil)
|
|
23
|
+
# Those settings are used for validation
|
|
24
|
+
@expiring ||= begin
|
|
25
|
+
config = Config.new(active: !ttl.nil?, ttl: ttl)
|
|
26
|
+
|
|
27
|
+
if config.active?
|
|
28
|
+
factory = ->(*) { Pro::Processing::Filters::Expirer.new(ttl) }
|
|
29
|
+
filter(factory)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
config
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Just an alias for nice API
|
|
37
|
+
#
|
|
38
|
+
# @param args [Array] Anything `#expiring` accepts
|
|
39
|
+
def expire_in(*args)
|
|
40
|
+
expiring(*args)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @return [Boolean] is a given job expiring
|
|
44
|
+
def expiring?
|
|
45
|
+
expiring.active?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @return [Hash] topic with all its native configuration options plus expiring
|
|
49
|
+
def to_h
|
|
50
|
+
super.merge(
|
|
51
|
+
expiring: expiring.to_h
|
|
52
|
+
).freeze
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
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
|
+
# Expiring allows us to filter out messages that are older than our expectation.
|
|
19
|
+
# This can also be done in a consumer, but applying the filtering prior to the jobs
|
|
20
|
+
# enqueuing allows us to improve operations with virtual partitions and limit the number of
|
|
21
|
+
# not necessary messages being ever seen
|
|
22
|
+
class Expiring < Base
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
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 Filtering < Base
|
|
19
|
+
# Filtering feature configuration
|
|
20
|
+
Config = Struct.new(:factories, keyword_init: true) do
|
|
21
|
+
# @return [Boolean] is this feature in use. Are any filters defined
|
|
22
|
+
def active?
|
|
23
|
+
!factories.empty?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @return [Array<Object>] array of filters applicable to a topic partition
|
|
27
|
+
def filters
|
|
28
|
+
factories.map(&:call)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [Hash] this config hash
|
|
32
|
+
def to_h
|
|
33
|
+
super.merge(active: active?)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
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 Filtering < Base
|
|
19
|
+
# Contract to validate configuration of the filtering feature
|
|
20
|
+
class Contract < Contracts::Base
|
|
21
|
+
configure do |config|
|
|
22
|
+
config.error_messages = YAML.safe_load(
|
|
23
|
+
File.read(
|
|
24
|
+
File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
|
|
25
|
+
)
|
|
26
|
+
).fetch('en').fetch('validations').fetch('topic')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
nested(:filtering) do
|
|
30
|
+
required(:active) { |val| [true, false].include?(val) }
|
|
31
|
+
|
|
32
|
+
required(:factories) do |val|
|
|
33
|
+
val.is_a?(Array) && val.all? { |factory| factory.respond_to?(:call) }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|