phobos 1.8.1 → 1.8.2.pre.beta1

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: 2521d4d12e282bf2f2fc1ae720c52cfdab4637e2464840e196c7fd275f316c9d
4
- data.tar.gz: 067d38a797a93bd7300e31c34b16e2bdea1dfd43ff6eddaaeac678b33ce9944c
3
+ metadata.gz: 6610d5e383b53c4d2f926b4ab10ae33c260215fe2de0520132fa38e6b51089d8
4
+ data.tar.gz: '0791b9c0fc4d4b10f878607bddc1374c359bbe627386375ce48ea3ff6996329d'
5
5
  SHA512:
6
- metadata.gz: a2808ac665d54a407da693e3ff0c8635ce0ef0daaf9815acf22c47628f268866cb350925a77477631f338cff360f79cc4e55b113a83c66e582333698bc19c800
7
- data.tar.gz: 896136ecf3e4e41eb255c043b3982c55eb008a057ea97b47082b44826f2c59c8c525255f2fa3b9f2271df3e494dcc826d17c1136d7308c10b43bc63291fa4121
6
+ metadata.gz: dc15fe9776e8aff478e3263a9d8d16b9d693baff6259ae62bdbf1e229b7f8c8bfb345fdf7b9603583ca5405642e1424461c2523ef4bdbcd9b85bd80140a03e6d
7
+ data.tar.gz: 782ca0a9838cf38a6ae37c92b33d3ce2f4692438a837aeeefabbea629dd6d5b6c595a6cdc7932e804882d29854784583d356574f8adfaa25613fe093e42cf10c
@@ -11,7 +11,7 @@ services:
11
11
  env:
12
12
  global:
13
13
  - DEFAULT_TIMEOUT=20
14
- - CC_TEST_REPORTER_ID=ce08ec7297e0161c25b6b0c86e7bd4b9eb85b15de9e2a17fe419b8439aa40def
14
+ - CC_TEST_REPORTER_ID=a990fd40ff4421e8b28167232242a1d6c6638f9907fc0b80eb90f82f88fcfd81
15
15
 
16
16
  before_install:
17
17
  - env
@@ -4,7 +4,10 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
- ## UNRELEASED
7
+ ## [1.8.2-beta1] - 2019-03-13
8
+
9
+ - Added `BatchHandler` to consume messages in batches on the business
10
+ layer.
8
11
 
9
12
  ## [1.8.1] - 2018-11-23
10
13
  ### Added
data/README.md CHANGED
@@ -1,10 +1,8 @@
1
1
  ![Phobos](https://raw.githubusercontent.com/klarna/phobos/master/logo.png)
2
2
 
3
- [![Build Status](https://travis-ci.org/klarna/phobos.svg?branch=master)](https://travis-ci.org/klarna/phobos)
4
- [![Maintainability](https://api.codeclimate.com/v1/badges/2d00845fc6e7e83df6e7/maintainability)](https://codeclimate.com/github/klarna/phobos/maintainability)
5
- [![Test Coverage](https://api.codeclimate.com/v1/badges/2d00845fc6e7e83df6e7/test_coverage)](https://codeclimate.com/github/klarna/phobos/test_coverage)
6
- [![Depfu](https://badges.depfu.com/badges/57da3d5ff1da449cf8739cfe30b8d2f8/count.svg)](https://depfu.com/github/klarna/phobos?project=Bundler)
7
- [![Chat with us on Discord](https://discordapp.com/api/guilds/379938130326847488/widget.png)](https://discord.gg/rfMUBVD)
3
+ [![Build Status](https://travis-ci.com/phobos/phobos.svg?branch=master)](https://travis-ci.com/phobos/phobos)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/e3814d747c91247b24c6/maintainability)](https://codeclimate.com/github/phobos/phobos/maintainability)
5
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/e3814d747c91247b24c6/test_coverage)](https://codeclimate.com/github/phobos/phobos/test_coverage)
8
6
 
9
7
  # Phobos
10
8
 
@@ -214,6 +212,49 @@ The hander life cycle can be illustrated as:
214
212
  or optionally,
215
213
 
216
214
  `.start` -> `#before_consume` -> `#around_consume` [ `#consume` ] -> `.stop`
215
+
216
+ #### Batch Consumption
217
+
218
+ In addition to the regular handler, Phobos provides a `BatchHandler`. The
219
+ basic ideas are identical, except that instead of being passed a single message
220
+ at a time, the `BatchHandler` is passed a batch of messages. All methods
221
+ follow the same pattern as the regular handler except that they each
222
+ end in `_batch` and are passed an array of `Phobos::BatchMessage`s instead
223
+ of a single payload.
224
+
225
+ To enable handling of batches on the consumer side, you must specify
226
+ a delivery method of `inline_batch` in [phobos.yml](config/phobos.yml.example),
227
+ and your handler must include `BatchHandler`. Using a delivery method of `batch`
228
+ assumes that you are still processing the messages one at a time and should
229
+ use `Handler`.
230
+
231
+ ```ruby
232
+ class MyBatchHandler
233
+ includes Phobos::BatchHandler
234
+
235
+ def before_consume_batch(payloads, metadata)
236
+ payloads.each do |p|
237
+ p.payload[:timestamp] = Time.zone.now
238
+ end
239
+ end
240
+
241
+ def around_consume_batch(payloads, metadata)
242
+ yield
243
+ end
244
+
245
+ def consume_batch(payloads, metadata)
246
+ payloads.each do |p|
247
+ logger.info("Got payload #{p.payload}, #{p.partition}, #{p.offset}, #{p.key}, #{p.payload[:timestamp]}")
248
+ end
249
+ end
250
+
251
+ end
252
+ ```
253
+
254
+ Note that retry logic will happen on the *batch* level in this case. If you are
255
+ processing messages individually and an error happens in the middle, Phobos's
256
+ retry logic will retry the entire batch. If this is not the behavior you want,
257
+ consider using `batch` instead of `inline_batch`.
217
258
 
218
259
  ### <a name="usage-producing-messages-to-kafka"></a> Producing messages to Kafka
219
260
 
@@ -436,7 +477,7 @@ end
436
477
  * partition
437
478
  * offset_lag
438
479
  * highwater_mark_offset
439
- * `listener.process_message` is sent after process a message. It includes the following payload:
480
+ * `listener.process_message` is sent after processing a message. It includes the following payload:
440
481
  * listener_id
441
482
  * group_id
442
483
  * topic
@@ -445,7 +486,16 @@ end
445
486
  * partition
446
487
  * offset
447
488
  * retry_count
448
- * `listener.retry_handler_error` is sent after waited for `handler#consume` retry. It includes the following payload:
489
+ * `listener.process_batch_inline` is sent after processing a batch with `batch_inline` mode. It includes the following payload:
490
+ * listener_id
491
+ * group_id
492
+ * topic
493
+ * handler
494
+ * batch_size
495
+ * partition
496
+ * offset_lag
497
+ * retry_count
498
+ * `listener.retry_handler_error` is sent after waiting for `handler#consume` retry. It includes the following payload:
449
499
  * listener_id
450
500
  * group_id
451
501
  * topic
@@ -458,22 +508,35 @@ end
458
508
  * exception_class
459
509
  * exception_message
460
510
  * backtrace
511
+ * `listener.retry_handler_error_batch` is sent after waiting for `handler#consume_batch` retry. It includes the following payload:
512
+ * listener_id
513
+ * group_id
514
+ * topic
515
+ * handler
516
+ * batch_size
517
+ * partition
518
+ * offset_lag
519
+ * retry_count
520
+ * waiting_time
521
+ * exception_class
522
+ * exception_message
523
+ * backtrace
461
524
  * `listener.retry_aborted` is sent after waiting for a retry but the listener was stopped before the retry happened. It includes the following payload:
462
525
  * listener_id
463
526
  * group_id
464
527
  * topic
465
528
  * handler
466
- * `listener.stopping` is sent when the listener receives signal to stop
529
+ * `listener.stopping` is sent when the listener receives signal to stop.
467
530
  * listener_id
468
531
  * group_id
469
532
  * topic
470
533
  * handler
471
- * `listener.stop_handler` is sent after stopping the handler
534
+ * `listener.stop_handler` is sent after stopping the handler.
472
535
  * listener_id
473
536
  * group_id
474
537
  * topic
475
538
  * handler
476
- * `listener.stop` is send after stopping the listener
539
+ * `listener.stop` is send after stopping the listener.
477
540
  * listener_id
478
541
  * group_id
479
542
  * topic
@@ -107,7 +107,11 @@ listeners:
107
107
  # - `batch` will yield batches from Ruby Kafka using `each_batch`, and commit/heartbeat at every consumed batch.
108
108
  # Due to implementation in Ruby Kafka, it should be noted that when configuring large batch sizes in combination with taking long time to consume messages,
109
109
  # your consumers might get kicked from the Kafka cluster for not sending a heartbeat within the expected interval.
110
- # Take this into consideration when determining your configuration.
110
+ # Take this into consideration when determining your configuration. You can send heartbeats manually while
111
+ # processing your messages if necessary.
112
+ # - `inline_batch` also uses `each_batch`, but will pass the entire batch to your handler instead
113
+ # of one message at a time. To use this method, you should include Phobos::BatchHandler
114
+ # instead of Phobos::Handler so that you can make use of the `consume_batch` etc. methods.
111
115
  # Note: Ultimately commit/heartbeart will depend on the offset commit options and the heartbeat interval.
112
116
  delivery: batch
113
117
  # Use this if custom backoff is required for a listener
@@ -22,8 +22,10 @@ require 'phobos/errors'
22
22
  require 'phobos/listener'
23
23
  require 'phobos/actions/process_batch'
24
24
  require 'phobos/actions/process_message'
25
+ require 'phobos/actions/process_batch_inline'
25
26
  require 'phobos/producer'
26
27
  require 'phobos/handler'
28
+ require 'phobos/batch_handler'
27
29
  require 'phobos/echo_handler'
28
30
  require 'phobos/executor'
29
31
 
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'phobos/batch_message'
4
+ require 'phobos/processor'
5
+
6
+ module Phobos
7
+ module Actions
8
+ class ProcessBatchInline
9
+ include Phobos::Processor
10
+
11
+ attr_reader :metadata
12
+
13
+ def initialize(listener:, batch:, metadata:)
14
+ @listener = listener
15
+ @batch = batch
16
+ @listener = listener
17
+ @batch = batch
18
+ @metadata = metadata.merge(
19
+ batch_size: batch.messages.count,
20
+ partition: batch.partition,
21
+ offset_lag: batch.offset_lag,
22
+ retry_count: 0
23
+ )
24
+ end
25
+
26
+ def execute
27
+ payloads = @batch.messages.map do |message|
28
+ Phobos::BatchMessage.new(
29
+ key: message.key,
30
+ partition: message.partition,
31
+ offset: message.offset,
32
+ payload: force_encoding(message.value)
33
+ )
34
+ end
35
+
36
+ begin
37
+ process_batch(payloads)
38
+ rescue StandardError => e
39
+ handle_error(e, 'listener.retry_handler_error_batch',
40
+ "error processing inline batch, waiting #{backoff_interval}s")
41
+ retry
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def process_batch(payloads)
48
+ instrument('listener.process_batch_inline', @metadata) do |_metadata|
49
+ handler = @listener.handler_class.new
50
+
51
+ preprocessed_payloads = handler.before_consume_batch(payloads, @metadata)
52
+ consume_block = proc { handler.consume_batch(preprocessed_payloads, @metadata) }
53
+
54
+ handler.around_consume_batch(preprocessed_payloads, @metadata, &consume_block)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'phobos/processor'
4
+
3
5
  module Phobos
4
6
  module Actions
5
7
  class ProcessMessage
6
- MAX_SLEEP_INTERVAL = 3
7
-
8
- include Phobos::Instrumentation
8
+ include Phobos::Processor
9
9
 
10
10
  attr_reader :metadata
11
11
 
@@ -26,29 +26,14 @@ module Phobos
26
26
  begin
27
27
  process_message(payload)
28
28
  rescue StandardError => e
29
- handle_error(e)
29
+ handle_error(e, 'listener.retry_handler_error',
30
+ "error processing message, waiting #{backoff_interval}s")
30
31
  retry
31
32
  end
32
33
  end
33
34
 
34
- def snooze(interval)
35
- remaining_interval = interval
36
-
37
- @listener.send_heartbeat_if_necessary
38
-
39
- while remaining_interval.positive?
40
- sleep [remaining_interval, MAX_SLEEP_INTERVAL].min
41
- remaining_interval -= MAX_SLEEP_INTERVAL
42
- @listener.send_heartbeat_if_necessary
43
- end
44
- end
45
-
46
35
  private
47
36
 
48
- def force_encoding(value)
49
- @listener.encoding ? value&.force_encoding(@listener.encoding) : value
50
- end
51
-
52
37
  def process_message(payload)
53
38
  instrument('listener.process_message', @metadata) do
54
39
  handler = @listener.handler_class.new
@@ -75,43 +60,6 @@ module Phobos
75
60
  'please update your consumer. This will not be backwards compatible in the future.')
76
61
  handler.before_consume(payload)
77
62
  end
78
-
79
- def handle_error(error)
80
- error_hash = {
81
- waiting_time: backoff_interval,
82
- exception_class: error.class.name,
83
- exception_message: error.message,
84
- backtrace: error.backtrace
85
- }
86
-
87
- instrument('listener.retry_handler_error', error_hash.merge(@metadata)) do
88
- Phobos.logger.error do
89
- { message: "error processing message, waiting #{backoff_interval}s" }
90
- .merge(error_hash)
91
- .merge(@metadata)
92
- end
93
-
94
- snooze(backoff_interval)
95
- end
96
-
97
- increment_retry_count
98
- end
99
-
100
- def retry_count
101
- @metadata[:retry_count]
102
- end
103
-
104
- def increment_retry_count
105
- @metadata[:retry_count] = retry_count + 1
106
- end
107
-
108
- def backoff
109
- @backoff ||= @listener.create_exponential_backoff
110
- end
111
-
112
- def backoff_interval
113
- backoff.interval_at(retry_count).round(2)
114
- end
115
63
  end
116
64
  end
117
65
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Phobos
4
+ module BatchHandler
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ def before_consume_batch(payloads, _metadata)
10
+ payloads
11
+ end
12
+
13
+ def consume_batch(_payloads, _metadata)
14
+ raise NotImplementedError
15
+ end
16
+
17
+ def around_consume_batch(_payloads, _metadata)
18
+ yield
19
+ end
20
+
21
+ module ClassMethods
22
+ def start(kafka_client); end
23
+
24
+ def stop; end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Phobos
4
+ class BatchMessage
5
+ attr_accessor :key, :partition, :offset, :payload
6
+
7
+ def initialize(key:, partition:, offset:, payload:)
8
+ @key = key
9
+ @partition = partition
10
+ @offset = offset
11
+ @payload = payload
12
+ end
13
+
14
+ def ==(other)
15
+ [:key, :partition, :offset, :payload].all? do |s|
16
+ public_send(s) == other.public_send(s)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -35,11 +35,15 @@ module Phobos
35
35
  File.exist?(config_file) || error_exit("Config file not found (#{config_file})")
36
36
  end
37
37
 
38
- def validate_listeners!
38
+ def validate_listeners! # rubocop:disable Metrics/MethodLength
39
39
  Phobos.config.listeners.each do |listener|
40
40
  handler = listener.handler
41
41
 
42
- Object.const_defined?(handler) || error_exit("Handler '#{handler}' not defined")
42
+ begin
43
+ handler.constantize
44
+ rescue NameError
45
+ error_exit("Handler '#{handler}' not defined")
46
+ end
43
47
 
44
48
  delivery = listener.delivery
45
49
  if delivery.nil?
@@ -7,7 +7,7 @@ module Phobos
7
7
  include Phobos::Log
8
8
 
9
9
  DEFAULT_MAX_BYTES_PER_PARTITION = 1_048_576 # 1 MB
10
- DELIVERY_OPTS = %w[batch message].freeze
10
+ DELIVERY_OPTS = %w[batch message inline_batch].freeze
11
11
 
12
12
  attr_reader :group_id, :topic, :id
13
13
  attr_reader :handler_class, :encoding
@@ -123,7 +123,15 @@ module Phobos
123
123
  end
124
124
 
125
125
  def start_consumer_loop
126
- @delivery == 'batch' ? consume_each_batch : consume_each_message
126
+ # validate batch handling
127
+ case @delivery
128
+ when 'batch'
129
+ consume_each_batch
130
+ when 'inline_batch'
131
+ consume_each_batch_inline
132
+ else
133
+ consume_each_message
134
+ end
127
135
  end
128
136
 
129
137
  def consume_each_batch
@@ -140,6 +148,20 @@ module Phobos
140
148
  end
141
149
  end
142
150
 
151
+ def consume_each_batch_inline
152
+ @consumer.each_batch(@message_processing_opts) do |batch|
153
+ batch_processor = Phobos::Actions::ProcessBatchInline.new(
154
+ listener: self,
155
+ batch: batch,
156
+ metadata: listener_metadata
157
+ )
158
+
159
+ batch_processor.execute
160
+ log_debug('Committed offset', batch_processor.metadata)
161
+ return nil if should_stop?
162
+ end
163
+ end
164
+
143
165
  def consume_each_message
144
166
  @consumer.each_message(@message_processing_opts) do |message|
145
167
  message_processor = Phobos::Actions::ProcessMessage.new(
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+
5
+ module Phobos
6
+ module Processor
7
+ extend ActiveSupport::Concern
8
+ include Phobos::Instrumentation
9
+
10
+ MAX_SLEEP_INTERVAL = 3
11
+
12
+ def snooze(interval)
13
+ remaining_interval = interval
14
+
15
+ @listener.send_heartbeat_if_necessary
16
+
17
+ while remaining_interval.positive?
18
+ sleep [remaining_interval, MAX_SLEEP_INTERVAL].min
19
+ remaining_interval -= MAX_SLEEP_INTERVAL
20
+ @listener.send_heartbeat_if_necessary
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def force_encoding(value)
27
+ @listener.encoding ? value&.force_encoding(@listener.encoding) : value
28
+ end
29
+
30
+ def handle_error(error, instrumentation_key, error_message)
31
+ error_hash = {
32
+ waiting_time: backoff_interval,
33
+ exception_class: error.class.name,
34
+ exception_message: error.message,
35
+ backtrace: error.backtrace
36
+ }
37
+
38
+ instrument(instrumentation_key, error_hash.merge(@metadata)) do
39
+ Phobos.logger.error do
40
+ { message: error_message }
41
+ .merge(error_hash)
42
+ .merge(@metadata)
43
+ end
44
+
45
+ snooze(backoff_interval)
46
+ end
47
+
48
+ increment_retry_count
49
+ end
50
+
51
+ def retry_count
52
+ @metadata[:retry_count]
53
+ end
54
+
55
+ def increment_retry_count
56
+ @metadata[:retry_count] = retry_count + 1
57
+ end
58
+
59
+ def backoff
60
+ @backoff ||= @listener.create_exponential_backoff
61
+ end
62
+
63
+ def backoff_interval
64
+ backoff.interval_at(retry_count).round(2)
65
+ end
66
+ end
67
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Phobos
4
- VERSION = '1.8.1'
4
+ VERSION = '1.8.2-beta1'
5
5
  end
@@ -14,7 +14,8 @@ Gem::Specification.new do |spec|
14
14
  'Thiago R. Colucci',
15
15
  'Martin Svalin',
16
16
  'Francisco Juan',
17
- 'Tommy Gustafsson'
17
+ 'Tommy Gustafsson',
18
+ 'Daniel Orner'
18
19
  ]
19
20
  spec.email = [
20
21
  'ornelas.tulio@gmail.com',
@@ -23,7 +24,8 @@ Gem::Specification.new do |spec|
23
24
  'ticolucci@gmail.com',
24
25
  'martin@lite.nu',
25
26
  'francisco.juan@gmail.com',
26
- 'tommydgustafsson@gmail.com'
27
+ 'tommydgustafsson@gmail.com',
28
+ 'dmorner@gmail.com'
27
29
  ]
28
30
 
29
31
  spec.summary = 'Simplifying Kafka for ruby apps'
@@ -53,7 +55,7 @@ Gem::Specification.new do |spec|
53
55
  spec.add_development_dependency 'pry-byebug'
54
56
  spec.add_development_dependency 'rake', '~> 12.3'
55
57
  spec.add_development_dependency 'rspec', '~> 3.0'
56
- spec.add_development_dependency 'rubocop', '0.60.0'
58
+ spec.add_development_dependency 'rubocop', '0.62.0'
57
59
  spec.add_development_dependency 'rubocop_rules'
58
60
  spec.add_development_dependency 'simplecov'
59
61
  spec.add_development_dependency 'timecop'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phobos
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.1
4
+ version: 1.8.2.pre.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Túlio Ornelas
@@ -11,10 +11,11 @@ authors:
11
11
  - Martin Svalin
12
12
  - Francisco Juan
13
13
  - Tommy Gustafsson
14
+ - Daniel Orner
14
15
  autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
- date: 2018-11-23 00:00:00.000000000 Z
18
+ date: 2019-03-13 00:00:00.000000000 Z
18
19
  dependencies:
19
20
  - !ruby/object:Gem::Dependency
20
21
  name: bundler
@@ -78,14 +79,14 @@ dependencies:
78
79
  requirements:
79
80
  - - '='
80
81
  - !ruby/object:Gem::Version
81
- version: 0.60.0
82
+ version: 0.62.0
82
83
  type: :development
83
84
  prerelease: false
84
85
  version_requirements: !ruby/object:Gem::Requirement
85
86
  requirements:
86
87
  - - '='
87
88
  - !ruby/object:Gem::Version
88
- version: 0.60.0
89
+ version: 0.62.0
89
90
  - !ruby/object:Gem::Dependency
90
91
  name: rubocop_rules
91
92
  requirement: !ruby/object:Gem::Requirement
@@ -237,6 +238,7 @@ email:
237
238
  - martin@lite.nu
238
239
  - francisco.juan@gmail.com
239
240
  - tommydgustafsson@gmail.com
241
+ - dmorner@gmail.com
240
242
  executables:
241
243
  - phobos
242
244
  extensions: []
@@ -268,7 +270,10 @@ files:
268
270
  - examples/publishing_messages_without_consumer.rb
269
271
  - lib/phobos.rb
270
272
  - lib/phobos/actions/process_batch.rb
273
+ - lib/phobos/actions/process_batch_inline.rb
271
274
  - lib/phobos/actions/process_message.rb
275
+ - lib/phobos/batch_handler.rb
276
+ - lib/phobos/batch_message.rb
272
277
  - lib/phobos/cli.rb
273
278
  - lib/phobos/cli/runner.rb
274
279
  - lib/phobos/cli/start.rb
@@ -281,6 +286,7 @@ files:
281
286
  - lib/phobos/instrumentation.rb
282
287
  - lib/phobos/listener.rb
283
288
  - lib/phobos/log.rb
289
+ - lib/phobos/processor.rb
284
290
  - lib/phobos/producer.rb
285
291
  - lib/phobos/test.rb
286
292
  - lib/phobos/test/helper.rb
@@ -304,12 +310,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
304
310
  version: '2.3'
305
311
  required_rubygems_version: !ruby/object:Gem::Requirement
306
312
  requirements:
307
- - - ">="
313
+ - - ">"
308
314
  - !ruby/object:Gem::Version
309
- version: '0'
315
+ version: 1.3.1
310
316
  requirements: []
311
- rubyforge_project:
312
- rubygems_version: 2.7.6
317
+ rubygems_version: 3.0.2
313
318
  signing_key:
314
319
  specification_version: 4
315
320
  summary: Simplifying Kafka for ruby apps