railway-ipc 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +1 -1
- data/lib/railway_ipc.rb +3 -7
- data/lib/railway_ipc/consumer/consumer.rb +5 -3
- data/lib/railway_ipc/consumer/process_incoming_message.rb +13 -5
- data/lib/railway_ipc/handler.rb +15 -3
- data/lib/railway_ipc/logger.rb +30 -25
- data/lib/railway_ipc/publisher.rb +24 -7
- data/lib/railway_ipc/rabbitmq/adapter.rb +1 -1
- data/lib/railway_ipc/responder.rb +5 -1
- data/lib/railway_ipc/rpc/client/client.rb +20 -5
- data/lib/railway_ipc/rpc/server/server.rb +17 -4
- data/lib/railway_ipc/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11e49c11ff3e5815f7c8050ad5fcdfde1510cf7646d10cfa5d1104a5c1868422
|
4
|
+
data.tar.gz: 3fbdeab2e555f9c4b3402cf27e3b072d33c833f85659eaccc09f31d11fddc219
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70d3834ac2a0db7b1a9a53c52edb3718b34a821d3b0d42e49ebe01f1c76c00188b928734a5969ef621e9609a3852117fd8190706566777c870b2b8b3d9592ccd
|
7
|
+
data.tar.gz: 297bbf2e92f9a77d85661849f3bbada5b18eff08b213ec6a48089dea112ab65b70a47b196e8ddc59b475e61cb9e6ecfc8648bb5dcbcd2836e341079d81b2fd92
|
data/CHANGELOG.md
CHANGED
@@ -10,6 +10,17 @@ 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.0] - 2020-08-20
|
14
|
+
### Added
|
15
|
+
* Several additions to internal logging:
|
16
|
+
- 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.
|
17
|
+
- Protobufs are logged as a sub-hash which contains both the protobuf type and payload.
|
18
|
+
- Exchange and queue names are logged where applicable.
|
19
|
+
- The internal Bunny connection now uses the `RailwayIpc::Logger` instead of a generic `Logger`.
|
20
|
+
|
21
|
+
### Changed
|
22
|
+
* *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.
|
23
|
+
|
13
24
|
## [1.1.0] - 2020-08-07
|
14
25
|
### Changed
|
15
26
|
* allow multiple consumers to handle the same message
|
data/README.md
CHANGED
data/lib/railway_ipc.rb
CHANGED
@@ -29,16 +29,12 @@ module RailwayIpc
|
|
29
29
|
Rake::Task['sneakers:run'].invoke
|
30
30
|
end
|
31
31
|
|
32
|
-
def self.configure(
|
33
|
-
@logger = RailwayIpc::Logger.new(
|
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(
|
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
|
@@ -44,10 +44,12 @@ module RailwayIpc
|
|
44
44
|
RailwayIpc::ProcessIncomingMessage.call(self, message)
|
45
45
|
ack!
|
46
46
|
rescue StandardError => e
|
47
|
-
RailwayIpc.logger.
|
48
|
-
|
47
|
+
RailwayIpc.logger.error(
|
48
|
+
e.message,
|
49
|
+
feature: 'railway_ipc_consumer',
|
50
|
+
exchange: exchange_name,
|
51
|
+
queue: queue_name,
|
49
52
|
error: e.class,
|
50
|
-
error_message: e.message,
|
51
53
|
payload: payload
|
52
54
|
)
|
53
55
|
raise e
|
@@ -16,8 +16,9 @@ module RailwayIpc
|
|
16
16
|
|
17
17
|
def run
|
18
18
|
logger.warn(
|
19
|
-
incoming_message.
|
20
|
-
|
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.
|
40
|
-
|
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(
|
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
|
|
data/lib/railway_ipc/handler.rb
CHANGED
@@ -11,15 +11,27 @@ module RailwayIpc
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def handle(message)
|
14
|
-
RailwayIpc.logger.info(
|
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(
|
17
|
+
RailwayIpc.logger.info('Successfully handled message', log_message_options(message))
|
18
18
|
else
|
19
|
-
RailwayIpc.logger.error(
|
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
|
data/lib/railway_ipc/logger.rb
CHANGED
@@ -1,36 +1,41 @@
|
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@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
|
-
|
16
|
-
|
30
|
+
%w[fatal error warn info debug].each do |level|
|
31
|
+
define_method(level) do |message, data={}|
|
32
|
+
data.merge!(feature: 'railway_ipc') unless data.key?(:feature)
|
33
|
+
logger.send(level, data.merge(message: message))
|
34
|
+
end
|
17
35
|
end
|
18
36
|
|
19
|
-
|
20
|
-
logger.debug("[#{message_header(message)}] #{statement}")
|
21
|
-
end
|
37
|
+
private
|
22
38
|
|
23
|
-
|
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
|
39
|
+
attr_reader :logger
|
35
40
|
end
|
36
41
|
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.
|
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(
|
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(
|
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(
|
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(
|
80
|
+
RailwayIpc.logger.error('Invalid protobuf', log_message_options(message))
|
77
81
|
raise e
|
78
82
|
rescue ActiveRecord::RecordInvalid => e
|
79
|
-
RailwayIpc.logger.error(
|
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
|
@@ -11,7 +11,11 @@ module RailwayIpc
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def respond(request)
|
14
|
-
RailwayIpc.logger.info(
|
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
|
|
@@ -39,18 +39,26 @@ module RailwayIpc
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# rubocop:disable Metrics/AbcSize
|
42
|
+
# rubocop:disable Metrics/MethodLength
|
42
43
|
def process_payload(response)
|
43
44
|
decoded_payload = decode_payload(response)
|
44
45
|
case decoded_payload.type
|
45
46
|
when *registered_handlers
|
46
47
|
@message = get_message_class(decoded_payload).decode(decoded_payload.message)
|
47
|
-
RailwayIpc.logger.info(
|
48
|
+
RailwayIpc.logger.info(
|
49
|
+
'Handling response',
|
50
|
+
feature: 'railway_ipc_consumer',
|
51
|
+
exchange: self.class.exchange_name,
|
52
|
+
queue: self.class.queue_name,
|
53
|
+
protobuf: { type: message.class, data: message }
|
54
|
+
)
|
48
55
|
RailwayIpc::Response.new(message, success: true)
|
49
56
|
else
|
50
57
|
@message = LearnIpc::ErrorMessage.decode(decoded_payload.message)
|
51
58
|
raise RailwayIpc::UnhandledMessageError.new("#{self.class} does not know how to handle #{decoded_payload.type}")
|
52
59
|
end
|
53
60
|
end
|
61
|
+
# rubocop:enable Metrics/MethodLength
|
54
62
|
# rubocop:enable Metrics/AbcSize
|
55
63
|
|
56
64
|
def setup_rabbit_connection
|
@@ -78,10 +86,12 @@ module RailwayIpc
|
|
78
86
|
private
|
79
87
|
|
80
88
|
def log_exception(exception, payload)
|
81
|
-
RailwayIpc.logger.
|
82
|
-
|
89
|
+
RailwayIpc.logger.error(
|
90
|
+
exception.message,
|
91
|
+
feature: 'railway_ipc_consumer',
|
92
|
+
exchange: self.class.exchange_name,
|
93
|
+
queue: self.class.queue_name,
|
83
94
|
error: exception.class,
|
84
|
-
error_message: exception.message,
|
85
95
|
payload: decode_for_error(exception, payload)
|
86
96
|
)
|
87
97
|
end
|
@@ -99,7 +109,12 @@ module RailwayIpc
|
|
99
109
|
end
|
100
110
|
|
101
111
|
def publish_message
|
102
|
-
RailwayIpc.logger.info(
|
112
|
+
RailwayIpc.logger.info(
|
113
|
+
'Sending request',
|
114
|
+
feature: 'railway_ipc_publisher',
|
115
|
+
exchange: self.class.exchange_name,
|
116
|
+
protobuf: { type: request_message.class, data: request_message }
|
117
|
+
)
|
103
118
|
rabbit_connection.publish(RailwayIpc::Rabbitmq::Payload.encode(request_message), routing_key: '')
|
104
119
|
end
|
105
120
|
|
@@ -45,10 +45,12 @@ module RailwayIpc
|
|
45
45
|
raise RailwayIpc::UnhandledMessageError.new("#{self.class} does not know how to handle #{decoded_payload.type}")
|
46
46
|
end
|
47
47
|
rescue StandardError => e
|
48
|
-
RailwayIpc.logger.
|
49
|
-
|
48
|
+
RailwayIpc.logger.error(
|
49
|
+
e.message,
|
50
|
+
feature: 'railway_ipc_consumer',
|
51
|
+
exchange: self.class.exchange_name,
|
52
|
+
queue: self.class.queue_name,
|
50
53
|
error: e.class,
|
51
|
-
error_message: e.message,
|
52
54
|
payload: payload
|
53
55
|
)
|
54
56
|
raise e
|
@@ -56,10 +58,19 @@ module RailwayIpc
|
|
56
58
|
# rubocop:enable Metrics/AbcSize
|
57
59
|
# rubocop:enable Metrics/MethodLength
|
58
60
|
|
61
|
+
# rubocop:disable Metrics/AbcSize
|
62
|
+
# rubocop:disable Metrics/MethodLength
|
59
63
|
def handle_request(payload)
|
60
64
|
response = work(payload)
|
61
65
|
rescue StandardError => e
|
62
|
-
RailwayIpc.logger.error(
|
66
|
+
RailwayIpc.logger.error(
|
67
|
+
'Error responding to message.',
|
68
|
+
exception: e,
|
69
|
+
feature: 'railway_ipc_consumer',
|
70
|
+
exchange: self.class.exchange_name,
|
71
|
+
queue: self.class.queue_name,
|
72
|
+
protobuf: { type: message.class, data: message }
|
73
|
+
)
|
63
74
|
response = self.class.rpc_error_adapter_class.error_message(e, message)
|
64
75
|
ensure
|
65
76
|
if response
|
@@ -68,6 +79,8 @@ module RailwayIpc
|
|
68
79
|
)
|
69
80
|
end
|
70
81
|
end
|
82
|
+
# rubocop:enable Metrics/AbcSize
|
83
|
+
# rubocop:enable Metrics/MethodLength
|
71
84
|
|
72
85
|
private
|
73
86
|
|
data/lib/railway_ipc/version.rb
CHANGED
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:
|
4
|
+
version: 2.0.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-
|
11
|
+
date: 2020-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -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,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
278
278
|
- !ruby/object:Gem::Version
|
279
279
|
version: '0'
|
280
280
|
requirements: []
|
281
|
-
rubyforge_project:
|
281
|
+
rubyforge_project:
|
282
282
|
rubygems_version: 2.7.6
|
283
|
-
signing_key:
|
283
|
+
signing_key:
|
284
284
|
specification_version: 4
|
285
285
|
summary: IPC components for Rails
|
286
286
|
test_files: []
|