waterdrop 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ca8a589d1b25ca64ff4fe5e0b9b501a73aa70fe14901b6d9a5da7e6792cad89
4
- data.tar.gz: bd75fb0f84eab0ebdc69412e72bd7132a327c545585e7ff5c04d0e3771be82dd
3
+ metadata.gz: 8f02b2aed0684d1d928c058a5c9797c1c50e3a626ac104db0428c486520ecf16
4
+ data.tar.gz: ec73f22737b8ac596f355253cc7deb63d68bbe191b6fc0b39058f3948439545f
5
5
  SHA512:
6
- metadata.gz: c0e6501922e0e3fac96db78e8666b800fb1a8244e136c88b21f8af808803b5aaad81fb24726bb3d84eacba19a933dbde31660c94b3b0d992123cac66d032f824
7
- data.tar.gz: f85d2617e9139e84b70b23221f92efa9f04c188da04b0077c945b0da978733aa9f9dbfc87b089c907faadb30b0931cd93bfd099914f9b258a4ab788f0cafcd8e
6
+ metadata.gz: 2c8e80c205676bc6a9a360e5177576bd31499dfa498be07a54017d9262b84fd806333e1e552d243fb60b4ac6323828749096b0c1f3de0dbb7dc90f353b3a7714
7
+ data.tar.gz: 758cb0b8a93655d4ca324549f07ea64cb823df1233892d0d199354889419712cb685521e8a4020dd482432719d0ac98d3349991236711bba85ff68bc414795c5
Binary file
Binary file
@@ -0,0 +1,3 @@
1
+ repository_id: '76b3a28c-d72b-44c7-870b-e5217e2f0d5c'
2
+ api_key: <%= ENV['CODITSU_API_KEY'] %>
3
+ api_secret: <%= ENV['CODITSU_API_SECRET'] %>
@@ -0,0 +1 @@
1
+ open_collective: karafka
data/.gitignore CHANGED
@@ -7,10 +7,11 @@ app.god
7
7
 
8
8
  # minimal Rails specific artifacts
9
9
  db/*.sqlite3
10
- /log/*
10
+ /log/*.log
11
11
  /tmp/*
12
12
  *.gem
13
13
  *.~
14
+ /.coditsu/local.yml
14
15
 
15
16
  # various artifacts
16
17
  **.war
@@ -1 +1 @@
1
- 2.5.0
1
+ 2.6.3
@@ -1,18 +1,35 @@
1
- language: ruby
2
- sudo: false
3
- rvm:
4
- - 2.3.0
5
- - 2.3.1
6
- - 2.3.2
7
- - 2.3.3
8
- - 2.3.4
9
- - 2.4.0
10
- - 2.4.1
11
- - 2.4.2
12
- - 2.5.0
13
- - jruby-head
14
- script: bundle exec rspec spec/
15
- env:
16
- global:
17
- - JRUBY_OPTS='--debug'
18
- install: bundle install --jobs=3 --retry=3
1
+ services:
2
+ - docker
3
+
4
+ dist: trusty
5
+ cache: bundler
6
+
7
+ git:
8
+ depth: false
9
+
10
+ test: &test
11
+ stage: Test
12
+ language: ruby
13
+ before_install:
14
+ - gem install bundler
15
+ - gem update --system
16
+ script: bundle exec rspec
17
+
18
+ jobs:
19
+ include:
20
+ - <<: *test
21
+ rvm: 2.6.3
22
+ - <<: *test
23
+ rvm: 2.5.5
24
+
25
+ - stage: coditsu
26
+ language: ruby
27
+ rvm: 2.6.3
28
+ before_install:
29
+ - gem update --system
30
+ - gem install bundler
31
+ script: \curl -sSL https://api.coditsu.io/run/ci | bash
32
+
33
+ stages:
34
+ - coditsu
35
+ - test
@@ -1,5 +1,41 @@
1
1
  # WaterDrop changelog
2
2
 
3
+ ## 1.3.0 (2019-09-09)
4
+ - Drop Ruby 2.4 support
5
+
6
+ ## 1.3.0.rc1 (2019-07-31)
7
+ - Drop Ruby 2.3 support
8
+ - Drop support for Kafka 0.10 in favor of native support for Kafka 0.11.
9
+ - Ruby 2.6.3 support
10
+ - Support message headers
11
+ - `sasl_over_ssl` support
12
+ - Unlock Ruby Kafka + provide support for 0.7 only
13
+ - #60 - Rename listener to StdoutListener
14
+ - Drop support for Kafka 0.10 in favor of native support for Kafka 0.11.
15
+ - Support ruby-kafka 0.7
16
+ - Support message headers
17
+ - `sasl_over_ssl` support
18
+ - `ssl_client_cert_key_password` support
19
+ - #87 - Make stdout listener as instance
20
+ - Use Zeitwerk for gem code loading
21
+ - #93 - zstd compression support
22
+ - #99 - schemas are renamed to contracts
23
+ - Bump delivery_boy (0.2.7 => 0.2.8)
24
+
25
+ ## 1.2.5
26
+ - Bump deps to match Karafka
27
+ - drop jruby support
28
+ - drop ruby 2.2 support
29
+
30
+ ## 1.2.4
31
+ - Due to multiple requests, unlock of 0.7 with an additional post-install message
32
+
33
+ ## 1.2.3
34
+ - Lock ruby-kafka to 0.6 (0.7 support targeted for WaterDrop 1.3)
35
+
36
+ ## 1.2.2
37
+ - #55 - Codec settings unification and config applier
38
+
3
39
  ## 1.2.1
4
40
  - #54 - compression_codec api sync with king-konf requirements
5
41
 
data/Gemfile CHANGED
@@ -4,7 +4,9 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
6
 
7
- group :development, :test do
7
+ gem 'dry-validation'
8
+
9
+ group :test do
8
10
  gem 'rspec'
9
11
  gem 'simplecov'
10
12
  end
@@ -1,90 +1,102 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- waterdrop (1.2.1)
4
+ waterdrop (1.3.0)
5
5
  delivery_boy (~> 0.2)
6
- dry-configurable (~> 0.7)
7
- dry-monitor (~> 0.1)
8
- dry-validation (~> 0.11)
9
- null-logger (~> 0.1)
6
+ dry-configurable (~> 0.8)
7
+ dry-monitor (~> 0.3)
8
+ dry-validation (~> 1.2)
9
+ ruby-kafka (>= 0.7.8)
10
+ zeitwerk (~> 2.1)
10
11
 
11
12
  GEM
12
13
  remote: https://rubygems.org/
13
14
  specs:
14
- concurrent-ruby (1.0.5)
15
- delivery_boy (0.2.4)
16
- king_konf (~> 0.1.8)
17
- ruby-kafka (~> 0.5.1)
15
+ concurrent-ruby (1.1.5)
16
+ delivery_boy (0.2.8)
17
+ king_konf (~> 0.3)
18
+ ruby-kafka (~> 0.7.8)
18
19
  diff-lcs (1.3)
19
- docile (1.3.0)
20
- dry-configurable (0.7.0)
20
+ digest-crc (0.4.1)
21
+ docile (1.3.2)
22
+ dry-configurable (0.8.3)
21
23
  concurrent-ruby (~> 1.0)
22
- dry-container (0.6.0)
24
+ dry-core (~> 0.4, >= 0.4.7)
25
+ dry-container (0.7.2)
23
26
  concurrent-ruby (~> 1.0)
24
27
  dry-configurable (~> 0.1, >= 0.1.3)
25
- dry-core (0.4.5)
28
+ dry-core (0.4.9)
26
29
  concurrent-ruby (~> 1.0)
27
- dry-equalizer (0.2.0)
28
- dry-events (0.1.0)
30
+ dry-equalizer (0.2.2)
31
+ dry-events (0.2.0)
29
32
  concurrent-ruby (~> 1.0)
30
33
  dry-core (~> 0.4)
31
34
  dry-equalizer (~> 0.2)
32
- dry-logic (0.4.2)
33
- dry-container (~> 0.2, >= 0.2.6)
35
+ dry-inflector (0.1.2)
36
+ dry-initializer (3.0.1)
37
+ dry-logic (1.0.3)
38
+ concurrent-ruby (~> 1.0)
34
39
  dry-core (~> 0.2)
35
40
  dry-equalizer (~> 0.2)
36
- dry-monitor (0.1.2)
41
+ dry-monitor (0.3.1)
37
42
  dry-configurable (~> 0.5)
43
+ dry-core (~> 0.4)
38
44
  dry-equalizer (~> 0.2)
39
45
  dry-events (~> 0.1)
40
- rouge (~> 2.0, >= 2.2.1)
41
- dry-types (0.12.2)
46
+ dry-schema (1.3.3)
42
47
  concurrent-ruby (~> 1.0)
43
- dry-configurable (~> 0.1)
44
- dry-container (~> 0.3)
45
- dry-core (~> 0.2, >= 0.2.1)
48
+ dry-configurable (~> 0.8, >= 0.8.3)
49
+ dry-core (~> 0.4)
46
50
  dry-equalizer (~> 0.2)
47
- dry-logic (~> 0.4, >= 0.4.2)
48
- inflecto (~> 0.0.0, >= 0.0.2)
49
- dry-validation (0.11.1)
51
+ dry-initializer (~> 3.0)
52
+ dry-logic (~> 1.0)
53
+ dry-types (~> 1.0)
54
+ dry-types (1.1.1)
50
55
  concurrent-ruby (~> 1.0)
51
- dry-configurable (~> 0.1, >= 0.1.3)
52
- dry-core (~> 0.2, >= 0.2.1)
56
+ dry-container (~> 0.3)
57
+ dry-core (~> 0.4, >= 0.4.4)
58
+ dry-equalizer (~> 0.2, >= 0.2.2)
59
+ dry-inflector (~> 0.1, >= 0.1.2)
60
+ dry-logic (~> 1.0, >= 1.0.2)
61
+ dry-validation (1.3.1)
62
+ concurrent-ruby (~> 1.0)
63
+ dry-container (~> 0.7, >= 0.7.1)
64
+ dry-core (~> 0.4)
53
65
  dry-equalizer (~> 0.2)
54
- dry-logic (~> 0.4, >= 0.4.0)
55
- dry-types (~> 0.12.0)
56
- inflecto (0.0.2)
57
- json (2.1.0)
58
- king_konf (0.1.10)
59
- null-logger (0.1.5)
60
- rouge (2.2.1)
61
- rspec (3.7.0)
62
- rspec-core (~> 3.7.0)
63
- rspec-expectations (~> 3.7.0)
64
- rspec-mocks (~> 3.7.0)
65
- rspec-core (3.7.1)
66
- rspec-support (~> 3.7.0)
67
- rspec-expectations (3.7.0)
66
+ dry-initializer (~> 3.0)
67
+ dry-schema (~> 1.0, >= 1.3.1)
68
+ json (2.2.0)
69
+ king_konf (0.3.7)
70
+ rspec (3.8.0)
71
+ rspec-core (~> 3.8.0)
72
+ rspec-expectations (~> 3.8.0)
73
+ rspec-mocks (~> 3.8.0)
74
+ rspec-core (3.8.2)
75
+ rspec-support (~> 3.8.0)
76
+ rspec-expectations (3.8.4)
68
77
  diff-lcs (>= 1.2.0, < 2.0)
69
- rspec-support (~> 3.7.0)
70
- rspec-mocks (3.7.0)
78
+ rspec-support (~> 3.8.0)
79
+ rspec-mocks (3.8.1)
71
80
  diff-lcs (>= 1.2.0, < 2.0)
72
- rspec-support (~> 3.7.0)
73
- rspec-support (3.7.1)
74
- ruby-kafka (0.5.4)
75
- simplecov (0.16.1)
81
+ rspec-support (~> 3.8.0)
82
+ rspec-support (3.8.2)
83
+ ruby-kafka (0.7.10)
84
+ digest-crc
85
+ simplecov (0.17.0)
76
86
  docile (~> 1.1)
77
87
  json (>= 1.8, < 3)
78
88
  simplecov-html (~> 0.10.0)
79
89
  simplecov-html (0.10.2)
90
+ zeitwerk (2.1.10)
80
91
 
81
92
  PLATFORMS
82
93
  ruby
83
94
 
84
95
  DEPENDENCIES
96
+ dry-validation
85
97
  rspec
86
98
  simplecov
87
99
  waterdrop!
88
100
 
89
101
  BUNDLED WITH
90
- 1.16.1
102
+ 2.0.2
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # WaterDrop
2
2
 
3
- [![Build Status](https://travis-ci.org/karafka/waterdrop.png)](https://travis-ci.org/karafka/waterdrop)
3
+ [![Build Status](https://travis-ci.org/karafka/waterdrop.svg)](https://travis-ci.org/karafka/waterdrop)
4
4
  [![Join the chat at https://gitter.im/karafka/karafka](https://badges.gitter.im/karafka/karafka.svg)](https://gitter.im/karafka/karafka?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5
5
 
6
6
  Gem used to send messages to Kafka in an easy way with an extra validation layer. It is a part of the [Karafka](https://github.com/karafka/karafka) ecosystem.
@@ -11,7 +11,7 @@ It is:
11
11
 
12
12
  - Thread safe
13
13
  - Supports sync and async producers
14
- - Working with 0.10.1+ Kafka
14
+ - Working with 0.11+ Kafka
15
15
 
16
16
  ## Installation
17
17
 
@@ -104,6 +104,7 @@ Both ```SyncProducer``` and ```AsyncProducer``` accept following options:
104
104
  | ```partition``` | false | Integer | A specific partition number that should be written to |
105
105
  | ```partition_key``` | false | String | A string that can be used to deterministically select the partition |
106
106
  | ```create_time``` | false | Time | The timestamp that should be set on the message |
107
+ | ```headers``` | false | Hash | Headers for the message |
107
108
 
108
109
  Keep in mind, that message you want to send should be either binary or stringified (to_s, to_json, etc).
109
110
 
@@ -0,0 +1,25 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEODCCAqCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhtYWNp
3
+ ZWovREM9bWVuc2ZlbGQvREM9cGwwHhcNMTkwNzMwMTQ1NDU0WhcNMjAwNzI5MTQ1
4
+ NDU0WjAjMSEwHwYDVQQDDBhtYWNpZWovREM9bWVuc2ZlbGQvREM9cGwwggGiMA0G
5
+ CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC9fCwtaHZG2SyyNXiH8r0QbJQx/xxl
6
+ dkvwWz9QGJO+O8rEx20FB1Ab+MVkfOscwIv5jWpmk1U9whzDPl1uFtIbgu+sk+Zb
7
+ uQlZyK/DPN6c+/BbBL+RryTBRyvkPLoCVwm7uxc/JZ1n4AI6eF4cCZ2ieZ9QgQbU
8
+ MQs2QPqs9hT50Ez/40GnOdadVfiDDGz+NME2C4ms0BriXwZ1tcRTfJIHe2xjIbbb
9
+ y5qRGfsLKcgMzvLQR24olixyX1MR0s4+Wveq3QL/gBhL4veUcv+UABJA8IJR0kyB
10
+ seHHutusiwZ1v3SjjjW1xLLrc2ARV0mgCb0WaK2T4iA3oFTGLh6Ydz8LNl31KQFv
11
+ 94nRd8IhmJxrhQ6dQ/WT9IXoa5S9lfT5lPJeINemH4/6QPABzf9W2IZlCdI9wCdB
12
+ TBaw57MKneGAYZiKjw6OALSy2ltQUCl3RqFl3VP7n8uFy1U987Q5VIIQ3O1UUsQD
13
+ Oe/h+r7GUU4RSPKgPlrwvW9bD/UQ+zF51v8CAwEAAaN3MHUwCQYDVR0TBAIwADAL
14
+ BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFJNIBHdfEUD7TqHqIer2YhWaWhwcMB0GA1Ud
15
+ EQQWMBSBEm1hY2llakBtZW5zZmVsZC5wbDAdBgNVHRIEFjAUgRJtYWNpZWpAbWVu
16
+ c2ZlbGQucGwwDQYJKoZIhvcNAQELBQADggGBAKA4eqko6BTNhlysip6rfBkVTGri
17
+ ZXsL+kRb2hLvsQJS/kLyM21oMlu+LN0aPj3qEFR8mE/YeDD8rLAfruBRTltPNbR7
18
+ xA5eE1gkxY5LfExUtK3b2wPqfmo7mZgfcsMwfYg/tUXw1WpBCnrhAJodpGH6SXmp
19
+ A40qFUZst0vjiOoO+aTblIHPmMJXoZ3K42dTlNKlEiDKUWMRKSgpjjYGEYalFNWI
20
+ hHfCz2r8L2t+dYdMZg1JGbEkq4ADGsAA8ioZIpJd7V4hI17u5TCdi7X5wh/0gN0E
21
+ CgP+nLox3D+l2q0QuQEkayr+auFYkzTCkF+BmEk1D0Ru4mcf3F4CJvEmW4Pzbjqt
22
+ i1tsCWPtJ4E/UUKnKaWKqGbjrjHJ0MuShYzHkodox5IOiCXIQg+1+YSzfXUV6WEK
23
+ KJG/fhg1JV5vVDdVy6x+tv5SQ5ctU0feCsVfESi3rE3zRd+nvzE9HcZ5aXeL1UtJ
24
+ nT5Xrioegu2w1jPyVEgyZgTZC5rvD0nNS5sFNQ==
25
+ -----END CERTIFICATE-----
@@ -1,6 +1,19 @@
1
1
  en:
2
- errors:
3
- broker_schema?: >
4
- has an invalid format.
5
- Expected schema, host and port number.
6
- Example: kafka://127.0.0.1:9092 or kafka+ssl://127.0.0.1:9092
2
+ dry_validation:
3
+ errors:
4
+ broker_schema: >
5
+ has an invalid format.
6
+ Expected schema, host and port number.
7
+ Example: kafka://127.0.0.1:9092 or kafka+ssl://127.0.0.1:9092
8
+ ssl_client_cert_with_ssl_client_cert_key: >
9
+ Both ssl_client_cert and ssl_client_cert_key need to be provided.
10
+ ssl_client_cert_key_with_ssl_client_cert: >
11
+ Both ssl_client_cert_key and ssl_client_cert need to be provided.
12
+ ssl_client_cert_chain_with_ssl_client_cert: >
13
+ Both ssl_client_cert_chain and ssl_client_cert need to be provided.
14
+ ssl_client_cert_chain_with_ssl_client_cert_key: >
15
+ Both ssl_client_cert_chain and ssl_client_cert_key need to be provided.
16
+ ssl_client_cert_key_password_with_ssl_client_cert_key: >
17
+ Both ssl_client_cert_key_password and ssl_client_cert_key need to be provided.
18
+ sasl_oauth_token_provider_respond_to_token: >
19
+ sasl_oauth_token_provider needs to respond to a #token method.
@@ -4,16 +4,13 @@
4
4
  %w[
5
5
  json
6
6
  delivery_boy
7
- null_logger
8
7
  singleton
9
8
  dry-configurable
10
9
  dry/monitor/notifications
11
10
  dry-validation
11
+ zeitwerk
12
12
  ].each { |lib| require lib }
13
13
 
14
- # Internal components
15
- base_path = File.dirname(__FILE__) + '/water_drop'
16
-
17
14
  # WaterDrop library
18
15
  module WaterDrop
19
16
  class << self
@@ -23,22 +20,8 @@ module WaterDrop
23
20
  # @param [Block] block configuration block
24
21
  def setup(&block)
25
22
  Config.setup(&block)
26
-
27
23
  DeliveryBoy.logger = self.logger = config.logger
28
-
29
- # Recursive lambda for mapping config down to delivery boy
30
- applier = lambda { |db_config, h|
31
- h.each do |k, v|
32
- applier.call(db_config, v) && next if v.is_a?(Hash)
33
- next unless db_config.respond_to?(:"#{k}=")
34
- db_config.public_send(:"#{k}=", v)
35
- end
36
- }
37
-
38
- DeliveryBoy.config.tap do |config|
39
- config.brokers = Config.config.kafka.seed_brokers
40
- applier.call(config, Config.config.to_h)
41
- end
24
+ ConfigApplier.call(DeliveryBoy.config, Config.config.to_h)
42
25
  end
43
26
 
44
27
  # @return [WaterDrop::Config] config instance
@@ -58,15 +41,8 @@ module WaterDrop
58
41
  end
59
42
  end
60
43
 
61
- %w[
62
- version
63
- instrumentation/monitor
64
- instrumentation/listener
65
- schemas/message_options
66
- schemas/config
67
- config
68
- errors
69
- base_producer
70
- sync_producer
71
- async_producer
72
- ].each { |lib| require "#{base_path}/#{lib}" }
44
+ Zeitwerk::Loader
45
+ .for_gem
46
+ .tap { |loader| loader.ignore("#{__dir__}/waterdrop.rb") }
47
+ .tap(&:setup)
48
+ .tap(&:eager_load)
@@ -19,8 +19,8 @@ module WaterDrop
19
19
  d_method = WaterDrop.config.raise_on_buffer_overflow ? :deliver_async! : :deliver_async
20
20
 
21
21
  DeliveryBoy.send(d_method, message, options)
22
- rescue Kafka::Error => error
23
- graceful_attempt?(attempts_count, message, options, error) ? retry : raise(error)
22
+ rescue Kafka::Error => e
23
+ graceful_attempt?(attempts_count, message, options, e) ? retry : raise(e)
24
24
  end
25
25
  end
26
26
  end
@@ -4,6 +4,12 @@ module WaterDrop
4
4
  # Base messages producer that contains all the logic that is exactly the same for both
5
5
  # sync and async producers
6
6
  class BaseProducer
7
+ # Contract for checking the correctness of the provided data that someone wants to
8
+ # dispatch to Kafka
9
+ SCHEMA = Contracts::MessageOptions.new.freeze
10
+
11
+ private_constant :SCHEMA
12
+
7
13
  class << self
8
14
  private
9
15
 
@@ -12,18 +18,19 @@ module WaterDrop
12
18
  # @raise [WaterDrop::Errors::InvalidMessageOptions] raised when message options are
13
19
  # somehow invalid and we cannot perform delivery because of that
14
20
  def validate!(options)
15
- validation_result = Schemas::MessageOptions.call(options)
21
+ validation_result = SCHEMA.call(options)
16
22
  return true if validation_result.success?
23
+
17
24
  raise Errors::InvalidMessageOptions, validation_result.errors
18
25
  end
19
26
 
20
27
  # Upon failed delivery, we may try to resend a message depending on the attempt number
21
- # or reraise an error if we're unable to do that after given number of retries
28
+ # or re-raise an error if we're unable to do that after given number of retries
22
29
  # This method checks that and also instruments errors and retries for the delivery
23
30
  # @param attempts_count [Integer] number of attempt (starting from 1) for the delivery
24
31
  # @param message [String] message that we want to send to Kafka
25
32
  # @param options [Hash] options (including topic) for producer
26
- # @param error [Kafka::Error] error that occured
33
+ # @param error [Kafka::Error] error that occurred
27
34
  # @return [Boolean] true if this is a graceful attempt and we can retry or false it this
28
35
  # was the final one and we should deal with the fact, that we cannot deliver a given
29
36
  # message
@@ -3,18 +3,24 @@
3
3
  # Configuration and descriptions are based on the delivery boy zendesk gem
4
4
  # @see https://github.com/zendesk/delivery_boy
5
5
  module WaterDrop
6
- # Configurator for setting up all options required by WaterDrop
6
+ # Configuration object for setting up all options required by WaterDrop
7
7
  class Config
8
8
  extend Dry::Configurable
9
9
 
10
+ # Config schema definition
11
+ # @note We use a single instance not to create new one upon each usage
12
+ SCHEMA = Contracts::Config.new.freeze
13
+
14
+ private_constant :SCHEMA
15
+
10
16
  # WaterDrop options
11
17
  # option client_id [String] identifier of this producer
12
18
  setting :client_id, 'waterdrop'
13
19
  # option [Instance, nil] logger that we want to use or nil to fallback to ruby-kafka logger
14
- setting :logger, NullLogger.new
20
+ setting :logger, Logger.new($stdout, level: Logger::WARN)
15
21
  # option [Instance] monitor that we want to use. See instrumentation part of the README for
16
22
  # more details
17
- setting :monitor, WaterDrop::Instrumentation::Monitor.instance
23
+ setting :monitor, WaterDrop::Instrumentation::Monitor.new
18
24
  # option [Boolean] should we send messages. Setting this to false can be really useful when
19
25
  # testing and or developing because when set to false, won't actually ping Kafka
20
26
  setting :deliver, true
@@ -108,21 +114,20 @@ module WaterDrop
108
114
  setting :sasl_scram_password, nil
109
115
  # option sasl_scram_mechanism [String, nil] Scram mechanism, either 'sha256' or 'sha512'
110
116
  setting :sasl_scram_mechanism, nil
111
- end
112
-
113
- # option producer [Hash] - optional - producer configuration options
114
- setting :producer do
115
- # option compression_codec [Symbol] Sets producer compression codec
116
- # More: https://github.com/zendesk/ruby-kafka#compression
117
- # More: https://github.com/zendesk/ruby-kafka/blob/master/lib/kafka/compression.rb
118
- setting :compression_codec, nil
119
- # option compression_codec [Integer] Sets producer compression threshold
120
- # More: https://github.com/zendesk/ruby-kafka#compression
121
- setting :compression_threshold, 1
117
+ # option sasl_over_ssl [Boolean] whether to enforce SSL with SASL
118
+ setting :sasl_over_ssl, true
119
+ # option ssl_client_cert_chain [String, nil] client cert chain or nil if not used
120
+ setting :ssl_client_cert_chain, nil
121
+ # option ssl_client_cert_key_password [String, nil] the password required to read
122
+ # the ssl_client_cert_key
123
+ setting :ssl_client_cert_key_password, nil
124
+ # @param sasl_oauth_token_provider [Object, nil] OAuthBearer Token Provider instance that
125
+ # implements method token.
126
+ setting :sasl_oauth_token_provider, nil
122
127
  end
123
128
 
124
129
  class << self
125
- # Configurating method
130
+ # Configuration method
126
131
  # @yield Runs a block of code providing a config singleton instance to it
127
132
  # @yieldparam [WaterDrop::Config] WaterDrop config instance
128
133
  def setup
@@ -139,9 +144,10 @@ module WaterDrop
139
144
  # @raise [WaterDrop::Errors::InvalidConfiguration] raised when something is wrong with
140
145
  # the configuration
141
146
  def validate!(config_hash)
142
- validation_result = Schemas::Config.call(config_hash)
147
+ validation_result = SCHEMA.call(config_hash)
143
148
  return true if validation_result.success?
144
- raise Errors::InvalidConfiguration, validation_result.errors
149
+
150
+ raise Errors::InvalidConfiguration, validation_result.errors.to_h
145
151
  end
146
152
  end
147
153
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaterDrop
4
+ # Engine used to propagate config application to DeliveryBoy with corner case handling
5
+ module ConfigApplier
6
+ class << self
7
+ # @param delivery_boy_config [DeliveryBoy::Config] delivery boy config instance
8
+ # @param settings [Hash] hash with WaterDrop settings
9
+ def call(delivery_boy_config, settings)
10
+ # Recursive lambda for mapping config down to delivery boy
11
+ settings.each do |key, value|
12
+ call(delivery_boy_config, value) && next if value.is_a?(Hash)
13
+
14
+ # If this is a special case that needs manual setup instead of a direct reassignment
15
+ if respond_to?(key, true)
16
+ send(key, delivery_boy_config, value)
17
+ else
18
+ # If this setting is our internal one, we should not sync it with the delivery boy
19
+ next unless delivery_boy_config.respond_to?(:"#{key}=")
20
+
21
+ delivery_boy_config.public_send(:"#{key}=", value)
22
+ end
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ # Extra setup for the compression codec as it behaves differently than other settings
29
+ # that are ported 1:1 from ruby-kafka
30
+ # For some crazy reason, delivery boy requires compression codec as a string, when
31
+ # ruby-kafka as a symbol. We follow ruby-kafka internal design, so we had to mimic
32
+ # that by assigning a string version that down the road will be symbolized again
33
+ # by delivery boy
34
+ # @param delivery_boy_config [DeliveryBoy::Config] delivery boy config instance
35
+ # @param codec_name [Symbol] codec name as a symbol
36
+ def compression_codec(delivery_boy_config, codec_name)
37
+ # If there is no compression codec, we don't apply anything
38
+ return unless codec_name
39
+
40
+ delivery_boy_config.compression_codec = codec_name.to_s
41
+ end
42
+
43
+ # We use the "seed_brokers" name and DeliveryBoy uses "brokers" so we pass the values
44
+ # manually
45
+ # @param delivery_boy_config [DeliveryBoy::Config] delivery boy config instance
46
+ # @param seed_brokers [Array<String>] kafka seed brokers
47
+ def seed_brokers(delivery_boy_config, seed_brokers)
48
+ delivery_boy_config.brokers = seed_brokers
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaterDrop
4
+ # Namespace for all the contracts for config validations
5
+ module Contracts
6
+ # Regex to check that topic has a valid format
7
+ TOPIC_REGEXP = /\A(\w|\-|\.)+\z/.freeze
8
+ end
9
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaterDrop
4
+ module Contracts
5
+ # Contract with validation rules for WaterDrop configuration details
6
+ class Config < Dry::Validation::Contract
7
+ # Valid uri schemas of Kafka broker url
8
+ URI_SCHEMES = %w[kafka kafka+ssl plaintext ssl].freeze
9
+
10
+ # Available sasl scram mechanism of authentication (plus nil)
11
+ SASL_SCRAM_MECHANISMS = %w[sha256 sha512].freeze
12
+
13
+ # Supported compression codecs
14
+ COMPRESSION_CODECS = %i[snappy gzip lz4 zstd].freeze
15
+
16
+ config.messages.load_paths << File.join(WaterDrop.gem_root, 'config', 'errors.yml')
17
+
18
+ class << self
19
+ private
20
+
21
+ # Builder for kafka scoped data custom rules
22
+ # @param keys [Symbol, Hash] the keys names
23
+ # @param block [Proc] block we want to run with validations within the kafka scope
24
+ def kafka_scope_rule(*keys, &block)
25
+ rule(*[:kafka].product(keys)) do
26
+ instance_exec(values[:kafka], &block)
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ # Uri validator to check if uri is in a Kafka acceptable format
34
+ # @param uri [String] uri we want to validate
35
+ # @return [Boolean] true if it is a valid uri, otherwise false
36
+ def broker_schema?(uri)
37
+ uri = URI.parse(uri)
38
+ URI_SCHEMES.include?(uri.scheme) && uri.port
39
+ rescue URI::InvalidURIError
40
+ false
41
+ end
42
+
43
+ params do
44
+ required(:client_id).filled(:str?, format?: Contracts::TOPIC_REGEXP)
45
+ required(:logger).filled
46
+ required(:deliver).filled(:bool?)
47
+ required(:raise_on_buffer_overflow).filled(:bool?)
48
+
49
+ required(:kafka).schema do
50
+ required(:seed_brokers).value(:array, :filled?).each(:str?)
51
+ required(:connect_timeout).filled(:int?, gt?: 0)
52
+ required(:socket_timeout).filled(:int?, gt?: 0)
53
+ required(:compression_threshold).filled(:int?, gteq?: 1)
54
+ optional(:compression_codec).maybe(included_in?: COMPRESSION_CODECS)
55
+
56
+ required(:max_buffer_bytesize).filled(:int?, gt?: 0)
57
+ required(:max_buffer_size).filled(:int?, gt?: 0)
58
+ required(:max_queue_size).filled(:int?, gt?: 0)
59
+
60
+ required(:ack_timeout).filled(:int?, gt?: 0)
61
+ required(:delivery_interval).filled(:int?, gteq?: 0)
62
+ required(:delivery_threshold).filled(:int?, gteq?: 0)
63
+
64
+ required(:max_retries).filled(:int?, gteq?: 0)
65
+ required(:retry_backoff).filled(:int?, gteq?: 0)
66
+ required(:required_acks).filled(included_in?: [1, 0, -1, :all])
67
+
68
+ %i[
69
+ ssl_ca_cert
70
+ ssl_ca_cert_file_path
71
+ ssl_client_cert
72
+ ssl_client_cert_key
73
+ ssl_client_cert_chain
74
+ ssl_client_cert_key_password
75
+ sasl_gssapi_principal
76
+ sasl_gssapi_keytab
77
+ sasl_plain_authzid
78
+ sasl_plain_username
79
+ sasl_plain_password
80
+ sasl_scram_username
81
+ sasl_scram_password
82
+ ].each do |encryption_attribute|
83
+ optional(encryption_attribute).maybe(:str?)
84
+ end
85
+
86
+ optional(:ssl_ca_certs_from_system).maybe(:bool?)
87
+ optional(:sasl_over_ssl).maybe(:bool?)
88
+ optional(:sasl_oauth_token_provider).value(:any)
89
+
90
+ # It's not with other encryptions as it has some more rules
91
+ optional(:sasl_scram_mechanism)
92
+ .maybe(:str?, included_in?: SASL_SCRAM_MECHANISMS)
93
+ end
94
+ end
95
+
96
+ kafka_scope_rule(:seed_brokers) do |kafka|
97
+ unless kafka[:seed_brokers].all?(&method(:broker_schema?))
98
+ key(%i[kafka seed_brokers]).failure(:broker_schema)
99
+ end
100
+ end
101
+
102
+ kafka_scope_rule(:ssl_client_cert, :ssl_client_cert_key) do |kafka|
103
+ if kafka[:ssl_client_cert] &&
104
+ kafka[:ssl_client_cert_key].nil?
105
+ key(%i[kafka ssl_client_cert_key]).failure(:ssl_client_cert_with_ssl_client_cert_key)
106
+ end
107
+ end
108
+
109
+ kafka_scope_rule(:ssl_client_cert_key, :ssl_client_cert) do |kafka|
110
+ if kafka[:ssl_client_cert_key] &&
111
+ kafka[:ssl_client_cert].nil?
112
+ key.failure(:ssl_client_cert_key_with_ssl_client_cert)
113
+ end
114
+ end
115
+
116
+ kafka_scope_rule(:ssl_client_cert_chain, :ssl_client_cert) do |kafka|
117
+ if kafka[:ssl_client_cert_chain] &&
118
+ kafka[:ssl_client_cert].nil?
119
+ key.failure(:ssl_client_cert_chain_with_ssl_client_cert)
120
+ end
121
+ end
122
+
123
+ kafka_scope_rule(:ssl_client_cert_key_password, :ssl_client_cert_key) do |kafka|
124
+ if kafka[:ssl_client_cert_key_password] &&
125
+ kafka[:ssl_client_cert_key].nil?
126
+ key.failure(:ssl_client_cert_key_password_with_ssl_client_cert_key)
127
+ end
128
+ end
129
+
130
+ kafka_scope_rule(:sasl_oauth_token_provider) do |kafka|
131
+ if kafka[:sasl_oauth_token_provider] &&
132
+ !kafka[:sasl_oauth_token_provider].respond_to?(:token)
133
+ key.failure(:sasl_oauth_token_provider_respond_to_token)
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaterDrop
4
+ module Contracts
5
+ # Contract with validation rules for validating that all the message options that
6
+ # we provide to producer ale valid and usable
7
+ # @note Does not validate message itself as it is not our concern
8
+ class MessageOptions < Dry::Validation::Contract
9
+ params do
10
+ required(:topic).filled(:str?, format?: TOPIC_REGEXP)
11
+ optional(:key).maybe(:str?, :filled?)
12
+ optional(:partition).filled(:int?, gteq?: 0)
13
+ optional(:partition_key).maybe(:str?, :filled?)
14
+ optional(:create_time).maybe(:time?)
15
+ optional(:headers).maybe(:hash?)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -6,10 +6,10 @@ module WaterDrop
6
6
  # Base class for all the WaterDrop internal errors
7
7
  BaseError = Class.new(StandardError)
8
8
 
9
- # Raised when configuration doesn't match with validation schema
9
+ # Raised when configuration doesn't match with validation contract
10
10
  InvalidConfiguration = Class.new(BaseError)
11
11
 
12
- # Raised when we try to send message with invalid optionss
12
+ # Raised when we try to send message with invalid options
13
13
  InvalidMessageOptions = Class.new(BaseError)
14
14
 
15
15
  # Raised when want to hook up to an event that is not registered and supported
@@ -5,13 +5,11 @@ module WaterDrop
5
5
  module Instrumentation
6
6
  # Monitor is used to hookup external monitoring services to monitor how WaterDrop works
7
7
  # Since it is a pub-sub based on dry-monitor, you can use as many subscribers/loggers at the
8
- # same time, which means that you might have for example file logging and newrelic at the same
8
+ # same time, which means that you might have for example file logging and NewRelic at the same
9
9
  # time
10
10
  # @note This class acts as a singleton because we are only permitted to have single monitor
11
11
  # per running process (just as logger)
12
12
  class Monitor < Dry::Monitor::Notifications
13
- include Singleton
14
-
15
13
  # List of events that we support in the system and to which a monitor client can hook up
16
14
  # @note The non-error once support timestamp benchmarking
17
15
  BASE_EVENTS = %w[
@@ -35,6 +33,7 @@ module WaterDrop
35
33
  def subscribe(event_name_or_listener)
36
34
  return super unless event_name_or_listener.is_a?(String)
37
35
  return super if available_events.include?(event_name_or_listener)
36
+
38
37
  raise Errors::UnregisteredMonitorEvent, event_name_or_listener
39
38
  end
40
39
 
@@ -6,7 +6,7 @@ module WaterDrop
6
6
  # It can be removed/replaced or anything without any harm to the Waterdrop flow
7
7
  # @note It is a module as we can use it then as a part of the Karafka framework listener
8
8
  # as well as we can use it standalone
9
- module Listener
9
+ class StdoutListener
10
10
  # Log levels that we use in this particular listener
11
11
  USED_LOG_LEVELS = %i[
12
12
  info
@@ -33,20 +33,12 @@ module WaterDrop
33
33
 
34
34
  info "Attempt #{attempts_count} of delivery to: #{options} because of #{error}"
35
35
  end
36
-
37
- module_function error_name
38
- module_function retry_name
39
- public error_name
40
- public retry_name
41
36
  end
42
37
 
43
38
  USED_LOG_LEVELS.each do |log_level|
44
39
  define_method log_level do |*args|
45
40
  WaterDrop.logger.send(log_level, *args)
46
41
  end
47
-
48
- module_function log_level
49
- private_class_method log_level
50
42
  end
51
43
  end
52
44
  end
@@ -17,8 +17,8 @@ module WaterDrop
17
17
  return unless WaterDrop.config.deliver
18
18
 
19
19
  DeliveryBoy.deliver(message, options)
20
- rescue Kafka::Error => error
21
- graceful_attempt?(attempts_count, message, options, error) ? retry : raise(error)
20
+ rescue Kafka::Error => e
21
+ graceful_attempt?(attempts_count, message, options, e) ? retry : raise(e)
22
22
  end
23
23
  end
24
24
  end
@@ -3,5 +3,5 @@
3
3
  # WaterDrop library
4
4
  module WaterDrop
5
5
  # Current WaterDrop version
6
- VERSION = '1.2.1'
6
+ VERSION = '1.3.0'
7
7
  end
File without changes
@@ -17,13 +17,19 @@ Gem::Specification.new do |spec|
17
17
  spec.license = 'MIT'
18
18
 
19
19
  spec.add_dependency 'delivery_boy', '~> 0.2'
20
- spec.add_dependency 'dry-configurable', '~> 0.7'
21
- spec.add_dependency 'dry-monitor', '~> 0.1'
22
- spec.add_dependency 'dry-validation', '~> 0.11'
23
- spec.add_dependency 'null-logger', '~> 0.1'
20
+ spec.add_dependency 'dry-configurable', '~> 0.8'
21
+ spec.add_dependency 'dry-monitor', '~> 0.3'
22
+ spec.add_dependency 'dry-validation', '~> 1.2'
23
+ spec.add_dependency 'ruby-kafka', '>= 0.7.8'
24
+ spec.add_dependency 'zeitwerk', '~> 2.1'
24
25
 
25
- spec.required_ruby_version = '>= 2.2.0'
26
+ spec.required_ruby_version = '>= 2.4.0'
26
27
 
28
+ if $PROGRAM_NAME.end_with?('gem')
29
+ spec.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
30
+ end
31
+
32
+ spec.cert_chain = %w[certs/mensfeld.pem]
27
33
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
28
34
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
29
35
  spec.require_paths = %w[lib]
metadata CHANGED
@@ -1,14 +1,40 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waterdrop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
8
8
  autorequire:
9
9
  bindir: bin
10
- cert_chain: []
11
- date: 2018-03-26 00:00:00.000000000 Z
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEODCCAqCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhtYWNp
14
+ ZWovREM9bWVuc2ZlbGQvREM9cGwwHhcNMTkwNzMwMTQ1NDU0WhcNMjAwNzI5MTQ1
15
+ NDU0WjAjMSEwHwYDVQQDDBhtYWNpZWovREM9bWVuc2ZlbGQvREM9cGwwggGiMA0G
16
+ CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC9fCwtaHZG2SyyNXiH8r0QbJQx/xxl
17
+ dkvwWz9QGJO+O8rEx20FB1Ab+MVkfOscwIv5jWpmk1U9whzDPl1uFtIbgu+sk+Zb
18
+ uQlZyK/DPN6c+/BbBL+RryTBRyvkPLoCVwm7uxc/JZ1n4AI6eF4cCZ2ieZ9QgQbU
19
+ MQs2QPqs9hT50Ez/40GnOdadVfiDDGz+NME2C4ms0BriXwZ1tcRTfJIHe2xjIbbb
20
+ y5qRGfsLKcgMzvLQR24olixyX1MR0s4+Wveq3QL/gBhL4veUcv+UABJA8IJR0kyB
21
+ seHHutusiwZ1v3SjjjW1xLLrc2ARV0mgCb0WaK2T4iA3oFTGLh6Ydz8LNl31KQFv
22
+ 94nRd8IhmJxrhQ6dQ/WT9IXoa5S9lfT5lPJeINemH4/6QPABzf9W2IZlCdI9wCdB
23
+ TBaw57MKneGAYZiKjw6OALSy2ltQUCl3RqFl3VP7n8uFy1U987Q5VIIQ3O1UUsQD
24
+ Oe/h+r7GUU4RSPKgPlrwvW9bD/UQ+zF51v8CAwEAAaN3MHUwCQYDVR0TBAIwADAL
25
+ BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFJNIBHdfEUD7TqHqIer2YhWaWhwcMB0GA1Ud
26
+ EQQWMBSBEm1hY2llakBtZW5zZmVsZC5wbDAdBgNVHRIEFjAUgRJtYWNpZWpAbWVu
27
+ c2ZlbGQucGwwDQYJKoZIhvcNAQELBQADggGBAKA4eqko6BTNhlysip6rfBkVTGri
28
+ ZXsL+kRb2hLvsQJS/kLyM21oMlu+LN0aPj3qEFR8mE/YeDD8rLAfruBRTltPNbR7
29
+ xA5eE1gkxY5LfExUtK3b2wPqfmo7mZgfcsMwfYg/tUXw1WpBCnrhAJodpGH6SXmp
30
+ A40qFUZst0vjiOoO+aTblIHPmMJXoZ3K42dTlNKlEiDKUWMRKSgpjjYGEYalFNWI
31
+ hHfCz2r8L2t+dYdMZg1JGbEkq4ADGsAA8ioZIpJd7V4hI17u5TCdi7X5wh/0gN0E
32
+ CgP+nLox3D+l2q0QuQEkayr+auFYkzTCkF+BmEk1D0Ru4mcf3F4CJvEmW4Pzbjqt
33
+ i1tsCWPtJ4E/UUKnKaWKqGbjrjHJ0MuShYzHkodox5IOiCXIQg+1+YSzfXUV6WEK
34
+ KJG/fhg1JV5vVDdVy6x+tv5SQ5ctU0feCsVfESi3rE3zRd+nvzE9HcZ5aXeL1UtJ
35
+ nT5Xrioegu2w1jPyVEgyZgTZC5rvD0nNS5sFNQ==
36
+ -----END CERTIFICATE-----
37
+ date: 2019-09-09 00:00:00.000000000 Z
12
38
  dependencies:
13
39
  - !ruby/object:Gem::Dependency
14
40
  name: delivery_boy
@@ -30,56 +56,70 @@ dependencies:
30
56
  requirements:
31
57
  - - "~>"
32
58
  - !ruby/object:Gem::Version
33
- version: '0.7'
59
+ version: '0.8'
34
60
  type: :runtime
35
61
  prerelease: false
36
62
  version_requirements: !ruby/object:Gem::Requirement
37
63
  requirements:
38
64
  - - "~>"
39
65
  - !ruby/object:Gem::Version
40
- version: '0.7'
66
+ version: '0.8'
41
67
  - !ruby/object:Gem::Dependency
42
68
  name: dry-monitor
43
69
  requirement: !ruby/object:Gem::Requirement
44
70
  requirements:
45
71
  - - "~>"
46
72
  - !ruby/object:Gem::Version
47
- version: '0.1'
73
+ version: '0.3'
48
74
  type: :runtime
49
75
  prerelease: false
50
76
  version_requirements: !ruby/object:Gem::Requirement
51
77
  requirements:
52
78
  - - "~>"
53
79
  - !ruby/object:Gem::Version
54
- version: '0.1'
80
+ version: '0.3'
55
81
  - !ruby/object:Gem::Dependency
56
82
  name: dry-validation
57
83
  requirement: !ruby/object:Gem::Requirement
58
84
  requirements:
59
85
  - - "~>"
60
86
  - !ruby/object:Gem::Version
61
- version: '0.11'
87
+ version: '1.2'
62
88
  type: :runtime
63
89
  prerelease: false
64
90
  version_requirements: !ruby/object:Gem::Requirement
65
91
  requirements:
66
92
  - - "~>"
67
93
  - !ruby/object:Gem::Version
68
- version: '0.11'
94
+ version: '1.2'
69
95
  - !ruby/object:Gem::Dependency
70
- name: null-logger
96
+ name: ruby-kafka
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: 0.7.8
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: 0.7.8
109
+ - !ruby/object:Gem::Dependency
110
+ name: zeitwerk
71
111
  requirement: !ruby/object:Gem::Requirement
72
112
  requirements:
73
113
  - - "~>"
74
114
  - !ruby/object:Gem::Version
75
- version: '0.1'
115
+ version: '2.1'
76
116
  type: :runtime
77
117
  prerelease: false
78
118
  version_requirements: !ruby/object:Gem::Requirement
79
119
  requirements:
80
120
  - - "~>"
81
121
  - !ruby/object:Gem::Version
82
- version: '0.1'
122
+ version: '2.1'
83
123
  description: Kafka messaging made easy!
84
124
  email:
85
125
  - maciej@mensfeld.pl
@@ -87,6 +127,8 @@ executables: []
87
127
  extensions: []
88
128
  extra_rdoc_files: []
89
129
  files:
130
+ - ".coditsu/ci.yml"
131
+ - ".github/FUNDING.yml"
90
132
  - ".gitignore"
91
133
  - ".rspec"
92
134
  - ".ruby-gemset"
@@ -97,19 +139,23 @@ files:
97
139
  - Gemfile.lock
98
140
  - MIT-LICENCE
99
141
  - README.md
142
+ - certs/mensfeld.pem
100
143
  - config/errors.yml
101
144
  - lib/water_drop.rb
102
145
  - lib/water_drop/async_producer.rb
103
146
  - lib/water_drop/base_producer.rb
104
147
  - lib/water_drop/config.rb
148
+ - lib/water_drop/config_applier.rb
149
+ - lib/water_drop/contracts.rb
150
+ - lib/water_drop/contracts/config.rb
151
+ - lib/water_drop/contracts/message_options.rb
105
152
  - lib/water_drop/errors.rb
106
- - lib/water_drop/instrumentation/listener.rb
107
153
  - lib/water_drop/instrumentation/monitor.rb
108
- - lib/water_drop/schemas/config.rb
109
- - lib/water_drop/schemas/message_options.rb
154
+ - lib/water_drop/instrumentation/stdout_listener.rb
110
155
  - lib/water_drop/sync_producer.rb
111
156
  - lib/water_drop/version.rb
112
157
  - lib/waterdrop.rb
158
+ - log/.keep
113
159
  - waterdrop.gemspec
114
160
  homepage: https://github.com/karafka/waterdrop
115
161
  licenses:
@@ -123,15 +169,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
123
169
  requirements:
124
170
  - - ">="
125
171
  - !ruby/object:Gem::Version
126
- version: 2.2.0
172
+ version: 2.4.0
127
173
  required_rubygems_version: !ruby/object:Gem::Requirement
128
174
  requirements:
129
175
  - - ">="
130
176
  - !ruby/object:Gem::Version
131
177
  version: '0'
132
178
  requirements: []
133
- rubyforge_project:
134
- rubygems_version: 2.7.6
179
+ rubygems_version: 3.0.3
135
180
  signing_key:
136
181
  specification_version: 4
137
182
  summary: Kafka messaging made easy!
Binary file
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WaterDrop
4
- # Namespace for all the schemas for config validations
5
- module Schemas
6
- # Schema with validation rules for WaterDrop configuration details
7
- Config = Dry::Validation.Schema do
8
- # Valid uri schemas of Kafka broker url
9
- URI_SCHEMES = %w[
10
- kafka
11
- kafka+ssl
12
- ].freeze
13
-
14
- # Available sasl scram mechanism of authentication (plus nil)
15
- SASL_SCRAM_MECHANISMS ||= %w[sha256 sha512].freeze
16
-
17
- configure do
18
- config.messages_file = File.join(
19
- WaterDrop.gem_root, 'config', 'errors.yml'
20
- )
21
-
22
- # Uri validator to check if uri is in a Kafka acceptable format
23
- # @param uri [String] uri we want to validate
24
- # @return [Boolean] true if it is a valid uri, otherwise false
25
- def broker_schema?(uri)
26
- uri = URI.parse(uri)
27
- URI_SCHEMES.include?(uri.scheme) && uri.port
28
- rescue URI::InvalidURIError
29
- false
30
- end
31
- end
32
-
33
- required(:client_id).filled(:str?, format?: Schemas::TOPIC_REGEXP)
34
- required(:logger).filled
35
- required(:deliver).filled(:bool?)
36
- required(:raise_on_buffer_overflow).filled(:bool?)
37
-
38
- required(:kafka).schema do
39
- required(:seed_brokers).filled { each(:broker_schema?) }
40
- required(:connect_timeout).filled { (int? | float?) & gt?(0) }
41
- required(:socket_timeout).filled { (int? | float?) & gt?(0) }
42
- required(:compression_threshold).filled(:int?, gteq?: 1)
43
- optional(:compression_codec).maybe(included_in?: %w[snappy gzip lz4])
44
-
45
- required(:max_buffer_bytesize).filled(:int?, gt?: 0)
46
- required(:max_buffer_size).filled(:int?, gt?: 0)
47
- required(:max_queue_size).filled(:int?, gt?: 0)
48
-
49
- required(:ack_timeout).filled(:int?, gt?: 0)
50
- required(:delivery_interval).filled(:int?, gteq?: 0)
51
- required(:delivery_threshold).filled(:int?, gteq?: 0)
52
-
53
- required(:max_retries).filled(:int?, gteq?: 0)
54
- required(:retry_backoff).filled(:int?, gteq?: 0)
55
- required(:required_acks).filled(included_in?: [1, 0, -1, :all])
56
-
57
- %i[
58
- ssl_ca_cert
59
- ssl_ca_cert_file_path
60
- ssl_client_cert
61
- ssl_client_cert_key
62
- sasl_gssapi_principal
63
- sasl_gssapi_keytab
64
- sasl_plain_authzid
65
- sasl_plain_username
66
- sasl_plain_password
67
- sasl_scram_username
68
- sasl_scram_password
69
- ].each do |encryption_attribute|
70
- optional(encryption_attribute).maybe(:str?)
71
- end
72
-
73
- optional(:ssl_ca_certs_from_system).maybe(:bool?)
74
-
75
- # It's not with other encryptions as it has some more rules
76
- optional(:sasl_scram_mechanism)
77
- .maybe(:str?, included_in?: WaterDrop::Schemas::SASL_SCRAM_MECHANISMS)
78
- end
79
- end
80
- end
81
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WaterDrop
4
- module Schemas
5
- # Regexp to check that topic has a valid format
6
- TOPIC_REGEXP = /\A(\w|\-|\.)+\z/
7
-
8
- # Schema with validation rules for validating that all the message options that
9
- # we provide to producer ale valid and usable
10
- # @note Does not validate message itself as it is not our concern
11
- MessageOptions = Dry::Validation.Schema do
12
- required(:topic).filled(:str?, format?: TOPIC_REGEXP)
13
- optional(:key).maybe(:str?, :filled?)
14
- optional(:partition).filled(:int?, gteq?: 0)
15
- optional(:partition_key).maybe(:str?, :filled?)
16
- optional(:create_time).maybe(:time?)
17
- end
18
- end
19
- end