karafka 2.1.13 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +35 -0
  4. data/Gemfile.lock +1 -1
  5. data/config/locales/errors.yml +4 -0
  6. data/config/locales/pro_errors.yml +17 -0
  7. data/lib/karafka/admin.rb +21 -33
  8. data/lib/karafka/connection/client.rb +1 -1
  9. data/lib/karafka/contracts/config.rb +24 -0
  10. data/lib/karafka/pro/contracts/base.rb +23 -0
  11. data/lib/karafka/pro/contracts/server_cli_options.rb +111 -0
  12. data/lib/karafka/pro/loader.rb +4 -1
  13. data/lib/karafka/pro/routing/features/active_job/builder.rb +45 -0
  14. data/lib/karafka/pro/routing/features/active_job.rb +26 -0
  15. data/lib/karafka/pro/routing/features/dead_letter_queue/contracts/topic.rb +53 -0
  16. data/lib/karafka/pro/routing/features/delaying/contracts/topic.rb +41 -0
  17. data/lib/karafka/pro/routing/features/expiring/contracts/topic.rb +41 -0
  18. data/lib/karafka/pro/routing/features/filtering/contracts/topic.rb +44 -0
  19. data/lib/karafka/pro/routing/features/long_running_job/{contract.rb → contracts/topic.rb} +14 -11
  20. data/lib/karafka/pro/routing/features/{filtering/contract.rb → patterns/builder.rb} +13 -16
  21. data/lib/karafka/pro/routing/features/patterns/config.rb +54 -0
  22. data/lib/karafka/pro/routing/features/patterns/consumer_group.rb +68 -0
  23. data/lib/karafka/pro/routing/features/patterns/contracts/consumer_group.rb +62 -0
  24. data/lib/karafka/pro/routing/features/patterns/contracts/pattern.rb +46 -0
  25. data/lib/karafka/pro/routing/features/patterns/contracts/topic.rb +41 -0
  26. data/lib/karafka/pro/routing/features/patterns/detector.rb +68 -0
  27. data/lib/karafka/pro/routing/features/patterns/pattern.rb +81 -0
  28. data/lib/karafka/pro/routing/features/{delaying/contract.rb → patterns/patterns.rb} +11 -14
  29. data/lib/karafka/pro/routing/features/patterns/topic.rb +50 -0
  30. data/lib/karafka/pro/routing/features/patterns/topics.rb +53 -0
  31. data/lib/karafka/pro/routing/features/patterns.rb +33 -0
  32. data/lib/karafka/pro/routing/features/pausing/contracts/topic.rb +51 -0
  33. data/lib/karafka/pro/routing/features/throttling/contracts/topic.rb +44 -0
  34. data/lib/karafka/pro/routing/features/virtual_partitions/contracts/topic.rb +55 -0
  35. data/lib/karafka/routing/consumer_group.rb +1 -1
  36. data/lib/karafka/routing/features/active_job/contracts/topic.rb +44 -0
  37. data/lib/karafka/routing/features/active_job/proxy.rb +14 -0
  38. data/lib/karafka/routing/features/base/expander.rb +8 -2
  39. data/lib/karafka/routing/features/base.rb +4 -2
  40. data/lib/karafka/routing/features/dead_letter_queue/contracts/topic.rb +46 -0
  41. data/lib/karafka/routing/features/declaratives/contracts/topic.rb +33 -0
  42. data/lib/karafka/routing/features/manual_offset_management/contracts/topic.rb +27 -0
  43. data/lib/karafka/routing/router.rb +0 -11
  44. data/lib/karafka/routing/subscription_group.rb +9 -0
  45. data/lib/karafka/routing/topic.rb +5 -0
  46. data/lib/karafka/server.rb +9 -4
  47. data/lib/karafka/setup/config.rb +45 -0
  48. data/lib/karafka/version.rb +1 -1
  49. data.tar.gz.sig +0 -0
  50. metadata +32 -15
  51. metadata.gz.sig +0 -0
  52. data/lib/karafka/pro/routing/features/dead_letter_queue/contract.rb +0 -50
  53. data/lib/karafka/pro/routing/features/expiring/contract.rb +0 -38
  54. data/lib/karafka/pro/routing/features/pausing/contract.rb +0 -48
  55. data/lib/karafka/pro/routing/features/throttling/contract.rb +0 -41
  56. data/lib/karafka/pro/routing/features/virtual_partitions/contract.rb +0 -52
  57. data/lib/karafka/routing/features/active_job/contract.rb +0 -41
  58. data/lib/karafka/routing/features/dead_letter_queue/contract.rb +0 -42
  59. data/lib/karafka/routing/features/declaratives/contract.rb +0 -30
  60. data/lib/karafka/routing/features/manual_offset_management/contract.rb +0 -24
@@ -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 Filtering < Base
19
+ # Namespace for filtering feature contracts
20
+ module Contracts
21
+ # Contract to validate configuration of the filtering feature
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(:filtering) do
32
+ required(:active) { |val| [true, false].include?(val) }
33
+
34
+ required(:factories) do |val|
35
+ val.is_a?(Array) && val.all? { |factory| factory.respond_to?(:call) }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -16,18 +16,21 @@ module Karafka
16
16
  module Routing
17
17
  module Features
18
18
  class LongRunningJob < Base
19
- # Rules around long-running job 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
19
+ # Namespace for LRJ contracts
20
+ module Contracts
21
+ # Rules around long-running job 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
28
30
 
29
- nested(:long_running_job) do
30
- required(:active) { |val| [true, false].include?(val) }
31
+ nested(:long_running_job) do
32
+ required(:active) { |val| [true, false].include?(val) }
33
+ end
31
34
  end
32
35
  end
33
36
  end
@@ -15,22 +15,19 @@ module Karafka
15
15
  module Pro
16
16
  module Routing
17
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) }
18
+ class Patterns < Base
19
+ # Expansions for the routing builder
20
+ module Builder
21
+ # Allows us to define the simple routing pattern matching
22
+ #
23
+ # @param regexp_or_name [Symbol, String, Regexp] name of the pattern or regexp for
24
+ # automatic-based named patterns
25
+ # @param regexp [Regexp, nil] nil if we use auto-generated name based on the regexp or
26
+ # the regexp if we used named patterns
27
+ # @param block [Proc]
28
+ def pattern(regexp_or_name, regexp = nil, &block)
29
+ consumer_group('app') do
30
+ pattern(regexp_or_name, regexp, &block)
34
31
  end
35
32
  end
36
33
  end
@@ -0,0 +1,54 @@
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
+ # Holds pattern info reference
19
+ # Type is set to:
20
+ # `:regular` - in case patterns are not used and topic is just a regular existing topic
21
+ # matched directly based on the name
22
+ # `:discovered` - in case it is a real topic on which we started to listed
23
+ # `:matcher` - represents a regular expression used by librdkafka
24
+ class Patterns < Base
25
+ # Config for pattern based topic
26
+ # Only pattern related topics are active in this context
27
+ Config = Struct.new(
28
+ :active,
29
+ :type,
30
+ :pattern,
31
+ keyword_init: true
32
+ ) do
33
+ alias_method :active?, :active
34
+
35
+ # @return [Boolean] is this a matcher topic
36
+ def matcher?
37
+ type == :matcher
38
+ end
39
+
40
+ # @return [Boolean] is this a discovered topic
41
+ def discovered?
42
+ type == :discovered
43
+ end
44
+
45
+ # @return [Boolean] is this a regular topic
46
+ def regular?
47
+ type == :regular
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,68 @@
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 Patterns < Base
19
+ # Expansion of the consumer groups routing component to work with patterns
20
+ module ConsumerGroup
21
+ # @param args [Object] whatever consumer group accepts
22
+ def initialize(*args)
23
+ super
24
+ @patterns = Patterns.new([])
25
+ end
26
+
27
+ # @return [::Karafka::Pro::Routing::Features::Patterns::Patterns] created patterns
28
+ def patterns
29
+ @patterns
30
+ end
31
+
32
+ # Creates the pattern for topic matching with appropriate virtual topic
33
+ # @param regexp_or_name [Symbol, String, Regexp] name of the pattern or regexp for
34
+ # automatic-based named patterns
35
+ # @param regexp [Regexp, nil] nil if we use auto-generated name based on the regexp or
36
+ # the regexp if we used named patterns
37
+ # @param block [Proc] appropriate underlying topic settings
38
+ def pattern=(regexp_or_name, regexp = nil, &block)
39
+ # This code allows us to have a nice nameless (automatic-named) patterns that do not
40
+ # have to be explicitly named. However if someone wants to use names for exclusions
41
+ # it can be done by providing both
42
+ if regexp_or_name.is_a?(Regexp)
43
+ name = nil
44
+ regexp = regexp_or_name
45
+ else
46
+ name = regexp_or_name
47
+ end
48
+
49
+ pattern = Pattern.new(name, regexp, block)
50
+ virtual_topic = public_send(:topic=, pattern.name, &block)
51
+ # Indicate the nature of this topic (matcher)
52
+ virtual_topic.patterns(active: true, type: :matcher, pattern: pattern)
53
+ pattern.topic = virtual_topic
54
+ @patterns << pattern
55
+ end
56
+
57
+ # @return [Hash] consumer group with patterns injected
58
+ def to_h
59
+ super.merge(
60
+ patterns: patterns.map(&:to_h)
61
+ ).freeze
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,62 @@
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 Patterns < Base
19
+ module Contracts
20
+ # Contract to validate configuration of the filtering feature
21
+ class ConsumerGroup < Karafka::Contracts::Base
22
+ configure do |config|
23
+ config.error_messages = YAML.safe_load(
24
+ File.read(
25
+ File.join(Karafka.gem_root, 'config', 'locales', 'pro_errors.yml')
26
+ )
27
+ ).fetch('en').fetch('validations').fetch('consumer_group')
28
+
29
+ required(:patterns) { |val| val.is_a?(Array) && val.all? { |el| el.is_a?(Hash) } }
30
+
31
+ virtual do |data, errors|
32
+ next unless errors.empty?
33
+
34
+ validator = Pattern.new
35
+
36
+ data[:patterns].each do |pattern|
37
+ validator.validate!(pattern)
38
+ end
39
+
40
+ nil
41
+ end
42
+
43
+ # Make sure, that there are no same regular expressions with different names
44
+ # in a single consumer group
45
+ virtual do |data, errors|
46
+ next unless errors.empty?
47
+
48
+ regexp_strings = data[:patterns].map { |pattern| pattern.fetch(:regexp_string) }
49
+
50
+ next if regexp_strings.empty?
51
+ next if regexp_strings.uniq.size == regexp_strings.size
52
+
53
+ [[%i[patterns], :regexps_not_unique]]
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,46 @@
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 Patterns < Base
19
+ # Namespace for patterns related contracts
20
+ module Contracts
21
+ # Contract used to validate pattern data
22
+ class Pattern < 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('pattern')
29
+
30
+ required(:regexp) { |val| val.is_a?(Regexp) }
31
+
32
+ required(:regexp_string) do |val|
33
+ val.is_a?(String) && val.start_with?('^') && val.size >= 2
34
+ end
35
+
36
+ required(:name) do |val|
37
+ val.is_a?(String) && Karafka::Contracts::TOPIC_REGEXP.match?(val)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ 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 Patterns < Base
19
+ # Namespace for patterns feature contracts
20
+ module Contracts
21
+ # Contract to validate configuration of the patterns feature
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(:patterns) do
32
+ required(:active) { |val| [true, false].include?(val) }
33
+ required(:type) { |val| %i[matcher discovered regular].include?(val) }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,68 @@
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 Patterns < Base
19
+ # Detects if a given topic matches any of the patterns and if so, injects it into the
20
+ # given subscription group routing
21
+ #
22
+ # @note This is NOT thread-safe and should run in a thread-safe context that warranties
23
+ # that there won't be any race conditions
24
+ class Detector
25
+ # Checks if the provided topic matches any of the patterns and when detected, expands
26
+ # the routing with it.
27
+ #
28
+ # @param sg_topics [Array<Karafka::Routing::Topic>] given subscription group routing
29
+ # topics.
30
+ # @param new_topic [String] new topic that we have detected
31
+ def expand(sg_topics, new_topic)
32
+ sg_topics
33
+ .map(&:patterns)
34
+ .select(&:active?)
35
+ .select(&:matcher?)
36
+ .map(&:pattern)
37
+ .then { |pts| pts.empty? ? return : pts }
38
+ .then { |pts| Patterns.new(pts) }
39
+ .find(new_topic)
40
+ .then { |pattern| pattern || return }
41
+ .then { |pattern| install(pattern, new_topic, sg_topics) }
42
+ end
43
+
44
+ private
45
+
46
+ # Adds the discovered topic into the routing
47
+ #
48
+ # @param pattern [Karafka::Pro::Routing::Features::Patterns::Pattern] matched pattern
49
+ # @param discovered_topic [String] topic that we discovered that should be part of the
50
+ # routing from now on.
51
+ # @param sg_topics [Array<Karafka::Routing::Topic>]
52
+ def install(pattern, discovered_topic, sg_topics)
53
+ consumer_group = pattern.topic.consumer_group
54
+
55
+ # Build new topic and register within the consumer group
56
+ topic = consumer_group.public_send(:topic=, discovered_topic, &pattern.config)
57
+ topic.patterns(active: true, type: :discovered)
58
+
59
+ # Inject into subscription group topics array always, so everything is reflected
60
+ # there but since it is not active, will not be picked
61
+ sg_topics << topic
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,81 @@
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 Patterns < Base
19
+ # Karafka topic pattern object
20
+ # It represents a topic that is not yet materialized and that contains a name that is a
21
+ # regexp and not a "real" value. Underneath we define a dynamic topic, that is not
22
+ # active, that can be a subject to normal flow validations, etc.
23
+ class Pattern
24
+ # Pattern regexp
25
+ attr_accessor :regexp
26
+
27
+ # Each pattern has its own "topic" that we use as a routing reference that we define
28
+ # with non-existing topic for the routing to correctly pick it up for operations
29
+ # Virtual topic name for initial subscription
30
+ attr_reader :name
31
+
32
+ # Associated created virtual topic reference
33
+ attr_accessor :topic
34
+
35
+ # Config for real-topic configuration during injection
36
+ attr_reader :config
37
+
38
+ # @param name [String, Symbol, nil] name or the regexp for building the topic name or
39
+ # nil if we want to make it based on the regexp content
40
+ # @param regexp [Regexp] regular expression to match topics
41
+ # @param config [Proc] config for topic bootstrap
42
+ def initialize(name, regexp, config)
43
+ @regexp = regexp
44
+ # This name is also used as the underlying matcher topic name
45
+ #
46
+ # It can be used provided by the user in case user wants to use exclusions of topics
47
+ # or we can generate it if irrelevant.
48
+ #
49
+ # We generate it based on the regexp so within the same consumer group they are
50
+ # always unique (checked by topic validations)
51
+ #
52
+ # This will not prevent users from creating a different regexps matching the same
53
+ # topic but this minimizes simple mistakes
54
+ #
55
+ # This sub-part of sh1 should be unique enough and short-enough to use it here
56
+ digest = Digest::SHA1.hexdigest(regexp.source)[8..16]
57
+ @name = name ? name.to_s : "karafka-pattern-#{digest}"
58
+ @config = config
59
+ end
60
+
61
+ # @return [String] defined regexp representation as a string that is compatible with
62
+ # librdkafka expectations. We use it as a subscription name for initial patterns
63
+ # subscription start.
64
+ def regexp_string
65
+ "^#{regexp.source}"
66
+ end
67
+
68
+ # @return [Hash] hash representation of this routing pattern
69
+ def to_h
70
+ {
71
+ regexp: regexp,
72
+ name: name,
73
+ regexp_string: regexp_string
74
+ }.freeze
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -15,20 +15,17 @@ module Karafka
15
15
  module Pro
16
16
  module Routing
17
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?) }
18
+ class Patterns < Base
19
+ # Representation of groups of topics
20
+ class Patterns < ::Karafka::Routing::Topics
21
+ # Finds first pattern matching given topic name
22
+ #
23
+ # @param topic_name [String] topic name that may match a pattern
24
+ # @return [Karafka::Routing::Pattern, nil] pattern or nil if not found
25
+ # @note Please keep in mind, that there may be many patterns matching given topic name
26
+ # and we always pick the first one (defined first)
27
+ def find(topic_name)
28
+ @accumulator.find { |pattern| pattern.regexp =~ topic_name }
32
29
  end
33
30
  end
34
31
  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 Patterns < Base
19
+ # Patterns feature topic extensions
20
+ module Topic
21
+ # @return [String] subscription name or the regexp string representing matching of
22
+ # new topics that should be detected.
23
+ def subscription_name
24
+ patterns.active? && patterns.matcher? ? patterns.pattern.regexp_string : super
25
+ end
26
+
27
+ # @param active [Boolean] is this topic active member of patterns
28
+ # @param type [Symbol] type of topic taking part in pattern matching
29
+ # @param pattern [Regexp] regular expression for matching
30
+ def patterns(active: false, type: :regular, pattern: nil)
31
+ @patterns ||= Config.new(active: active, type: type, pattern: pattern)
32
+ end
33
+
34
+ # @return [Boolean] is this topic a member of patterns
35
+ def patterns?
36
+ patterns.active?
37
+ end
38
+
39
+ # @return [Hash] topic with all its native configuration options plus patterns
40
+ def to_h
41
+ super.merge(
42
+ patterns: patterns.to_h
43
+ ).freeze
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end