racecar 2.0.0.beta2 → 2.0.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: 40511d6f40dafe30b33700935c54aea628eecdeae41fa4c1f25c1af26a9f398c
4
- data.tar.gz: 41d62e586808c359db8761b872fe8c2ddbfd116b10e703c347b4b4452bdaea57
3
+ metadata.gz: dbf41d42dfa928893b72e569837c86cdab99e180a4c182c6b7ef7194553f57f5
4
+ data.tar.gz: 4e67b732e59c59431c34a19d32b0a5d0ffae64a31fd858e35d2673b26c3ac192
5
5
  SHA512:
6
- metadata.gz: 92479e9d06a5c724041fc1b6556a329eadca406f909c767e9aa1f3f09f42470b9e67d2444ec9aa019459ed325d516d59f84772b49cf26fceded1c157e5937edf
7
- data.tar.gz: e6f60c739ad0cd1db7d833fd32dd7df2537a26830b8d87ac19382aa2bc2d98f1289fe07544159d35d6cdd3dd586a80397068256a36ad5228a3bdd4b76ca143c8
6
+ metadata.gz: a501912a2c4f9f8d32c943b1c9516042998b241ce743449c3db48623507e360bc14af96c70a2f3b1448550de9e5e6a45d917bf31b3a2f6270f4401eed9c1d70a
7
+ data.tar.gz: 8e13043d7f41ff8fcaa47d7e5b1cdd4f5a2fd75eba04579172e31dbe76c7831a0d8fc9ed1dd976baec2a8d782c6ad4656f96709d7b3161f7186004aa633a5324
@@ -2,29 +2,30 @@
2
2
 
3
3
  ## racecar v2.0.0
4
4
 
5
- * Replace `ruby-kafka` with `rdkafka-ruby`
6
- * Removed config option `sasl_over_ssl`
7
- * [Racecar::Consumer] Do not pause consuming partitions on exception
8
- * [Racecar::Consumer] `topic`, `payload` and `key` are mandadory to method `produce`
9
- * [Racecar::Consumer] `process_batch` retrieves an array of messages instead of batch object
10
- * [Racecar::Consumer] Remove `offset_retention_time`
11
- * [Racecar::Consumer] Allow providing `additional_config` for subscriptions
12
- * [Racecar::Consumer] Provide access to `producer` and `consumer`
13
- * [Racecar::Consumer] Enforce delivering messages with method `deliver!`
14
- * [Racecar::Consumer] instead of raising when a partition EOF is reached, the result can be queried through `consumer.last_poll_read_partition_eof?`
15
- * [Racecar::Config] Remove `offset_retention_time`, `connect_timeout` and `offset_commit_threshold`
16
- * [Racecar::Config] Pass config to `rdkafka-ruby` via `producer` and `consumer`
17
- * [Racecar::Config] Replace `max_fetch_queue_size` with `min_message_queue_size`
18
- * [Racecar::Config] Add `synchronous_commits` to control blocking of `consumer.commit` (default `false`)
19
- * [Racecar::Config] Add `security_protocol` to control protocol between client and broker
20
- * [Racecar::Config] SSL configuration via `ssl_ca_location`, `ssl_crl_location`, `ssl_keystore_location` and `ssl_keystore_password`
21
- * [Racecar::Config] SASL configuration via `sasl_mechanism`, `sasl_kerberos_service_name`, `sasl_kerberos_principal`, `sasl_kerberos_kinit_cmd`, `sasl_kerberos_keytab`, `sasl_kerberos_min_time_before_relogin`, `sasl_username` and `sasl_password`
5
+ * Replace `ruby-kafka` with `rdkafka-ruby` as the low-level library underneath Racecar.
6
+ * Fix `max_wait_time` usage (#179).
7
+ * Removed config option `sasl_over_ssl`.
8
+ * [Racecar::Consumer] Do not pause consuming partitions on exception.
9
+ * [Racecar::Consumer] `topic`, `payload` and `key` are mandadory to method `produce`.
10
+ * [Racecar::Consumer] `process_batch` retrieves an array of messages instead of batch object.
11
+ * [Racecar::Consumer] Remove `offset_retention_time`.
12
+ * [Racecar::Consumer] Allow providing `additional_config` for subscriptions.
13
+ * [Racecar::Consumer] Provide access to `producer` and `consumer`.
14
+ * [Racecar::Consumer] Enforce delivering messages with method `deliver!`.
15
+ * [Racecar::Consumer] instead of raising when a partition EOF is reached, the result can be queried through `consumer.last_poll_read_partition_eof?`.
16
+ * [Racecar::Config] Remove `offset_retention_time`, `connect_timeout` and `offset_commit_threshold`.
17
+ * [Racecar::Config] Pass config to `rdkafka-ruby` via `producer` and `consumer`.
18
+ * [Racecar::Config] Replace `max_fetch_queue_size` with `min_message_queue_size`.
19
+ * [Racecar::Config] Add `synchronous_commits` to control blocking of `consumer.commit` (default `false`).
20
+ * [Racecar::Config] Add `security_protocol` to control protocol between client and broker.
21
+ * [Racecar::Config] SSL configuration via `ssl_ca_location`, `ssl_crl_location`, `ssl_keystore_location` and `ssl_keystore_password`.
22
+ * [Racecar::Config] SASL configuration via `sasl_mechanism`, `sasl_kerberos_service_name`, `sasl_kerberos_principal`, `sasl_kerberos_kinit_cmd`, `sasl_kerberos_keytab`, `sasl_kerberos_min_time_before_relogin`, `sasl_username` and `sasl_password`.
22
23
  * [Instrumentation] `produce_message.racecar` sent whenever a produced message is queued. Payload includes `topic`, `key`, `value` and `create_time`.
23
24
  * [Instrumentation] `acknowledged_message.racecar` send whenever a produced message was successfully received by Kafka. Payload includes `offset` and `partition`, but no message details.
24
- * [Instrumentation] `rdkafka-ruby` does not yet provide instrumentation [rdkafka-ruby#54](https://github.com/appsignal/rdkafka-ruby/issues/54)
25
- * [Instrumentation] if processors define a `statistics_callback`, it will be called once every second for every subscription or producer connection. The first argument will be a Hash, for contents see [librdkafka STATISTICS.md](https://github.com/edenhill/librdkafka/blob/master/STATISTICS.md)
25
+ * [Instrumentation] `rdkafka-ruby` does not yet provide instrumentation [rdkafka-ruby#54](https://github.com/appsignal/rdkafka-ruby/issues/54).
26
+ * [Instrumentation] if processors define a `statistics_callback`, it will be called once every second for every subscription or producer connection. The first argument will be a Hash, for contents see [librdkafka STATISTICS.md](https://github.com/edenhill/librdkafka/blob/master/STATISTICS.md).
26
27
  * Add current directory to `$LOAD_PATH` only when `--require` option is used (#117).
27
- * Remove manual heartbeat support, see [Long-running message processing section in README](README.md#long-running-message-processing)
28
+ * Remove manual heartbeat support, see [Long-running message processing section in README](README.md#long-running-message-processing).
28
29
 
29
30
  ## racecar v1.0.0
30
31
 
data/README.md CHANGED
@@ -1,5 +1,3 @@
1
- **IMPORTANT:** The `master` branch is unstable, working towards a v2 release that breaks a lot of stuff. Use the `v1-stable` branch if you want to suggest changes.
2
-
3
1
  # Racecar
4
2
 
5
3
  Racecar is a friendly and easy-to-approach Kafka consumer framework. It allows you to write small applications that process messages stored in Kafka topics while optionally integrating with your Rails models.
@@ -21,6 +19,7 @@ The framework is based on [rdkafka-ruby](https://github.com/appsignal/rdkafka-ru
21
19
  7. [Handling errors](#handling-errors)
22
20
  8. [Logging](#logging)
23
21
  9. [Operations](#operations)
22
+ 10. [Upgrading from v1 to v2](#upgrading-from-v1-to-v2)
24
23
  3. [Development](#development)
25
24
  4. [Contributing](#contributing)
26
25
  5. [Support and Discussion](#support-and-discussion)
@@ -288,6 +287,9 @@ The memory usage limit is roughly estimated as `max_bytes * min_message_queue_si
288
287
  * `ssl_crl_location` – Path to CRL for verifying broker's certificate validity
289
288
  * `ssl_keystore_location` – Path to client's keystore (PKCS#12) used for authentication
290
289
  * `ssl_keystore_password` – Client's keystore (PKCS#12) password
290
+ * `ssl_certificate_location` – Path to the certificate
291
+ * `ssl_key_location` – Path to client's certificate used for authentication
292
+ * `ssl_key_password` – Client's certificate password
291
293
 
292
294
  #### SASL encryption, authentication & authorization
293
295
 
@@ -464,7 +466,7 @@ Racecar.config.on_error do |exception, info|
464
466
  end
465
467
  ```
466
468
 
467
- It is highly recommended that you set up an error handler.
469
+ It is highly recommended that you set up an error handler. Please note that the `info` object contains different keys and values depending on whether you are using `process` or `process_batch`. See the `instrumentation_payload` object in the `process` and `process_batch` methods in the `Runner` class for the complete list.
468
470
 
469
471
 
470
472
  ### Logging
@@ -481,6 +483,11 @@ In order to gracefully shut down a Racecar consumer process, send it the `SIGTER
481
483
  In order to introspect the configuration of a consumer process, send it the `SIGUSR1` signal. This will make Racecar print its configuration to the standard error file descriptor associated with the consumer process, so you'll need to know where that is written to.
482
484
 
483
485
 
486
+ ### Upgrading from v1 to v2
487
+
488
+ In order to safely upgrade from Racecar v1 to v2, you need to completely shut down your consumer group before starting it up again with the v2 Racecar dependency. In general, you should avoid rolling deploys for consumers groups, so it is likely the case that this will just work for you, but it's a good idea to check first.
489
+
490
+
484
491
  ## Development
485
492
 
486
493
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -13,6 +13,8 @@ rescue SignalException => e
13
13
  raise
14
14
  end
15
15
  rescue
16
+ # Exceptions are printed to STDERR and sent to the error handler
17
+ # in `Racecar::Cli#run`, so we don't need to do anything here.
16
18
  exit(1)
17
19
  else
18
20
  exit(0)
@@ -102,7 +102,12 @@ module Racecar
102
102
  opts.on("-r", "--require STRING", "Require a library before starting the consumer") do |lib|
103
103
  $LOAD_PATH.unshift(Dir.pwd) unless load_path_modified
104
104
  load_path_modified = true
105
- require lib
105
+ begin
106
+ require lib
107
+ rescue => e
108
+ $stderr.puts "=> #{lib} failed to load: #{e.message}"
109
+ exit
110
+ end
106
111
  end
107
112
 
108
113
  opts.on("-l", "--log STRING", "Log to the specified file") do |logfile|
@@ -28,6 +28,9 @@ module Racecar
28
28
  desc "The maxium number of messages that get consumed within one batch"
29
29
  integer :fetch_messages, default: 1000
30
30
 
31
+ desc "Minimum number of bytes the broker responds with"
32
+ integer :fetch_min_bytes, default: 1
33
+
31
34
  desc "Automatically store offset of last message provided to application"
32
35
  boolean :synchronous_commits, default: false
33
36
 
@@ -82,6 +85,15 @@ module Racecar
82
85
  desc "Client's keystore (PKCS#12) password"
83
86
  string :ssl_keystore_password
84
87
 
88
+ desc "Path to the certificate used for authentication"
89
+ string :ssl_certificate_location
90
+
91
+ desc "Path to client's certificate used for authentication"
92
+ string :ssl_key_location
93
+
94
+ desc "Client's certificate password"
95
+ string :ssl_key_password
96
+
85
97
  desc "SASL mechanism to use for authentication"
86
98
  string :sasl_mechanism, allowed_values: %w{GSSAPI PLAIN SCRAM-SHA-256 SCRAM-SHA-512}
87
99
 
@@ -144,6 +156,10 @@ module Racecar
144
156
 
145
157
  attr_accessor :subscriptions, :logger
146
158
 
159
+ def max_wait_time_ms
160
+ max_wait_time * 1000
161
+ end
162
+
147
163
  def initialize(env: ENV)
148
164
  super(env: env)
149
165
  @error_handler = proc {}
@@ -217,6 +233,9 @@ module Racecar
217
233
  "ssl.crl.location" => ssl_crl_location,
218
234
  "ssl.keystore.location" => ssl_keystore_location,
219
235
  "ssl.keystore.password" => ssl_keystore_password,
236
+ "ssl.certificate.location" => ssl_certificate_location,
237
+ "ssl.key.location" => ssl_key_location,
238
+ "ssl.key.password" => ssl_key_password,
220
239
  "sasl.mechanism" => sasl_mechanism,
221
240
  "sasl.kerberos.service.name" => sasl_kerberos_service_name,
222
241
  "sasl.kerberos.principal" => sasl_kerberos_principal,
@@ -54,21 +54,29 @@ module Racecar
54
54
  protected
55
55
 
56
56
  # https://github.com/appsignal/rdkafka-ruby#producing-messages
57
- def produce(payload, topic:, key:, headers: nil, create_time: nil)
57
+ def produce(payload, topic:, key:, partition_key: nil, headers: nil, create_time: nil)
58
58
  @delivery_handles ||= []
59
59
  message_size = payload.respond_to?(:bytesize) ? payload.bytesize : 0
60
60
  instrumentation_payload = {
61
- value: payload,
62
- headers: headers,
63
- key: key,
64
- topic: topic,
61
+ value: payload,
62
+ headers: headers,
63
+ key: key,
64
+ partition_key: partition_key,
65
+ topic: topic,
65
66
  message_size: message_size,
66
- create_time: Time.now,
67
- buffer_size: @delivery_handles.size
67
+ create_time: Time.now,
68
+ buffer_size: @delivery_handles.size,
68
69
  }
69
70
 
70
71
  @instrumenter.instrument("produce_message", instrumentation_payload) do
71
- @delivery_handles << @producer.produce(topic: topic, payload: payload, key: key, timestamp: create_time, headers: headers)
72
+ @delivery_handles << @producer.produce(
73
+ topic: topic,
74
+ payload: payload,
75
+ key: key,
76
+ partition_key: partition_key,
77
+ timestamp: create_time,
78
+ headers: headers,
79
+ )
72
80
  end
73
81
  end
74
82
 
@@ -174,8 +174,9 @@ module Racecar
174
174
  "client.id" => @config.client_id,
175
175
  "enable.partition.eof" => false,
176
176
  "fetch.max.bytes" => @config.max_bytes,
177
- "fetch.message.max.bytes" => subscription.max_bytes_per_partition,
178
- "fetch.wait.max.ms" => @config.max_wait_time * 1000,
177
+ "message.max.bytes" => subscription.max_bytes_per_partition,
178
+ "fetch.min.bytes" => @config.fetch_min_bytes,
179
+ "fetch.wait.max.ms" => @config.max_wait_time_ms,
179
180
  "group.id" => @config.group_id,
180
181
  "heartbeat.interval.ms" => @config.heartbeat_interval * 1000,
181
182
  "max.poll.interval.ms" => @config.max_poll_interval * 1000,
@@ -26,7 +26,7 @@ module Racecar
26
26
  end
27
27
 
28
28
  def host
29
- @host ||= default_host
29
+ @host
30
30
  end
31
31
 
32
32
  def host=(host)
@@ -35,7 +35,7 @@ module Racecar
35
35
  end
36
36
 
37
37
  def port
38
- @port ||= default_port
38
+ @port
39
39
  end
40
40
 
41
41
  def port=(port)
@@ -63,22 +63,6 @@ module Racecar
63
63
 
64
64
  private
65
65
 
66
- def default_host
67
- if ::Datadog::Statsd.const_defined?(:Connection)
68
- ::Datadog::Statsd::Connection::DEFAULT_HOST
69
- else
70
- ::Datadog::Statsd::DEFAULT_HOST
71
- end
72
- end
73
-
74
- def default_port
75
- if ::Datadog::Statsd.const_defined?(:Connection)
76
- ::Datadog::Statsd::Connection::DEFAULT_PORT
77
- else
78
- ::Datadog::Statsd::DEFAULT_PORT
79
- end
80
- end
81
-
82
66
  def clear
83
67
  @statsd && @statsd.close
84
68
  @statsd = nil
@@ -126,6 +110,8 @@ module Racecar
126
110
  def process_batch(event)
127
111
  offset = event.payload.fetch(:last_offset)
128
112
  messages = event.payload.fetch(:message_count)
113
+ last_create_time = event.payload.fetch(:last_create_time)
114
+ time_lag = last_create_time && ((Time.now - last_create_time) * 1000).to_i
129
115
  tags = default_tags(event)
130
116
 
131
117
  if event.payload.key?(:exception)
@@ -135,7 +121,12 @@ module Racecar
135
121
  count("consumer.messages", messages, tags: tags)
136
122
  end
137
123
 
124
+ histogram("consumer.batch_size", messages, tags: tags)
138
125
  gauge("consumer.offset", offset, tags: tags)
126
+
127
+ if time_lag
128
+ gauge("consumer.time_lag", time_lag, tags: tags)
129
+ end
139
130
  end
140
131
 
141
132
  def join_group(event)
@@ -239,7 +230,7 @@ module Racecar
239
230
  increment("producer.ack.messages", tags: tags)
240
231
  end
241
232
 
242
- attach_to "producer.racecar"
233
+ attach_to "racecar"
243
234
  end
244
235
  end
245
236
  end
@@ -65,12 +65,12 @@ module Racecar
65
65
  @instrumenter.instrument("main_loop", instrumentation_payload) do
66
66
  case process_method
67
67
  when :batch then
68
- msg_per_part = consumer.batch_poll(config.max_wait_time).group_by(&:partition)
68
+ msg_per_part = consumer.batch_poll(config.max_wait_time_ms).group_by(&:partition)
69
69
  msg_per_part.each_value do |messages|
70
70
  process_batch(messages)
71
71
  end
72
72
  when :single then
73
- message = consumer.poll(config.max_wait_time)
73
+ message = consumer.poll(config.max_wait_time_ms)
74
74
  process(message) if message
75
75
  end
76
76
  end
@@ -166,11 +166,16 @@ module Racecar
166
166
  }
167
167
 
168
168
  @instrumenter.instrument("start_process_message", instrumentation_payload)
169
- @instrumenter.instrument("process_message", instrumentation_payload) do
170
- with_pause(message.topic, message.partition, message.offset..message.offset) do
171
- processor.process(Racecar::Message.new(message))
172
- processor.deliver!
173
- consumer.store_offset(message)
169
+ with_pause(message.topic, message.partition, message.offset..message.offset) do
170
+ begin
171
+ @instrumenter.instrument("process_message", instrumentation_payload) do
172
+ processor.process(Racecar::Message.new(message))
173
+ processor.deliver!
174
+ consumer.store_offset(message)
175
+ end
176
+ rescue => e
177
+ config.error_handler.call(e, instrumentation_payload)
178
+ raise e
174
179
  end
175
180
  end
176
181
  end
@@ -183,15 +188,21 @@ module Racecar
183
188
  partition: first.partition,
184
189
  first_offset: first.offset,
185
190
  last_offset: last.offset,
191
+ last_create_time: last.timestamp,
186
192
  message_count: messages.size
187
193
  }
188
194
 
189
195
  @instrumenter.instrument("start_process_batch", instrumentation_payload)
190
196
  @instrumenter.instrument("process_batch", instrumentation_payload) do
191
197
  with_pause(first.topic, first.partition, first.offset..last.offset) do
192
- processor.process_batch(messages.map {|message| Racecar::Message.new(message) })
193
- processor.deliver!
194
- consumer.store_offset(messages.last)
198
+ begin
199
+ processor.process_batch(messages.map {|message| Racecar::Message.new(message) })
200
+ processor.deliver!
201
+ consumer.store_offset(messages.last)
202
+ rescue => e
203
+ config.error_handler.call(e, instrumentation_payload)
204
+ raise e
205
+ end
195
206
  end
196
207
  end
197
208
  end
@@ -1,3 +1,3 @@
1
1
  module Racecar
2
- VERSION = "2.0.0.beta2"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -21,12 +21,12 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ["lib"]
22
22
 
23
23
  spec.add_runtime_dependency "king_konf", "~> 0.3.7"
24
- spec.add_runtime_dependency "rdkafka", "~> 0.6.0"
24
+ spec.add_runtime_dependency "rdkafka", "~> 0.8.0.beta.1"
25
25
 
26
26
  spec.add_development_dependency "bundler", [">= 1.13", "< 3"]
27
27
  spec.add_development_dependency "rake", "> 10.0"
28
28
  spec.add_development_dependency "rspec", "~> 3.0"
29
29
  spec.add_development_dependency "timecop"
30
- spec.add_development_dependency "dogstatsd-ruby", ">= 3.0.0", "< 5.0.0"
30
+ spec.add_development_dependency "dogstatsd-ruby", ">= 4.0.0", "< 5.0.0"
31
31
  spec.add_development_dependency "activesupport", ">= 4.0", "< 6.1"
32
32
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: racecar
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta2
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Schierbeck
8
8
  - Benjamin Quorning
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-02-05 00:00:00.000000000 Z
12
+ date: 2020-08-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: king_konf
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: 0.6.0
34
+ version: 0.8.0.beta.1
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: 0.6.0
41
+ version: 0.8.0.beta.1
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: bundler
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -107,7 +107,7 @@ dependencies:
107
107
  requirements:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: 3.0.0
110
+ version: 4.0.0
111
111
  - - "<"
112
112
  - !ruby/object:Gem::Version
113
113
  version: 5.0.0
@@ -117,7 +117,7 @@ dependencies:
117
117
  requirements:
118
118
  - - ">="
119
119
  - !ruby/object:Gem::Version
120
- version: 3.0.0
120
+ version: 4.0.0
121
121
  - - "<"
122
122
  - !ruby/object:Gem::Version
123
123
  version: 5.0.0
@@ -141,7 +141,7 @@ dependencies:
141
141
  - - "<"
142
142
  - !ruby/object:Gem::Version
143
143
  version: '6.1'
144
- description:
144
+ description:
145
145
  email:
146
146
  - dschierbeck@zendesk.com
147
147
  - bquorning@zendesk.com
@@ -192,7 +192,7 @@ homepage: https://github.com/zendesk/racecar
192
192
  licenses:
193
193
  - Apache License Version 2.0
194
194
  metadata: {}
195
- post_install_message:
195
+ post_install_message:
196
196
  rdoc_options: []
197
197
  require_paths:
198
198
  - lib
@@ -203,13 +203,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
203
203
  version: '0'
204
204
  required_rubygems_version: !ruby/object:Gem::Requirement
205
205
  requirements:
206
- - - ">"
206
+ - - ">="
207
207
  - !ruby/object:Gem::Version
208
- version: 1.3.1
208
+ version: '0'
209
209
  requirements: []
210
- rubyforge_project:
211
- rubygems_version: 2.7.6
212
- signing_key:
210
+ rubygems_version: 3.1.2
211
+ signing_key:
213
212
  specification_version: 4
214
213
  summary: A framework for running Kafka consumers
215
214
  test_files: []