waterdrop 1.0.1 → 1.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.ruby-version +1 -1
- data/.travis.yml +1 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +22 -11
- data/README.md +28 -34
- data/lib/water_drop.rb +9 -0
- data/lib/water_drop/async_producer.rb +8 -11
- data/lib/water_drop/base_producer.rb +29 -0
- data/lib/water_drop/config.rb +25 -8
- data/lib/water_drop/errors.rb +3 -0
- data/lib/water_drop/instrumentation/listener.rb +53 -0
- data/lib/water_drop/instrumentation/monitor.rb +47 -0
- data/lib/water_drop/schemas/config.rb +23 -14
- data/lib/water_drop/schemas/message_options.rb +1 -0
- data/lib/water_drop/sync_producer.rb +5 -10
- data/lib/water_drop/version.rb +1 -1
- data/waterdrop.gemspec +4 -3
- metadata +25 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 25c083d88a1163c685e9939307feba4294fd3a526f4523692958cdc5d0d04363
|
4
|
+
data.tar.gz: 300d3e1cce18970d0c9beb105ab6e3b6b7d5eedfc388e3fad7f1cd0db1c204e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa9f0cdfb2285b1f50a71f9a1e84310903e1abc936cd41838f8568a2ddf818b4c83324ccaf7a7c299980a7a8b7d6f0c8fb7fdad65b075e26440bc740be1f20cb
|
7
|
+
data.tar.gz: fff2c225e42eeb1ab849fb5ea34c900e6bf4b9783541a6087c094647ec8235c6ce6305087119455d2900cfd53c55e7179b27be5b0f29d49ef80f70720f6674ff
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.5.0
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# WaterDrop changelog
|
2
2
|
|
3
|
+
## 1.2.0.beta1
|
4
|
+
- #45 - Allow specifying a create time for messages
|
5
|
+
- #47 - Support SCRAM once released
|
6
|
+
- #49 - Add lz4 support once merged and released
|
7
|
+
- #50 - Potential message loss in async mode
|
8
|
+
- Ruby 2.5.0 support
|
9
|
+
- Gem bump to match Karafka framework versioning
|
10
|
+
- #48 - ssl_ca_certs_from_system
|
11
|
+
- #52 - Use instrumentation compatible with Karafka 1.2
|
12
|
+
|
3
13
|
## 1.0.1
|
4
14
|
- Added high level retry on connection problems
|
5
15
|
|
data/Gemfile.lock
CHANGED
@@ -1,20 +1,21 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
waterdrop (1.0.
|
5
|
-
delivery_boy (>= 0.2.
|
4
|
+
waterdrop (1.2.0.beta1)
|
5
|
+
delivery_boy (>= 0.2.3)
|
6
6
|
dry-configurable (~> 0.7)
|
7
|
+
dry-monitor (~> 0.1)
|
7
8
|
dry-validation (~> 0.11)
|
8
9
|
null-logger
|
9
|
-
ruby-kafka (>= 0.5)
|
10
|
+
ruby-kafka (>= 0.5.3)
|
10
11
|
|
11
12
|
GEM
|
12
13
|
remote: https://rubygems.org/
|
13
14
|
specs:
|
14
15
|
concurrent-ruby (1.0.5)
|
15
|
-
delivery_boy (0.2.
|
16
|
+
delivery_boy (0.2.4)
|
16
17
|
king_konf (~> 0.1.8)
|
17
|
-
ruby-kafka (~> 0.
|
18
|
+
ruby-kafka (~> 0.5.1)
|
18
19
|
diff-lcs (1.3)
|
19
20
|
docile (1.1.5)
|
20
21
|
dry-configurable (0.7.0)
|
@@ -22,13 +23,22 @@ GEM
|
|
22
23
|
dry-container (0.6.0)
|
23
24
|
concurrent-ruby (~> 1.0)
|
24
25
|
dry-configurable (~> 0.1, >= 0.1.3)
|
25
|
-
dry-core (0.4.
|
26
|
+
dry-core (0.4.4)
|
26
27
|
concurrent-ruby (~> 1.0)
|
27
28
|
dry-equalizer (0.2.0)
|
29
|
+
dry-events (0.1.0)
|
30
|
+
concurrent-ruby (~> 1.0)
|
31
|
+
dry-core (~> 0.4)
|
32
|
+
dry-equalizer (~> 0.2)
|
28
33
|
dry-logic (0.4.2)
|
29
34
|
dry-container (~> 0.2, >= 0.2.6)
|
30
35
|
dry-core (~> 0.2)
|
31
36
|
dry-equalizer (~> 0.2)
|
37
|
+
dry-monitor (0.1.2)
|
38
|
+
dry-configurable (~> 0.5)
|
39
|
+
dry-equalizer (~> 0.2)
|
40
|
+
dry-events (~> 0.1)
|
41
|
+
rouge (~> 2.0, >= 2.2.1)
|
32
42
|
dry-types (0.12.2)
|
33
43
|
concurrent-ruby (~> 1.0)
|
34
44
|
dry-configurable (~> 0.1)
|
@@ -46,13 +56,14 @@ GEM
|
|
46
56
|
dry-types (~> 0.12.0)
|
47
57
|
inflecto (0.0.2)
|
48
58
|
json (2.1.0)
|
49
|
-
king_konf (0.1.
|
59
|
+
king_konf (0.1.10)
|
50
60
|
null-logger (0.1.4)
|
61
|
+
rouge (2.2.1)
|
51
62
|
rspec (3.7.0)
|
52
63
|
rspec-core (~> 3.7.0)
|
53
64
|
rspec-expectations (~> 3.7.0)
|
54
65
|
rspec-mocks (~> 3.7.0)
|
55
|
-
rspec-core (3.7.
|
66
|
+
rspec-core (3.7.1)
|
56
67
|
rspec-support (~> 3.7.0)
|
57
68
|
rspec-expectations (3.7.0)
|
58
69
|
diff-lcs (>= 1.2.0, < 2.0)
|
@@ -60,8 +71,8 @@ GEM
|
|
60
71
|
rspec-mocks (3.7.0)
|
61
72
|
diff-lcs (>= 1.2.0, < 2.0)
|
62
73
|
rspec-support (~> 3.7.0)
|
63
|
-
rspec-support (3.7.
|
64
|
-
ruby-kafka (0.5.
|
74
|
+
rspec-support (3.7.1)
|
75
|
+
ruby-kafka (0.5.3)
|
65
76
|
simplecov (0.15.1)
|
66
77
|
docile (~> 1.1.0)
|
67
78
|
json (>= 1.8, < 3)
|
@@ -77,4 +88,4 @@ DEPENDENCIES
|
|
77
88
|
waterdrop!
|
78
89
|
|
79
90
|
BUNDLED WITH
|
80
|
-
1.
|
91
|
+
1.16.1
|
data/README.md
CHANGED
@@ -11,6 +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
15
|
|
15
16
|
## Installation
|
16
17
|
|
@@ -60,19 +61,20 @@ end
|
|
60
61
|
|
61
62
|
**Note:** All the options are subject to validations. In order to check what is and what is not acceptable, please go to the [config.rb validation schema](https://github.com/karafka/waterdrop/blob/master/lib/water_drop/schemas/config.rb) file.
|
62
63
|
|
63
|
-
| Option
|
64
|
-
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
| Option | Description |
|
65
|
+
|--------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
|
66
|
+
| raise_on_buffer_overflow | Should we raise an exception, when messages can't be sent in an async way due to the message buffer overflow or should we just drop them |
|
67
|
+
| delivery_interval | The number of seconds between background message deliveries. Disable timer-based background deliveries by setting this to 0. |
|
68
|
+
| delivery_threshold | The number of buffered messages that will trigger a background message delivery. Disable buffer size based background deliveries by setting this to 0.|
|
69
|
+
| required_acks | The number of Kafka replicas that must acknowledge messages before they're considered as successfully written. |
|
70
|
+
| ack_timeout | A timeout executed by a broker when the client is sending messages to it. |
|
71
|
+
| max_retries | The number of retries when attempting to deliver messages. |
|
72
|
+
| retry_backoff | The number of seconds to wait after a failed attempt to send messages to a Kafka broker before retrying. |
|
73
|
+
| max_buffer_bytesize | The maximum number of bytes allowed in the buffer before new messages are rejected. |
|
74
|
+
| max_buffer_size | The maximum number of messages allowed in the buffer before new messages are rejected. |
|
75
|
+
| max_queue_size | The maximum number of messages allowed in the queue before new messages are rejected. |
|
76
|
+
| sasl_plain_username | The username used to authenticate. |
|
77
|
+
| sasl_plain_password | The password used to authenticate. |
|
76
78
|
|
77
79
|
This configuration can be also placed in *config/initializers* and can vary based on the environment:
|
78
80
|
|
@@ -95,12 +97,13 @@ WaterDrop::AsyncProducer.call('message', topic: 'my-topic')
|
|
95
97
|
|
96
98
|
Both ```SyncProducer``` and ```AsyncProducer``` accept following options:
|
97
99
|
|
98
|
-
| Option | Required | Value type
|
99
|
-
|--------------------
|
100
|
-
| ```topic``` | true | String
|
101
|
-
| ```key``` | false | String
|
102
|
-
| ```partition``` | false | Integer
|
103
|
-
| ```partition_key``` | false | String
|
100
|
+
| Option | Required | Value type | Description |
|
101
|
+
|-------------------- |----------|------------|---------------------------------------------------------------------|
|
102
|
+
| ```topic``` | true | String | The Kafka topic that should be written to |
|
103
|
+
| ```key``` | false | String | The key that should be set on the Kafka message |
|
104
|
+
| ```partition``` | false | Integer | A specific partition number that should be written to |
|
105
|
+
| ```partition_key``` | false | String | A string that can be used to deterministically select the partition |
|
106
|
+
| ```create_time``` | false | Time | The timestamp that should be set on the message |
|
104
107
|
|
105
108
|
Keep in mind, that message you want to send should be either binary or stringified (to_s, to_json, etc).
|
106
109
|
|
@@ -110,23 +113,14 @@ Keep in mind, that message you want to send should be either binary or stringifi
|
|
110
113
|
* [WaterDrop Travis CI](https://travis-ci.org/karafka/waterdrop)
|
111
114
|
* [WaterDrop Coditsu](https://app.coditsu.io/karafka/repositories/waterdrop)
|
112
115
|
|
113
|
-
## Note on
|
116
|
+
## Note on contributions
|
114
117
|
|
115
|
-
|
116
|
-
Make your feature addition or bug fix.
|
117
|
-
Add tests for it. This is important so we don't break it in a future versions unintentionally.
|
118
|
-
Commit, do not mess with version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull). Send me a pull request. Bonus points for topic branches.
|
118
|
+
First, thank you for considering contributing to WaterDrop! It's people like you that make the open source community such a great community!
|
119
119
|
|
120
|
-
|
120
|
+
Each pull request must pass all the rspec specs and meet our quality requirements.
|
121
121
|
|
122
|
-
|
122
|
+
To check if everything is as it should be, we use [Coditsu](https://coditsu.io) that combines multiple linters and code analyzers for both code and documentation. Once you're done with your changes, submit a pull request.
|
123
123
|
|
124
|
-
|
124
|
+
Coditsu will automatically check your work against our quality standards. You can find your commit check results on the [builds page](https://app.coditsu.io/karafka/repositories/waterdrop/builds/commit_builds) of WaterDrop repository.
|
125
125
|
|
126
|
-
|
127
|
-
|
128
|
-
```bash
|
129
|
-
bundle exec rspec
|
130
|
-
```
|
131
|
-
|
132
|
-
to check if everything is in order. After that you can submit a pull request.
|
126
|
+
[![coditsu](https://coditsu.io/assets/quality_bar.svg)](https://app.coditsu.io/karafka/repositories/waterdrop/builds/commit_builds)
|
data/lib/water_drop.rb
CHANGED
@@ -5,7 +5,9 @@
|
|
5
5
|
json
|
6
6
|
delivery_boy
|
7
7
|
null_logger
|
8
|
+
singleton
|
8
9
|
dry-configurable
|
10
|
+
dry/monitor/notifications
|
9
11
|
dry-validation
|
10
12
|
].each { |lib| require lib }
|
11
13
|
|
@@ -44,6 +46,11 @@ module WaterDrop
|
|
44
46
|
Config.config
|
45
47
|
end
|
46
48
|
|
49
|
+
# @return [::WaterDrop::Monitor] monitor that we want to use
|
50
|
+
def monitor
|
51
|
+
config.monitor
|
52
|
+
end
|
53
|
+
|
47
54
|
# @return [String] root path of this gem
|
48
55
|
def gem_root
|
49
56
|
Pathname.new(File.expand_path('../..', __FILE__))
|
@@ -53,6 +60,8 @@ end
|
|
53
60
|
|
54
61
|
%w[
|
55
62
|
version
|
63
|
+
instrumentation/monitor
|
64
|
+
instrumentation/listener
|
56
65
|
schemas/message_options
|
57
66
|
schemas/config
|
58
67
|
config
|
@@ -10,20 +10,17 @@ module WaterDrop
|
|
10
10
|
# @raise [WaterDrop::Errors::InvalidMessageOptions] raised when message options are
|
11
11
|
# somehow invalid and we cannot perform delivery because of that
|
12
12
|
def self.call(message, options)
|
13
|
-
|
14
|
-
|
13
|
+
attempts_count ||= 0
|
14
|
+
attempts_count += 1
|
15
15
|
|
16
16
|
validate!(options)
|
17
17
|
return unless WaterDrop.config.deliver
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
WaterDrop.logger.warn "Retrying delivery after: #{e}"
|
25
|
-
retry
|
26
|
-
end
|
18
|
+
|
19
|
+
d_method = WaterDrop.config.raise_on_buffer_overflow ? :deliver_async! : :deliver_async
|
20
|
+
|
21
|
+
DeliveryBoy.send(d_method, message, options)
|
22
|
+
rescue Kafka::Error => error
|
23
|
+
graceful_attempt?(attempts_count, message, options, error) ? retry : raise(error)
|
27
24
|
end
|
28
25
|
end
|
29
26
|
end
|
@@ -16,6 +16,35 @@ module WaterDrop
|
|
16
16
|
return true if validation_result.success?
|
17
17
|
raise Errors::InvalidMessageOptions, validation_result.errors
|
18
18
|
end
|
19
|
+
|
20
|
+
# 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
|
22
|
+
# This method checks that and also instruments errors and retries for the delivery
|
23
|
+
# @param attempts_count [Integer] number of attempt (starting from 1) for the delivery
|
24
|
+
# @param message [String] message that we want to send to Kafka
|
25
|
+
# @param options [Hash] options (including topic) for producer
|
26
|
+
# @param error [Kafka::Error] error that occured
|
27
|
+
# @return [Boolean] true if this is a graceful attempt and we can retry or false it this
|
28
|
+
# was the final one and we should deal with the fact, that we cannot deliver a given
|
29
|
+
# message
|
30
|
+
def graceful_attempt?(attempts_count, message, options, error)
|
31
|
+
scope = "#{to_s.split('::').last.sub('Producer', '_producer').downcase}.call"
|
32
|
+
payload = {
|
33
|
+
caller: self,
|
34
|
+
message: message,
|
35
|
+
options: options,
|
36
|
+
error: error,
|
37
|
+
attempts_count: attempts_count
|
38
|
+
}
|
39
|
+
|
40
|
+
if attempts_count > WaterDrop.config.kafka.max_retries
|
41
|
+
WaterDrop.monitor.instrument("#{scope}.error", payload)
|
42
|
+
false
|
43
|
+
else
|
44
|
+
WaterDrop.monitor.instrument("#{scope}.retry", payload)
|
45
|
+
true
|
46
|
+
end
|
47
|
+
end
|
19
48
|
end
|
20
49
|
end
|
21
50
|
end
|
data/lib/water_drop/config.rb
CHANGED
@@ -12,9 +12,17 @@ module WaterDrop
|
|
12
12
|
setting :client_id, 'waterdrop'
|
13
13
|
# option [Instance, nil] logger that we want to use or nil to fallback to ruby-kafka logger
|
14
14
|
setting :logger, NullLogger.new
|
15
|
+
# option [Instance] monitor that we want to use. See instrumentation part of the README for
|
16
|
+
# more details
|
17
|
+
setting :monitor, WaterDrop::Instrumentation::Monitor.instance
|
15
18
|
# option [Boolean] should we send messages. Setting this to false can be really useful when
|
16
19
|
# testing and or developing because when set to false, won't actually ping Kafka
|
17
20
|
setting :deliver, true
|
21
|
+
# option [Boolean] if you're producing messages faster than the framework or the network can
|
22
|
+
# send them off, ruby-kafka might reject them. If that happens, WaterDrop will either raise
|
23
|
+
# or ignore - this setting manages that behavior. This only applies to async producer as
|
24
|
+
# sync producer will always raise upon problems
|
25
|
+
setting :raise_on_buffer_overflow, true
|
18
26
|
|
19
27
|
# Settings directly related to the Kafka driver
|
20
28
|
setting :kafka do
|
@@ -73,24 +81,33 @@ module WaterDrop
|
|
73
81
|
setting :compression_codec, nil
|
74
82
|
|
75
83
|
# SSL authentication related settings
|
76
|
-
# option ca_cert [String] SSL CA certificate
|
84
|
+
# option ca_cert [String, nil] SSL CA certificate
|
77
85
|
setting :ssl_ca_cert, nil
|
78
|
-
# option ssl_ca_cert_file_path [String] SSL CA certificate file path
|
86
|
+
# option ssl_ca_cert_file_path [String, nil] SSL CA certificate file path
|
79
87
|
setting :ssl_ca_cert_file_path, nil
|
80
|
-
# option
|
88
|
+
# option ssl_ca_certs_from_system [Boolean] Use the CA certs from your system's default
|
89
|
+
# certificate store
|
90
|
+
setting :ssl_ca_certs_from_system, false
|
91
|
+
# option ssl_client_cert [String, nil] SSL client certificate
|
81
92
|
setting :ssl_client_cert, nil
|
82
|
-
# option ssl_client_cert_key [String] SSL client certificate password
|
93
|
+
# option ssl_client_cert_key [String, nil] SSL client certificate password
|
83
94
|
setting :ssl_client_cert_key, nil
|
84
|
-
# option sasl_gssapi_principal [String] sasl principal
|
95
|
+
# option sasl_gssapi_principal [String, nil] sasl principal
|
85
96
|
setting :sasl_gssapi_principal, nil
|
86
|
-
# option sasl_gssapi_keytab [String] sasl keytab
|
97
|
+
# option sasl_gssapi_keytab [String, nil] sasl keytab
|
87
98
|
setting :sasl_gssapi_keytab, nil
|
88
99
|
# option sasl_plain_authzid [String] The authorization identity to use
|
89
100
|
setting :sasl_plain_authzid, ''
|
90
|
-
# option sasl_plain_username [String] The username used to authenticate
|
101
|
+
# option sasl_plain_username [String, nil] The username used to authenticate
|
91
102
|
setting :sasl_plain_username, nil
|
92
|
-
# option sasl_plain_password [String] The password used to authenticate
|
103
|
+
# option sasl_plain_password [String, nil] The password used to authenticate
|
93
104
|
setting :sasl_plain_password, nil
|
105
|
+
# option sasl_scram_username [String, nil] The username used to authenticate
|
106
|
+
setting :sasl_scram_username, nil
|
107
|
+
# option sasl_scram_password [String, nil] The password used to authenticate
|
108
|
+
setting :sasl_scram_password, nil
|
109
|
+
# option sasl_scram_mechanism [String, nil] Scram mechanism, either 'sha256' or 'sha512'
|
110
|
+
setting :sasl_scram_mechanism, nil
|
94
111
|
end
|
95
112
|
|
96
113
|
# option producer [Hash] - optional - producer configuration options
|
data/lib/water_drop/errors.rb
CHANGED
@@ -11,5 +11,8 @@ module WaterDrop
|
|
11
11
|
|
12
12
|
# Raised when we try to send message with invalid optionss
|
13
13
|
InvalidMessageOptions = Class.new(BaseError)
|
14
|
+
|
15
|
+
# Raised when want to hook up to an event that is not registered and supported
|
16
|
+
UnregisteredMonitorEvent = Class.new(BaseError)
|
14
17
|
end
|
15
18
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module WaterDrop
|
4
|
+
module Instrumentation
|
5
|
+
# Default listener that hooks up to our instrumentation and uses its events for logging
|
6
|
+
# It can be removed/replaced or anything without any harm to the Waterdrop flow
|
7
|
+
# @note It is a module as we can use it then as a part of the Karafka framework listener
|
8
|
+
# as well as we can use it standalone
|
9
|
+
module Listener
|
10
|
+
# Log levels that we use in this particular listener
|
11
|
+
USED_LOG_LEVELS = %i[
|
12
|
+
info
|
13
|
+
error
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
%i[
|
17
|
+
sync_producer
|
18
|
+
async_producer
|
19
|
+
].each do |producer_type|
|
20
|
+
error_name = :"on_#{producer_type}_call_error"
|
21
|
+
retry_name = :"on_#{producer_type}_call_retry"
|
22
|
+
|
23
|
+
define_method error_name do |event|
|
24
|
+
options = event[:options]
|
25
|
+
error = event[:error]
|
26
|
+
error "Delivery failure to: #{options} because of #{error}"
|
27
|
+
end
|
28
|
+
|
29
|
+
define_method retry_name do |event|
|
30
|
+
attempts_count = event[:attempts_count]
|
31
|
+
options = event[:options]
|
32
|
+
error = event[:error]
|
33
|
+
|
34
|
+
info "Attempt #{attempts_count} of delivery to: #{options} because of #{error}"
|
35
|
+
end
|
36
|
+
|
37
|
+
module_function error_name
|
38
|
+
module_function retry_name
|
39
|
+
public error_name
|
40
|
+
public retry_name
|
41
|
+
end
|
42
|
+
|
43
|
+
USED_LOG_LEVELS.each do |log_level|
|
44
|
+
define_method log_level do |*args|
|
45
|
+
WaterDrop.logger.send(log_level, *args)
|
46
|
+
end
|
47
|
+
|
48
|
+
module_function log_level
|
49
|
+
private_class_method log_level
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module WaterDrop
|
4
|
+
# Namespace for all the things related with WaterDrop instrumentation process
|
5
|
+
module Instrumentation
|
6
|
+
# Monitor is used to hookup external monitoring services to monitor how WaterDrop works
|
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
|
9
|
+
# time
|
10
|
+
# @note This class acts as a singleton because we are only permitted to have single monitor
|
11
|
+
# per running process (just as logger)
|
12
|
+
class Monitor < Dry::Monitor::Notifications
|
13
|
+
include Singleton
|
14
|
+
|
15
|
+
# List of events that we support in the system and to which a monitor client can hook up
|
16
|
+
# @note The non-error once support timestamp benchmarking
|
17
|
+
BASE_EVENTS = %w[
|
18
|
+
async_producer.call.error
|
19
|
+
async_producer.call.retry
|
20
|
+
sync_producer.call.error
|
21
|
+
sync_producer.call.retry
|
22
|
+
].freeze
|
23
|
+
|
24
|
+
private_constant :BASE_EVENTS
|
25
|
+
|
26
|
+
# @return [WaterDrop::Instrumentation::Monitor] monitor instance for system instrumentation
|
27
|
+
def initialize
|
28
|
+
super(:waterdrop)
|
29
|
+
BASE_EVENTS.each(&method(:register_event))
|
30
|
+
end
|
31
|
+
|
32
|
+
# Allows us to subscribe to events with a code that will be yielded upon events
|
33
|
+
# @param event_name_or_listener [String, Object] name of the event we want to subscribe to
|
34
|
+
# or a listener if we decide to go with object listener
|
35
|
+
def subscribe(event_name_or_listener)
|
36
|
+
return super unless event_name_or_listener.is_a?(String)
|
37
|
+
return super if available_events.include?(event_name_or_listener)
|
38
|
+
raise Errors::UnregisteredMonitorEvent, event_name_or_listener
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Array<String>] names of available events to which we can subscribe
|
42
|
+
def available_events
|
43
|
+
__bus__.events.keys
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -11,18 +11,8 @@ module WaterDrop
|
|
11
11
|
kafka+ssl
|
12
12
|
].freeze
|
13
13
|
|
14
|
-
#
|
15
|
-
|
16
|
-
ssl_ca_cert
|
17
|
-
ssl_ca_cert_file_path
|
18
|
-
ssl_client_cert
|
19
|
-
ssl_client_cert_key
|
20
|
-
sasl_plain_authzid
|
21
|
-
sasl_plain_username
|
22
|
-
sasl_plain_password
|
23
|
-
sasl_gssapi_principal
|
24
|
-
sasl_gssapi_keytab
|
25
|
-
].freeze
|
14
|
+
# Available sasl scram mechanism of authentication (plus nil)
|
15
|
+
SASL_SCRAM_MECHANISMS ||= %w[sha256 sha512].freeze
|
26
16
|
|
27
17
|
configure do
|
28
18
|
config.messages_file = File.join(
|
@@ -43,13 +33,14 @@ module WaterDrop
|
|
43
33
|
required(:client_id).filled(:str?, format?: Schemas::TOPIC_REGEXP)
|
44
34
|
required(:logger).filled
|
45
35
|
required(:deliver).filled(:bool?)
|
36
|
+
required(:raise_on_buffer_overflow).filled(:bool?)
|
46
37
|
|
47
38
|
required(:kafka).schema do
|
48
39
|
required(:seed_brokers).filled { each(:broker_schema?) }
|
49
40
|
required(:connect_timeout).filled { (int? | float?) & gt?(0) }
|
50
41
|
required(:socket_timeout).filled { (int? | float?) & gt?(0) }
|
51
42
|
required(:compression_threshold).filled(:int?, gteq?: 1)
|
52
|
-
optional(:compression_codec).maybe(included_in?: %i[snappy gzip])
|
43
|
+
optional(:compression_codec).maybe(included_in?: %i[snappy gzip lz4])
|
53
44
|
|
54
45
|
required(:max_buffer_bytesize).filled(:int?, gt?: 0)
|
55
46
|
required(:max_buffer_size).filled(:int?, gt?: 0)
|
@@ -63,9 +54,27 @@ module WaterDrop
|
|
63
54
|
required(:retry_backoff).filled(:int?, gteq?: 0)
|
64
55
|
required(:required_acks).filled(included_in?: [1, 0, -1, :all])
|
65
56
|
|
66
|
-
|
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|
|
67
70
|
optional(encryption_attribute).maybe(:str?)
|
68
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)
|
69
78
|
end
|
70
79
|
end
|
71
80
|
end
|
@@ -10,20 +10,15 @@ module WaterDrop
|
|
10
10
|
# @raise [WaterDrop::Errors::InvalidMessageOptions] raised when message options are
|
11
11
|
# somehow invalid and we cannot perform delivery because of that
|
12
12
|
def self.call(message, options)
|
13
|
-
|
14
|
-
|
13
|
+
attempts_count ||= 0
|
14
|
+
attempts_count += 1
|
15
15
|
|
16
16
|
validate!(options)
|
17
17
|
return unless WaterDrop.config.deliver
|
18
|
+
|
18
19
|
DeliveryBoy.deliver(message, options)
|
19
|
-
rescue Kafka::Error =>
|
20
|
-
|
21
|
-
WaterDrop.logger.error e
|
22
|
-
raise e
|
23
|
-
else
|
24
|
-
WaterDrop.logger.warn "Retrying delivery after: #{e}"
|
25
|
-
retry
|
26
|
-
end
|
20
|
+
rescue Kafka::Error => error
|
21
|
+
graceful_attempt?(attempts_count, message, options, error) ? retry : raise(error)
|
27
22
|
end
|
28
23
|
end
|
29
24
|
end
|
data/lib/water_drop/version.rb
CHANGED
data/waterdrop.gemspec
CHANGED
@@ -12,15 +12,16 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.authors = ['Maciej Mensfeld']
|
13
13
|
spec.email = %w[maciej@mensfeld.pl]
|
14
14
|
spec.homepage = 'https://github.com/karafka/waterdrop'
|
15
|
-
spec.summary = '
|
15
|
+
spec.summary = 'Kafka messaging made easy!'
|
16
16
|
spec.description = spec.summary
|
17
17
|
spec.license = 'MIT'
|
18
18
|
|
19
|
-
spec.add_dependency 'delivery_boy', '>= 0.2.
|
19
|
+
spec.add_dependency 'delivery_boy', '>= 0.2.3'
|
20
20
|
spec.add_dependency 'dry-configurable', '~> 0.7'
|
21
|
+
spec.add_dependency 'dry-monitor', '~> 0.1'
|
21
22
|
spec.add_dependency 'dry-validation', '~> 0.11'
|
22
23
|
spec.add_dependency 'null-logger'
|
23
|
-
spec.add_dependency 'ruby-kafka', '>= 0.5'
|
24
|
+
spec.add_dependency 'ruby-kafka', '>= 0.5.3'
|
24
25
|
|
25
26
|
spec.required_ruby_version = '>= 2.2.0'
|
26
27
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: waterdrop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.2.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maciej Mensfeld
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: delivery_boy
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.2.
|
19
|
+
version: 0.2.3
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.2.
|
26
|
+
version: 0.2.3
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: dry-configurable
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dry-monitor
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.1'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.1'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: dry-validation
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,14 +86,14 @@ dependencies:
|
|
72
86
|
requirements:
|
73
87
|
- - ">="
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
89
|
+
version: 0.5.3
|
76
90
|
type: :runtime
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
94
|
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
96
|
+
version: 0.5.3
|
83
97
|
description: Kafka messaging made easy!
|
84
98
|
email:
|
85
99
|
- maciej@mensfeld.pl
|
@@ -103,6 +117,8 @@ files:
|
|
103
117
|
- lib/water_drop/base_producer.rb
|
104
118
|
- lib/water_drop/config.rb
|
105
119
|
- lib/water_drop/errors.rb
|
120
|
+
- lib/water_drop/instrumentation/listener.rb
|
121
|
+
- lib/water_drop/instrumentation/monitor.rb
|
106
122
|
- lib/water_drop/schemas/config.rb
|
107
123
|
- lib/water_drop/schemas/message_options.rb
|
108
124
|
- lib/water_drop/sync_producer.rb
|
@@ -124,12 +140,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
124
140
|
version: 2.2.0
|
125
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
142
|
requirements:
|
127
|
-
- - "
|
143
|
+
- - ">"
|
128
144
|
- !ruby/object:Gem::Version
|
129
|
-
version:
|
145
|
+
version: 1.3.1
|
130
146
|
requirements: []
|
131
147
|
rubyforge_project:
|
132
|
-
rubygems_version: 2.
|
148
|
+
rubygems_version: 2.7.3
|
133
149
|
signing_key:
|
134
150
|
specification_version: 4
|
135
151
|
summary: Kafka messaging made easy!
|