railway-ipc 1.1.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: f2a31b80fc9d4f13598bdc2fbd14c84c78360bd4adeb588bb63b3bb20c33a2de
4
- data.tar.gz: 2bfef85b0fbe56b0d66df365f8ffa5b7913b188658edbb63484aaa0138dfa6ba
3
+ metadata.gz: 3b65c6b026a85e5cd4ae6693711ec05d9efe714517c2a05c3bfd7111bde92eab
4
+ data.tar.gz: 944093374956d0ad82460ebbddb61f952d3ac70dbdb8294f032dd63ee2e0df9e
5
5
  SHA512:
6
- metadata.gz: a27c830370df223add103179c9e8b60d5259abbb5b21b664f0b2642d96e5736926325c07e271b08822401c312ef532ec8a6f3c03dba30ce5a637edcbbba1ed12
7
- data.tar.gz: 555cb81425239fba2c5752e238bd541db554f48eb7d46d1336122d730781e40fdd0b339a8266a49a42ace8b73909d7a26f145b9e3ea5d9602fbfcefb9db1a022
6
+ metadata.gz: 7fad19c0a2c6bc99a7e56242eaa70b6c5f449d9c641372cc4088cc5aaba1f8ac3cfcc45f6e8b003c34713c65342b676114dd7ada579ed8d8bf3b31a94838d614
7
+ data.tar.gz: 27e95ff1100792b27e07414ee681062ceb54f12c7c31308e022045184031c15793f5f187b9dfbe51746ffe0bd4cb4ab0bf1d81163cb04126598fba15d720a6ec
@@ -10,6 +10,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
10
10
  ### Removed
11
11
  ### Fixed
12
12
 
13
+ ## [2.0.3] - 2020-09-02
14
+ ### Fixed
15
+ * Fix RPC server. RPC servers need to conform to the Sneaker worker API (i.e. their initializers need to be able to accept queue name / pool and they require a `stop` method.
16
+
17
+ ## [2.0.2] - 2020-08-27
18
+ ### Changed
19
+ * RPC `RailwayIpc::Client` does not need to log the queue name.
20
+
21
+ ## [2.0.1] - 2020-08-24
22
+ ### Fixed
23
+ * `RailwayIpc::Logger` now handles block syntax (i.e. `logger.info { 'my message' }`) correctly.
24
+
25
+ ## [2.0.0] - 2020-08-20
26
+ ### Added
27
+ * Several additions to internal logging:
28
+ - Log messages now include a `feature` key. This can be used by logging aggregator tools to group log messages across different systems that use the gem. If one isn't provided a default value of `railway_ipc` is used.
29
+ - Protobufs are logged as a sub-hash which contains both the protobuf type and payload.
30
+ - Exchange and queue names are logged where applicable.
31
+ - The internal Bunny connection now uses the `RailwayIpc::Logger` instead of a generic `Logger`.
32
+
33
+ ### Changed
34
+ * *Breaking Change* `RailwayIpc.configure` now takes `device`, `level`, and `formatter` instead of a complete `Logger` instance. The instance is now managed internally by Railway. This is a breaking change to the `RailwayIpc.configure` API, clients will need to be updated to use the new syntax.
35
+
13
36
  ## [1.1.0] - 2020-08-07
14
37
  ### Changed
15
38
  * allow multiple consumers to handle the same message
@@ -43,7 +66,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
43
66
  ### Added
44
67
  - Correlation ID and message UUID are auto generated for messages for IDs are not passed in [#23](https://github.com/learn-co/railway_ipc_gem/pull/23)
45
68
 
46
- [Unreleased]: https://github.com/learn-co/railway_ipc_gem/compare/v1.1.0...HEAD
69
+ [Unreleased]: https://github.com/learn-co/railway_ipc_gem/compare/v2.0.3...HEAD
70
+ [2.0.3]: https://github.com/learn-co/railway_ipc_gem/compare/v2.0.2...v2.0.3
71
+ [2.0.2]: https://github.com/learn-co/railway_ipc_gem/compare/v2.0.1...v2.0.2
72
+ [2.0.1]: https://github.com/learn-co/railway_ipc_gem/compare/v2.0.0...v2.0.1
73
+ [2.0.0]: https://github.com/learn-co/railway_ipc_gem/compare/v1.1.0...v2.0.0
47
74
  [1.1.0]: https://github.com/learn-co/railway_ipc_gem/compare/v1.0.1...v1.1.0
48
75
  [1.0.1]: https://github.com/learn-co/railway_ipc_gem/compare/v1.0.0...v1.0.1
49
76
  [1.0.0]: https://github.com/learn-co/railway_ipc_gem/compare/v0.1.7...v1.0.0
data/README.md CHANGED
@@ -19,7 +19,7 @@ And then execute:
19
19
  ```ruby
20
20
  # config/initializers/railway_ipc.rb
21
21
 
22
- RailwayIpc.configure(logger: Rails.logger)
22
+ RailwayIpc.configure(STDOUT, Logger::INFO, MyFormatter)
23
23
  ```
24
24
 
25
25
  * Load the rake tasks in your Rakefile
@@ -29,16 +29,12 @@ module RailwayIpc
29
29
  Rake::Task['sneakers:run'].invoke
30
30
  end
31
31
 
32
- def self.configure(logger: ::Logger.new(STDOUT))
33
- @logger = RailwayIpc::Logger.new(logger)
32
+ def self.configure(log_device=STDOUT, level=::Logger::INFO, log_formatter=nil)
33
+ @logger = RailwayIpc::Logger.new(log_device, level, log_formatter)
34
34
  end
35
35
 
36
36
  def self.logger
37
- @logger || RailwayIpc::Logger.new(::Logger.new(STDOUT))
38
- end
39
-
40
- def self.bunny_logger
41
- logger.logger
37
+ @logger || RailwayIpc::Logger.new(STDOUT)
42
38
  end
43
39
 
44
40
  def self.bunny_connection
@@ -3,6 +3,7 @@
3
3
  module RailwayIpc
4
4
  class Consumer
5
5
  include Sneakers::Worker
6
+
6
7
  def self.inherited(base)
7
8
  base.instance_eval do
8
9
  def handlers
@@ -11,12 +12,13 @@ module RailwayIpc
11
12
  end
12
13
  end
13
14
 
14
- def self.listen_to(queue:, exchange:)
15
- from_queue queue,
16
- exchange: exchange,
17
- durable: true,
18
- exchange_type: :fanout,
19
- connection: RailwayIpc.bunny_connection
15
+ def self.listen_to(queue:, exchange:, options: {})
16
+ from_queue queue, {
17
+ exchange: exchange,
18
+ durable: true,
19
+ exchange_type: :fanout,
20
+ connection: RailwayIpc.bunny_connection
21
+ }.merge(options)
20
22
  end
21
23
 
22
24
  def self.handle(message_type, with:)
@@ -44,10 +46,12 @@ module RailwayIpc
44
46
  RailwayIpc::ProcessIncomingMessage.call(self, message)
45
47
  ack!
46
48
  rescue StandardError => e
47
- RailwayIpc.logger.log_exception(
48
- feature: 'railway_consumer',
49
+ RailwayIpc.logger.error(
50
+ e.message,
51
+ feature: 'railway_ipc_consumer',
52
+ exchange: exchange_name,
53
+ queue: queue_name,
49
54
  error: e.class,
50
- error_message: e.message,
51
55
  payload: payload
52
56
  )
53
57
  raise e
@@ -16,8 +16,9 @@ module RailwayIpc
16
16
 
17
17
  def run
18
18
  logger.warn(
19
- incoming_message.decoded,
20
- "Ignoring unknown message of type '#{incoming_message.type}'"
19
+ "Ignoring unknown message of type '#{incoming_message.type}'",
20
+ feature: 'railway_ipc_consumer',
21
+ protobuf: { type: incoming_message.type, data: incoming_message.decoded }
21
22
  )
22
23
  end
23
24
  end
@@ -36,8 +37,9 @@ module RailwayIpc
36
37
 
37
38
  def run
38
39
  logger.warn(
39
- incoming_message.decoded,
40
- "Ignoring message, no registered handler for '#{incoming_message.type}'"
40
+ "Ignoring message, no registered handler for '#{incoming_message.type}'",
41
+ feature: 'railway_ipc_consumer',
42
+ protobuf: { type: incoming_message.type, data: incoming_message.decoded }
41
43
  )
42
44
  end
43
45
  end
@@ -81,7 +83,13 @@ module RailwayIpc
81
83
 
82
84
  def raise_message_invalid_error
83
85
  error = "Message is invalid: #{incoming_message.stringify_errors}."
84
- logger.error(incoming_message.decoded, error)
86
+ logger.error(
87
+ error,
88
+ feature: 'railway_ipc_consumer',
89
+ exchange: consumer.exchange_name,
90
+ queue: consumer.queue_name,
91
+ protobuf: { type: incoming_message.class, data: incoming_message.decoded }
92
+ )
85
93
  raise RailwayIpc::IncomingMessage::InvalidMessage.new(error)
86
94
  end
87
95
 
@@ -11,15 +11,27 @@ module RailwayIpc
11
11
  end
12
12
 
13
13
  def handle(message)
14
- RailwayIpc.logger.info(message, 'Handling message')
14
+ RailwayIpc.logger.info('Handling message', log_message_options(message))
15
15
  response = self.class.block.call(message)
16
16
  if response.success?
17
- RailwayIpc.logger.info(message, 'Successfully handled message')
17
+ RailwayIpc.logger.info('Successfully handled message', log_message_options(message))
18
18
  else
19
- RailwayIpc.logger.error(message, 'Failed to handle message')
19
+ RailwayIpc.logger.error('Failed to handle message', log_message_options(message))
20
20
  end
21
21
 
22
22
  response
23
23
  end
24
+
25
+ private
26
+
27
+ def log_message_options(message)
28
+ {
29
+ feature: 'railway_ipc_consumer',
30
+ protobuf: {
31
+ type: message.class.name,
32
+ data: message
33
+ }
34
+ }
35
+ end
24
36
  end
25
37
  end
@@ -1,36 +1,53 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailwayIpc
4
+ # Custom logger that accepts a `device`, `level`, and `formatter`.
5
+ # `formatter` can be any object that responds to `call`; a
6
+ # `Logger::Formatter` is used if the argument is not provided.
7
+ #
8
+ # Here is an example formatter that uses `Oj` to format structured log
9
+ # messages:
10
+ #
11
+ # require 'oj'
12
+ # OjFormatter = proc do |severity, datetime, progname, data|
13
+ # data.merge!(
14
+ # name: progname,
15
+ # timestamp: datetime,
16
+ # severity: severity
17
+ # )
18
+ # Oj.dump(data, { mode: :compat, time_format: :xmlschema })
19
+ # end
20
+ #
21
+ # logger = RailwayIpc::Logger.new(STDOUT, Logger::INFO, OjFormatter)
22
+ #
4
23
  class Logger
5
- attr_reader :logger
6
-
7
- def initialize(logger)
8
- @logger = logger
9
- end
10
-
11
- def info(message, statement)
12
- logger.info("[#{message_header(message)}] #{statement}")
24
+ def initialize(device=STDOUT, level=::Logger::INFO, formatter=nil)
25
+ @logger = ::Logger.new(device)
26
+ @logger.level = level
27
+ @logger.formatter = formatter if formatter
13
28
  end
14
29
 
15
- def warn(message, statement)
16
- logger.warn("[#{message_header(message)}] #{statement}")
30
+ %w[fatal error warn info debug].each do |level|
31
+ define_method(level) do |message=nil, data={}, &block|
32
+ data.merge!(feature: 'railway_ipc') unless data.key?(:feature)
33
+ return logger.send(level, data.merge(message: message)) unless block
34
+
35
+ data = message.merge(data) if message&.is_a?(Hash)
36
+ data.merge!(message: block.call)
37
+
38
+ # This is for compatability w/ Ruby's Logger. Ruby's Logger class
39
+ # assumes that if both a `message` argument and a block are given,
40
+ # that the block contains the actual message. The `message` argument
41
+ # is assumed to be the `progname`.
42
+ #
43
+ # https://github.com/ruby/logger/blob/master/lib/logger.rb#L471
44
+ data.merge!(progname: message) if message&.is_a?(String)
45
+ logger.send(level, data)
46
+ end
17
47
  end
18
48
 
19
- def debug(message, statement)
20
- logger.debug("[#{message_header(message)}] #{statement}")
21
- end
49
+ private
22
50
 
23
- def error(message, statement)
24
- logger.error("[#{message_header(message)}] #{statement}")
25
- end
26
-
27
- def log_exception(exception)
28
- logger.error(exception)
29
- end
30
-
31
- def message_header(message)
32
- log_statement = "message type: #{message.class}, uuid: #{message.uuid}, correlation_id: #{message.correlation_id}"
33
- message.respond_to?(:user_uuid) ? "#{log_statement}, user_uuid: #{message.user_uuid}" : log_statement
34
- end
51
+ attr_reader :logger
35
52
  end
36
53
  end
@@ -21,16 +21,15 @@ module RailwayIpc
21
21
  end
22
22
 
23
23
  def publish(message, published_message_store=RailwayIpc::PublishedMessage)
24
- RailwayIpc.logger.logger.warn('DEPRECATED: Use new PublisherInstance class')
24
+ RailwayIpc.logger.warn('DEPRECATED: Use new PublisherInstance class', log_message_options)
25
25
  ensure_message_uuid(message)
26
26
  ensure_correlation_id(message)
27
- RailwayIpc.logger.info(message, 'Publishing message')
28
-
27
+ RailwayIpc.logger.info('Publishing message', log_message_options(message))
29
28
  result = super(RailwayIpc::Rabbitmq::Payload.encode(message))
30
29
  published_message_store.store_message(self.class.exchange_name, message)
31
30
  result
32
31
  rescue RailwayIpc::InvalidProtobuf => e
33
- RailwayIpc.logger.error(message, 'Invalid protobuf')
32
+ RailwayIpc.logger.error('Invalid protobuf', log_message_options(message))
34
33
  raise e
35
34
  end
36
35
 
@@ -45,6 +44,11 @@ module RailwayIpc
45
44
  message.correlation_id = SecureRandom.uuid if message.correlation_id.blank?
46
45
  message
47
46
  end
47
+
48
+ def log_message_options(message=nil)
49
+ options = { feature: 'railway_ipc_publisher', exchange: self.class.exchange_name }
50
+ message.nil? ? options : options.merge(protobuf: { type: message.class, data: message })
51
+ end
48
52
  end
49
53
  end
50
54
 
@@ -68,20 +72,33 @@ module RailwayIpc
68
72
  def publish(message)
69
73
  message.uuid = SecureRandom.uuid if message.uuid.blank?
70
74
  message.correlation_id = SecureRandom.uuid if message.correlation_id.blank?
71
- RailwayIpc.logger.info(message, 'Publishing message')
75
+ RailwayIpc.logger.info('Publishing message', log_message_options(message))
72
76
 
73
77
  stored_message = message_store.store_message(exchange_name, message)
74
78
  super(RailwayIpc::Rabbitmq::Payload.encode(message))
75
79
  rescue RailwayIpc::InvalidProtobuf => e
76
- RailwayIpc.logger.error(message, 'Invalid protobuf')
80
+ RailwayIpc.logger.error('Invalid protobuf', log_message_options(message))
77
81
  raise e
78
82
  rescue ActiveRecord::RecordInvalid => e
79
- RailwayIpc.logger.error(message, 'Failed to store outgoing message')
83
+ RailwayIpc.logger.error('Failed to store outgoing message', log_message_options(message))
80
84
  raise RailwayIpc::FailedToStoreOutgoingMessage.new(e)
81
85
  rescue StandardError => e
82
86
  stored_message&.destroy
83
87
  raise e
84
88
  end
85
89
  # rubocop:enable Metrics/AbcSize
90
+
91
+ private
92
+
93
+ def log_message_options(message)
94
+ {
95
+ feature: 'railway_ipc_publisher',
96
+ exchange: exchange_name,
97
+ protobuf: {
98
+ type: message.class,
99
+ data: message
100
+ }
101
+ }
102
+ end
86
103
  end
87
104
  end
@@ -28,7 +28,7 @@ module RailwayIpc
28
28
  port: settings[:port],
29
29
  vhost: vhost,
30
30
  automatic_recovery: false,
31
- logger: RailwayIpc.bunny_logger
31
+ logger: RailwayIpc.logger
32
32
  }.merge(options))
33
33
  end
34
34
 
@@ -11,7 +11,11 @@ module RailwayIpc
11
11
  end
12
12
 
13
13
  def respond(request)
14
- RailwayIpc.logger.info(request, 'Responding to request')
14
+ RailwayIpc.logger.info(
15
+ 'Responding to request',
16
+ protobuf: { type: request.class, data: request },
17
+ feature: 'railway_ipc_request'
18
+ )
15
19
  response = self.class.block.call(request)
16
20
  raise ResponseTypeError.new(response.class) unless response.is_a?(Google::Protobuf::MessageExts)
17
21
 
@@ -44,7 +44,12 @@ module RailwayIpc
44
44
  case decoded_payload.type
45
45
  when *registered_handlers
46
46
  @message = get_message_class(decoded_payload).decode(decoded_payload.message)
47
- RailwayIpc.logger.info(message, 'Handling response')
47
+ RailwayIpc.logger.info(
48
+ 'Handling response',
49
+ feature: 'railway_ipc_consumer',
50
+ exchange: self.class.exchange_name,
51
+ protobuf: { type: message.class, data: message }
52
+ )
48
53
  RailwayIpc::Response.new(message, success: true)
49
54
  else
50
55
  @message = LearnIpc::ErrorMessage.decode(decoded_payload.message)
@@ -78,10 +83,11 @@ module RailwayIpc
78
83
  private
79
84
 
80
85
  def log_exception(exception, payload)
81
- RailwayIpc.logger.log_exception(
82
- feature: 'railway_consumer',
86
+ RailwayIpc.logger.error(
87
+ exception.message,
88
+ feature: 'railway_ipc_consumer',
89
+ exchange: self.class.exchange_name,
83
90
  error: exception.class,
84
- error_message: exception.message,
85
91
  payload: decode_for_error(exception, payload)
86
92
  )
87
93
  end
@@ -99,7 +105,12 @@ module RailwayIpc
99
105
  end
100
106
 
101
107
  def publish_message
102
- RailwayIpc.logger.info(request_message, 'Sending request')
108
+ RailwayIpc.logger.info(
109
+ 'Sending request',
110
+ feature: 'railway_ipc_publisher',
111
+ exchange: self.class.exchange_name,
112
+ protobuf: { type: request_message.class, data: request_message }
113
+ )
103
114
  rabbit_connection.publish(RailwayIpc::Rabbitmq::Payload.encode(request_message), routing_key: '')
104
115
  end
105
116
 
@@ -3,7 +3,7 @@
3
3
  module RailwayIpc
4
4
  module RPC
5
5
  module MessageObservationConfigurable
6
- def listen_to(exchange:, queue:)
6
+ def listen_to(queue:, exchange:)
7
7
  @exchange_name = exchange
8
8
  @queue_name = queue
9
9
  end
@@ -14,7 +14,7 @@ module RailwayIpc
14
14
  RailwayIpc::RPC::ServerResponseHandlers.instance.register(handler: with, message: message_type)
15
15
  end
16
16
 
17
- def initialize(opts={ automatic_recovery: true }, rabbit_adapter: RailwayIpc::Rabbitmq::Adapter)
17
+ def initialize(_queue, _pool, opts={ automatic_recovery: true }, rabbit_adapter: RailwayIpc::Rabbitmq::Adapter)
18
18
  @rabbit_connection = rabbit_adapter.new(
19
19
  queue_name: self.class.queue_name,
20
20
  exchange_name: self.class.exchange_name,
@@ -31,6 +31,10 @@ module RailwayIpc
31
31
  subscribe_to_queue
32
32
  end
33
33
 
34
+ def stop
35
+ rabbit_connection.disconnect
36
+ end
37
+
34
38
  # rubocop:disable Metrics/AbcSize
35
39
  # rubocop:disable Metrics/MethodLength
36
40
  def work(payload)
@@ -45,10 +49,12 @@ module RailwayIpc
45
49
  raise RailwayIpc::UnhandledMessageError.new("#{self.class} does not know how to handle #{decoded_payload.type}")
46
50
  end
47
51
  rescue StandardError => e
48
- RailwayIpc.logger.log_exception(
49
- feature: 'railway_consumer',
52
+ RailwayIpc.logger.error(
53
+ e.message,
54
+ feature: 'railway_ipc_consumer',
55
+ exchange: self.class.exchange_name,
56
+ queue: self.class.queue_name,
50
57
  error: e.class,
51
- error_message: e.message,
52
58
  payload: payload
53
59
  )
54
60
  raise e
@@ -56,10 +62,19 @@ module RailwayIpc
56
62
  # rubocop:enable Metrics/AbcSize
57
63
  # rubocop:enable Metrics/MethodLength
58
64
 
65
+ # rubocop:disable Metrics/AbcSize
66
+ # rubocop:disable Metrics/MethodLength
59
67
  def handle_request(payload)
60
68
  response = work(payload)
61
69
  rescue StandardError => e
62
- RailwayIpc.logger.error(message, "Error responding to message. Error: #{e.class}, #{e.message}")
70
+ RailwayIpc.logger.error(
71
+ 'Error responding to message.',
72
+ exception: e,
73
+ feature: 'railway_ipc_consumer',
74
+ exchange: self.class.exchange_name,
75
+ queue: self.class.queue_name,
76
+ protobuf: { type: message.class, data: message }
77
+ )
63
78
  response = self.class.rpc_error_adapter_class.error_message(e, message)
64
79
  ensure
65
80
  if response
@@ -68,6 +83,8 @@ module RailwayIpc
68
83
  )
69
84
  end
70
85
  end
86
+ # rubocop:enable Metrics/AbcSize
87
+ # rubocop:enable Metrics/MethodLength
71
88
 
72
89
  private
73
90
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailwayIpc
4
- VERSION = '1.1.0'
4
+ VERSION = '2.1.0'
5
5
  end
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
35
  spec.require_paths = ['lib']
36
36
 
37
- spec.add_development_dependency 'bundler', '2.0.1'
37
+ spec.add_development_dependency 'bundler', '2.1.4'
38
38
  spec.add_development_dependency 'factory_bot', '~> 5.1'
39
39
  spec.add_development_dependency 'google-protobuf', '~> 3.9'
40
40
  spec.add_development_dependency 'rake', '>= 10.0.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: railway-ipc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-07 00:00:00.000000000 Z
11
+ date: 2020-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 2.0.1
19
+ version: 2.1.4
20
20
  type: :development
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: 2.0.1
26
+ version: 2.1.4
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: factory_bot
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -263,7 +263,7 @@ licenses:
263
263
  - MIT
264
264
  metadata:
265
265
  allowed_push_host: https://rubygems.org/
266
- post_install_message:
266
+ post_install_message:
267
267
  rdoc_options: []
268
268
  require_paths:
269
269
  - lib
@@ -278,9 +278,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
278
278
  - !ruby/object:Gem::Version
279
279
  version: '0'
280
280
  requirements: []
281
- rubyforge_project:
282
- rubygems_version: 2.7.6
283
- signing_key:
281
+ rubygems_version: 3.0.3
282
+ signing_key:
284
283
  specification_version: 4
285
284
  summary: IPC components for Rails
286
285
  test_files: []