phobos 1.8.1 → 1.8.2.pre.beta1

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: 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