racecar 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dbf41d42dfa928893b72e569837c86cdab99e180a4c182c6b7ef7194553f57f5
4
- data.tar.gz: 4e67b732e59c59431c34a19d32b0a5d0ffae64a31fd858e35d2673b26c3ac192
3
+ metadata.gz: 90dddff7c52ef8440ab154be364aacd71f687e7121eaa3456e6b580c3717c294
4
+ data.tar.gz: '092eb0699d0e60537840cd0114497003ee32e18d611a5b386d430fdfeabd7e03'
5
5
  SHA512:
6
- metadata.gz: a501912a2c4f9f8d32c943b1c9516042998b241ce743449c3db48623507e360bc14af96c70a2f3b1448550de9e5e6a45d917bf31b3a2f6270f4401eed9c1d70a
7
- data.tar.gz: 8e13043d7f41ff8fcaa47d7e5b1cdd4f5a2fd75eba04579172e31dbe76c7831a0d8fc9ed1dd976baec2a8d782c6ad4656f96709d7b3161f7186004aa633a5324
6
+ metadata.gz: cd4d053961a7f228aeda34bb01e758f9caa6356cf4fb7a3e773c14b9976c19ab30587ce23a010e31b115f30d85999bb38c120e0313b99b43cc744b71f273fb3c
7
+ data.tar.gz: d0d1865ef2c7adcf94e1bf9c551d7bcdc02a223ee50fbfe4e7293b89629ca7853c55c5cfe144ce879c8aa28c3b8939dcd87fc01c54d441369cfe3c4a186643f3
@@ -0,0 +1,56 @@
1
+ version: 2.1
2
+ orbs:
3
+ ruby: circleci/ruby@0.1.2
4
+
5
+ jobs:
6
+ build:
7
+ docker:
8
+ - image: circleci/ruby:2.6.3-stretch-node
9
+ executor: ruby/default
10
+ steps:
11
+ - checkout
12
+ - run:
13
+ name: Which bundler?
14
+ command: bundle -v
15
+ - ruby/bundle-install
16
+ - run: bundle exec rspec --exclude-pattern='spec/integration/*_spec.rb'
17
+ integration-tests:
18
+ docker:
19
+ - image: circleci/ruby:2.6.3-stretch-node
20
+ - image: wurstmeister/zookeeper
21
+ - image: wurstmeister/kafka:2.11-2.0.0
22
+ environment:
23
+ KAFKA_ADVERTISED_HOST_NAME: localhost
24
+ KAFKA_ADVERTISED_PORT: 9092
25
+ KAFKA_PORT: 9092
26
+ KAFKA_ZOOKEEPER_CONNECT: localhost:2181
27
+ KAFKA_DELETE_TOPIC_ENABLE: true
28
+ - image: wurstmeister/kafka:2.11-2.0.0
29
+ environment:
30
+ KAFKA_ADVERTISED_HOST_NAME: localhost
31
+ KAFKA_ADVERTISED_PORT: 9093
32
+ KAFKA_PORT: 9093
33
+ KAFKA_ZOOKEEPER_CONNECT: localhost:2181
34
+ KAFKA_DELETE_TOPIC_ENABLE: true
35
+ - image: wurstmeister/kafka:2.11-2.0.0
36
+ environment:
37
+ KAFKA_ADVERTISED_HOST_NAME: localhost
38
+ KAFKA_ADVERTISED_PORT: 9094
39
+ KAFKA_PORT: 9094
40
+ KAFKA_ZOOKEEPER_CONNECT: localhost:2181
41
+ KAFKA_DELETE_TOPIC_ENABLE: true
42
+ executor: ruby/default
43
+ steps:
44
+ - checkout
45
+ - run:
46
+ name: Which bundler?
47
+ command: bundle -v
48
+ - ruby/bundle-install
49
+ - run: bundle exec rspec --pattern='spec/integration/*_spec.rb'
50
+
51
+ workflows:
52
+ version: 2
53
+ test:
54
+ jobs:
55
+ - build
56
+ - integration-tests
@@ -1,8 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## racecar v2.1.0
6
+
7
+ * Bump rdkafka to 0.8.0 (#191)
8
+
3
9
  ## racecar v2.0.0
4
10
 
5
- * Replace `ruby-kafka` with `rdkafka-ruby` as the low-level library underneath Racecar.
11
+ * Replace `ruby-kafka` with `rdkafka-ruby` as the low-level library underneath Racecar (#91).
6
12
  * Fix `max_wait_time` usage (#179).
7
13
  * Removed config option `sasl_over_ssl`.
8
14
  * [Racecar::Consumer] Do not pause consuming partitions on exception.
@@ -26,6 +32,8 @@
26
32
  * [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).
27
33
  * Add current directory to `$LOAD_PATH` only when `--require` option is used (#117).
28
34
  * Remove manual heartbeat support, see [Long-running message processing section in README](README.md#long-running-message-processing).
35
+ * Rescue exceptions--then log and pass to `on_error`--at the outermost level of `exe/racecar`, so that exceptions raised outside `Cli.run` are not silently discarded (#186).
36
+ * When exceptions with a `cause` are logged, recursively log the `cause` detail, separated by `--- Caused by: ---\n`.
29
37
 
30
38
  ## racecar v1.0.0
31
39
 
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in racecar.gemspec
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
 
@@ -0,0 +1,32 @@
1
+ version: '2'
2
+ services:
3
+ zookeeper:
4
+ image: confluentinc/cp-zookeeper:5.5.1
5
+ hostname: zookeeper
6
+ container_name: zookeeper
7
+ ports:
8
+ - "2181:2181"
9
+ environment:
10
+ ZOOKEEPER_CLIENT_PORT: 2181
11
+ ZOOKEEPER_TICK_TIME: 2000
12
+
13
+ broker:
14
+ image: confluentinc/cp-kafka:5.5.1
15
+ hostname: broker
16
+ container_name: broker
17
+ depends_on:
18
+ - zookeeper
19
+ ports:
20
+ - "29092:29092"
21
+ - "9092:9092"
22
+ - "9101:9101"
23
+ environment:
24
+ KAFKA_BROKER_ID: 1
25
+ KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
26
+ KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
27
+ KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker:29092,PLAINTEXT_HOST://localhost:9092
28
+ KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
29
+ KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
30
+ KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
31
+ KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
32
+ KAFKA_JMX_PORT: 9101
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class BatchConsumer < Racecar::Consumer
2
4
  subscribes_to "messages", start_from_beginning: false
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CatConsumer < Racecar::Consumer
2
4
  subscribes_to "messages", start_from_beginning: false
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ProducingConsumer < Racecar::Consumer
2
4
  subscribes_to "messages", start_from_beginning: false
3
5
 
@@ -3,19 +3,42 @@
3
3
  require "racecar"
4
4
  require "racecar/cli"
5
5
 
6
- begin
7
- Racecar::Cli.main(ARGV)
8
- rescue SignalException => e
9
- # We might receive SIGTERM before our signal handler is installed.
10
- if Signal.signame(e.signo) == "TERM"
11
- exit(0)
12
- else
13
- raise
6
+ module Racecar
7
+ class << self
8
+ def start(argv)
9
+ Cli.main(argv)
10
+ rescue SignalException => e
11
+ # We might receive SIGTERM before our signal handler is installed.
12
+ if Signal.signame(e.signo) == "TERM"
13
+ exit(0)
14
+ else
15
+ raise
16
+ end
17
+ rescue SystemExit
18
+ raise
19
+ rescue Exception => e
20
+ $stderr.puts "=> Crashed: #{exception_with_causes(e)}\n#{e.backtrace.join("\n")}"
21
+
22
+ Racecar.config.error_handler.call(e)
23
+
24
+ exit(1)
25
+ else
26
+ exit(0)
27
+ end
28
+
29
+ private
30
+
31
+ def exception_with_causes(e)
32
+ result = +"#{e.class}: #{e}"
33
+ if e.cause
34
+ result << "\n"
35
+ result << "--- Caused by: ---\n"
36
+ result << exception_with_causes(e.cause)
37
+ end
38
+ result
39
+ end
14
40
  end
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.
18
- exit(1)
19
- else
20
- exit(0)
21
41
  end
42
+
43
+ # Start your engines!
44
+ Racecar.start(ARGV)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # only needed when ruby < 2.4 and not using active support
2
4
 
3
5
  unless {}.respond_to? :compact
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Racecar
2
4
  module Generators
3
5
  class ConsumerGenerator < Rails::Generators::NamedBase
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Racecar
2
4
  module Generators
3
5
  class InstallGenerator < Rails::Generators::Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "logger"
2
4
 
3
5
  require "racecar/instrumenter"
@@ -6,6 +8,7 @@ require "racecar/consumer"
6
8
  require "racecar/consumer_set"
7
9
  require "racecar/runner"
8
10
  require "racecar/config"
11
+ require "racecar/version"
9
12
  require "ensure_hash_compact"
10
13
 
11
14
  module Racecar
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "optparse"
2
4
  require "logger"
3
5
  require "fileutils"
@@ -6,8 +8,10 @@ require "racecar/daemon"
6
8
 
7
9
  module Racecar
8
10
  class Cli
9
- def self.main(args)
10
- new(args).run
11
+ class << self
12
+ def main(args)
13
+ new(args).run
14
+ end
11
15
  end
12
16
 
13
17
  def initialize(args)
@@ -16,10 +20,6 @@ module Racecar
16
20
  @consumer_name = args.first or raise Racecar::Error, "no consumer specified"
17
21
  end
18
22
 
19
- def config
20
- Racecar.config
21
- end
22
-
23
23
  def run
24
24
  $stderr.puts "=> Starting Racecar consumer #{consumer_name}..."
25
25
 
@@ -61,18 +61,16 @@ module Racecar
61
61
  processor = consumer_class.new
62
62
 
63
63
  Racecar.run(processor)
64
- rescue => e
65
- $stderr.puts "=> Crashed: #{e.class}: #{e}\n#{e.backtrace.join("\n")}"
66
-
67
- config.error_handler.call(e)
68
-
69
- raise
70
64
  end
71
65
 
72
66
  private
73
67
 
74
68
  attr_reader :consumer_name
75
69
 
70
+ def config
71
+ Racecar.config
72
+ end
73
+
76
74
  def daemonize!
77
75
  daemon = Daemon.new(File.expand_path(config.pidfile))
78
76
 
@@ -102,12 +100,7 @@ module Racecar
102
100
  opts.on("-r", "--require STRING", "Require a library before starting the consumer") do |lib|
103
101
  $LOAD_PATH.unshift(Dir.pwd) unless load_path_modified
104
102
  load_path_modified = true
105
- begin
106
- require lib
107
- rescue => e
108
- $stderr.puts "=> #{lib} failed to load: #{e.message}"
109
- exit
110
- end
103
+ require lib
111
104
  end
112
105
 
113
106
  opts.on("-l", "--log STRING", "Log to the specified file") do |logfile|
@@ -115,13 +108,13 @@ module Racecar
115
108
  end
116
109
 
117
110
  Racecar::Config.variables.each do |variable|
118
- opt_name = "--" << variable.name.to_s.gsub("_", "-")
111
+ opt_name = +"--#{variable.name.to_s.gsub('_', '-')}"
119
112
  opt_name << " #{variable.type.upcase}" unless variable.boolean?
120
113
 
121
114
  desc = variable.description || "N/A"
122
115
 
123
116
  if variable.default
124
- desc << " (default: #{variable.default.inspect})"
117
+ desc += " (default: #{variable.default.inspect})"
125
118
  end
126
119
 
127
120
  opts.on(opt_name, desc) do |value|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "king_konf"
2
4
 
3
5
  module Racecar
@@ -196,8 +198,8 @@ module Racecar
196
198
  group_id_prefix,
197
199
 
198
200
  # MyFunnyConsumer => my-funny-consumer
199
- consumer_class.name.gsub(/[a-z][A-Z]/) {|str| str[0] << "-" << str[1] }.downcase,
200
- ].compact.join("")
201
+ consumer_class.name.gsub(/[a-z][A-Z]/) { |str| "#{str[0]}-#{str[1]}" }.downcase,
202
+ ].compact.join
201
203
 
202
204
  self.subscriptions = consumer_class.subscriptions
203
205
  self.max_wait_time = consumer_class.max_wait_time || self.max_wait_time
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Racecar
2
4
  class Consumer
3
5
  Subscription = Struct.new(:topic, :start_from_beginning, :max_bytes_per_partition, :additional_config)
@@ -54,7 +56,7 @@ module Racecar
54
56
  protected
55
57
 
56
58
  # https://github.com/appsignal/rdkafka-ruby#producing-messages
57
- def produce(payload, topic:, key:, partition_key: nil, headers: nil, create_time: nil)
59
+ def produce(payload, topic:, key: nil, partition_key: nil, headers: nil, create_time: nil)
58
60
  @delivery_handles ||= []
59
61
  message_size = payload.respond_to?(:bytesize) ? payload.bytesize : 0
60
62
  instrumentation_payload = {
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Racecar
2
4
  class ConsumerSet
3
5
  MAX_POLL_TRIES = 10
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "optparse"
2
4
  require "racecar/rails_config_file_loader"
3
5
  require "racecar/daemon"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Racecar
2
4
  class Daemon
3
5
  attr_reader :pidfile
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require "datadog/statsd"
3
5
  rescue LoadError
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Racecar
2
4
  ##
3
5
  # Common API for instrumentation to standardize
@@ -11,6 +13,8 @@ module Racecar
11
13
  @default_payload = default_payload
12
14
 
13
15
  @backend = if defined?(ActiveSupport::Notifications)
16
+ # ActiveSupport needs `concurrent-ruby` but doesn't `require` it.
17
+ require 'concurrent/utility/monotonic_time'
14
18
  ActiveSupport::Notifications
15
19
  else
16
20
  NullInstrumenter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "forwardable"
2
4
 
3
5
  module Racecar
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Racecar
2
4
  # Ignores all instrumentation events.
3
5
  class NullInstrumenter
@@ -1,8 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Racecar
2
4
  class Pause
5
+ attr_reader :pauses_count
6
+
3
7
  def initialize(timeout: nil, max_timeout: nil, exponential_backoff: false)
4
8
  @started_at = nil
5
- @pauses = 0
9
+ @pauses_count = 0
6
10
  @timeout = timeout
7
11
  @max_timeout = max_timeout
8
12
  @exponential_backoff = exponential_backoff
@@ -11,7 +15,7 @@ module Racecar
11
15
  def pause!
12
16
  @started_at = Time.now
13
17
  @ends_at = @started_at + backoff_interval unless @timeout.nil?
14
- @pauses += 1
18
+ @pauses_count += 1
15
19
  end
16
20
 
17
21
  def resume!
@@ -38,13 +42,13 @@ module Racecar
38
42
  end
39
43
 
40
44
  def reset!
41
- @pauses = 0
45
+ @pauses_count = 0
42
46
  end
43
47
 
44
48
  def backoff_interval
45
49
  return Float::INFINITY if @timeout.nil?
46
50
 
47
- backoff_factor = @exponential_backoff ? 2**@pauses : 1
51
+ backoff_factor = @exponential_backoff ? 2**@pauses_count : 1
48
52
  timeout = backoff_factor * @timeout
49
53
 
50
54
  timeout = @max_timeout if @max_timeout && timeout > @max_timeout
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Racecar
2
4
  module RailsConfigFileLoader
3
5
  def self.load!
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rdkafka"
2
4
  require "racecar/pause"
3
5
  require "racecar/message"
@@ -166,7 +168,7 @@ module Racecar
166
168
  }
167
169
 
168
170
  @instrumenter.instrument("start_process_message", instrumentation_payload)
169
- with_pause(message.topic, message.partition, message.offset..message.offset) do
171
+ with_pause(message.topic, message.partition, message.offset..message.offset) do |pause|
170
172
  begin
171
173
  @instrumenter.instrument("process_message", instrumentation_payload) do
172
174
  processor.process(Racecar::Message.new(message))
@@ -174,6 +176,7 @@ module Racecar
174
176
  consumer.store_offset(message)
175
177
  end
176
178
  rescue => e
179
+ instrumentation_payload[:retries_count] = pause.pauses_count
177
180
  config.error_handler.call(e, instrumentation_payload)
178
181
  raise e
179
182
  end
@@ -194,12 +197,13 @@ module Racecar
194
197
 
195
198
  @instrumenter.instrument("start_process_batch", instrumentation_payload)
196
199
  @instrumenter.instrument("process_batch", instrumentation_payload) do
197
- with_pause(first.topic, first.partition, first.offset..last.offset) do
200
+ with_pause(first.topic, first.partition, first.offset..last.offset) do |pause|
198
201
  begin
199
202
  processor.process_batch(messages.map {|message| Racecar::Message.new(message) })
200
203
  processor.deliver!
201
204
  consumer.store_offset(messages.last)
202
205
  rescue => e
206
+ instrumentation_payload[:retries_count] = pause.pauses_count
203
207
  config.error_handler.call(e, instrumentation_payload)
204
208
  raise e
205
209
  end
@@ -208,17 +212,17 @@ module Racecar
208
212
  end
209
213
 
210
214
  def with_pause(topic, partition, offsets)
211
- return yield if config.pause_timeout == 0
215
+ pause = pauses[topic][partition]
216
+ return yield pause if config.pause_timeout == 0
212
217
 
213
218
  begin
214
- yield
219
+ yield pause
215
220
  # We've successfully processed a batch from the partition, so we can clear the pause.
216
221
  pauses[topic][partition].reset!
217
222
  rescue => e
218
223
  desc = "#{topic}/#{partition}"
219
224
  logger.error "Failed to process #{desc} at #{offsets}: #{e}"
220
225
 
221
- pause = pauses[topic][partition]
222
226
  logger.warn "Pausing partition #{desc} for #{pause.backoff_interval} seconds"
223
227
  consumer.pause(topic, partition, offsets.first)
224
228
  pause.pause!
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Racecar
2
- VERSION = "2.0.0"
4
+ VERSION = "2.1.0"
3
5
  end
@@ -21,9 +21,10 @@ 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.8.0.beta.1"
24
+ spec.add_runtime_dependency "rdkafka", "~> 0.8.0"
25
25
 
26
26
  spec.add_development_dependency "bundler", [">= 1.13", "< 3"]
27
+ spec.add_development_dependency "pry"
27
28
  spec.add_development_dependency "rake", "> 10.0"
28
29
  spec.add_development_dependency "rspec", "~> 3.0"
29
30
  spec.add_development_dependency "timecop"
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
4
+ version: 2.1.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-08-24 00:00:00.000000000 Z
12
+ date: 2020-09-30 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.8.0.beta.1
34
+ version: 0.8.0
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.8.0.beta.1
41
+ version: 0.8.0
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: bundler
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -59,6 +59,20 @@ dependencies:
59
59
  - - "<"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '3'
62
+ - !ruby/object:Gem::Dependency
63
+ name: pry
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
62
76
  - !ruby/object:Gem::Dependency
63
77
  name: rake
64
78
  requirement: !ruby/object:Gem::Requirement
@@ -141,7 +155,7 @@ dependencies:
141
155
  - - "<"
142
156
  - !ruby/object:Gem::Version
143
157
  version: '6.1'
144
- description:
158
+ description:
145
159
  email:
146
160
  - dschierbeck@zendesk.com
147
161
  - bquorning@zendesk.com
@@ -151,6 +165,7 @@ executables:
151
165
  extensions: []
152
166
  extra_rdoc_files: []
153
167
  files:
168
+ - ".circleci/config.yml"
154
169
  - ".github/workflows/rspec.yml"
155
170
  - ".gitignore"
156
171
  - ".rspec"
@@ -162,6 +177,7 @@ files:
162
177
  - Rakefile
163
178
  - bin/console
164
179
  - bin/setup
180
+ - docker-compose.yml
165
181
  - examples/batch_consumer.rb
166
182
  - examples/cat_consumer.rb
167
183
  - examples/producing_consumer.rb
@@ -192,7 +208,7 @@ homepage: https://github.com/zendesk/racecar
192
208
  licenses:
193
209
  - Apache License Version 2.0
194
210
  metadata: {}
195
- post_install_message:
211
+ post_install_message:
196
212
  rdoc_options: []
197
213
  require_paths:
198
214
  - lib
@@ -208,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
208
224
  version: '0'
209
225
  requirements: []
210
226
  rubygems_version: 3.1.2
211
- signing_key:
227
+ signing_key:
212
228
  specification_version: 4
213
229
  summary: A framework for running Kafka consumers
214
230
  test_files: []