railway-ipc 0.1.6 → 2.0.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 +4 -4
- data/.gitignore +4 -3
- data/CHANGELOG.md +61 -0
- data/Gemfile +2 -2
- data/README.md +2 -2
- data/Rakefile +10 -4
- data/bin/console +3 -3
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/lib/railway_ipc.rb +9 -11
- data/lib/railway_ipc/Rakefile +2 -0
- data/lib/railway_ipc/consumer/consumer.rb +33 -73
- data/lib/railway_ipc/consumer/process_incoming_message.rb +111 -0
- data/lib/railway_ipc/errors.rb +9 -1
- data/lib/railway_ipc/handler.rb +17 -3
- data/lib/railway_ipc/handler_store.rb +5 -2
- data/lib/railway_ipc/incoming_message.rb +51 -0
- data/lib/railway_ipc/logger.rb +32 -26
- data/lib/railway_ipc/models/consumed_message.rb +40 -35
- data/lib/railway_ipc/models/published_message.rb +11 -9
- data/lib/railway_ipc/publisher.rb +77 -3
- data/lib/railway_ipc/rabbitmq/adapter.rb +23 -15
- data/lib/railway_ipc/rabbitmq/payload.rb +9 -4
- data/lib/railway_ipc/railtie.rb +2 -0
- data/lib/railway_ipc/responder.rb +10 -3
- data/lib/railway_ipc/response.rb +4 -1
- data/lib/railway_ipc/rpc/client/client.rb +43 -18
- data/lib/railway_ipc/rpc/client/client_response_handlers.rb +2 -0
- data/lib/railway_ipc/rpc/client/errors/timeout_error.rb +2 -0
- data/lib/railway_ipc/rpc/concerns/error_adapter_configurable.rb +2 -0
- data/lib/railway_ipc/rpc/concerns/message_observation_configurable.rb +2 -0
- data/lib/railway_ipc/rpc/concerns/publish_location_configurable.rb +2 -0
- data/lib/railway_ipc/rpc/rpc.rb +2 -0
- data/lib/railway_ipc/rpc/server/server.rb +25 -7
- data/lib/railway_ipc/rpc/server/server_response_handlers.rb +2 -0
- data/lib/railway_ipc/tasks/generate_migrations.rake +16 -16
- data/lib/railway_ipc/tasks/start_consumers.rake +3 -1
- data/lib/railway_ipc/tasks/start_servers.rake +3 -1
- data/lib/railway_ipc/unhandled_message_error.rb +2 -0
- data/lib/railway_ipc/unknown_message.pb.rb +18 -0
- data/lib/railway_ipc/version.rb +3 -1
- data/priv/migrations/add_railway_ipc_consumed_messages.rb +5 -3
- data/priv/migrations/add_railway_ipc_published_messages.rb +3 -1
- data/railway_ipc.gemspec +34 -30
- metadata +65 -66
- data/.rspec +0 -3
- data/.travis.yml +0 -7
- data/Gemfile.lock +0 -186
- data/lib/railway_ipc/base_message.pb.rb +0 -21
- data/lib/railway_ipc/consumer/consumer_response_handlers.rb +0 -14
- data/lib/railway_ipc/handler_manifest.rb +0 -10
- data/lib/railway_ipc/null_handler.rb +0 -7
- data/lib/railway_ipc/null_message.rb +0 -7
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/.gitignore
CHANGED
@@ -6,14 +6,15 @@
|
|
6
6
|
/pkg/
|
7
7
|
/spec/reports/
|
8
8
|
/tmp/
|
9
|
+
Gemfile.lock
|
9
10
|
|
10
11
|
# rspec failure tracking
|
11
12
|
.rspec_status
|
12
13
|
|
13
14
|
# rails support app files
|
14
|
-
/spec/support/rails_app/.bundle
|
15
|
-
/spec/support/rails_app/log/*
|
16
|
-
/spec/support/rails_app/tmp/*
|
17
15
|
/spec/support/rails_app!/log/.keep
|
18
16
|
/spec/support/rails_app!/tmp/.keep
|
19
17
|
/spec/support/rails_app.byebug_history
|
18
|
+
/spec/support/rails_app/.bundle
|
19
|
+
/spec/support/rails_app/log/*
|
20
|
+
/spec/support/rails_app/tmp/*
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
|
+
|
7
|
+
## [Unreleased]
|
8
|
+
### Added
|
9
|
+
### Changed
|
10
|
+
### Removed
|
11
|
+
### Fixed
|
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
|
+
|
24
|
+
## [1.1.0] - 2020-08-07
|
25
|
+
### Changed
|
26
|
+
* allow multiple consumers to handle the same message
|
27
|
+
* consumed messages table requires its own primary key due to ActiveRecord not having support for composite primary keys
|
28
|
+
|
29
|
+
## [1.0.1] - 2020-07-23
|
30
|
+
### Fixed
|
31
|
+
* Fix publisher connection by using default connection if one isn't provided
|
32
|
+
|
33
|
+
## [1.0.0] - 2020-07-20
|
34
|
+
### Added
|
35
|
+
* CircleCI build that runs the specs
|
36
|
+
* Rubocop (also ran by CircleCI)
|
37
|
+
* New error types for incoming messages
|
38
|
+
* RailwayIpc::Messages::Unknown protobuf
|
39
|
+
|
40
|
+
### Changed
|
41
|
+
* Refactored worker to use ProcessIncomingMessage and IncomingMessage abstractions
|
42
|
+
* Moved decoding logic from ConsumedMessage to IncomingMessage
|
43
|
+
* Removed STATUSES constant from ConsumedMessage
|
44
|
+
* Publisher is no longer a Singleton; kept a Singleton version of the Publisher for backwards compatibility that gives a "deprecated" warning
|
45
|
+
|
46
|
+
### Removed
|
47
|
+
* Removed `BaseMessage` protobuf
|
48
|
+
* NullMessage and NullHandler were removed
|
49
|
+
|
50
|
+
### Fixed
|
51
|
+
* Fixed all Rubocop warnings and errors
|
52
|
+
|
53
|
+
## [0.1.7] - 2020-06-29
|
54
|
+
### Added
|
55
|
+
- 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)
|
56
|
+
|
57
|
+
[Unreleased]: https://github.com/learn-co/railway_ipc_gem/compare/v1.1.0...HEAD
|
58
|
+
[1.1.0]: https://github.com/learn-co/railway_ipc_gem/compare/v1.0.1...v1.1.0
|
59
|
+
[1.0.1]: https://github.com/learn-co/railway_ipc_gem/compare/v1.0.0...v1.0.1
|
60
|
+
[1.0.0]: https://github.com/learn-co/railway_ipc_gem/compare/v0.1.7...v1.0.0
|
61
|
+
[0.1.7]: https://github.com/learn-co/railway_ipc_gem/releases/tag/v0.1.7
|
data/Gemfile
CHANGED
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(
|
22
|
+
RailwayIpc.configure(STDOUT, Logger::INFO, MyFormatter)
|
23
23
|
```
|
24
24
|
|
25
25
|
* Load the rake tasks in your Rakefile
|
@@ -32,7 +32,7 @@ require "railway_ipc"
|
|
32
32
|
* Create RabbitMQ connection credentials for Railway and set the environment variable:
|
33
33
|
|
34
34
|
```
|
35
|
-
|
35
|
+
RAILWAY_RABBITMQ_CONNECTION_URL=amqp://<railway_user>:<railway_password>@localhost:5672
|
36
36
|
```
|
37
37
|
|
38
38
|
* Load table migrations and migrate by executing:
|
data/Rakefile
CHANGED
@@ -1,7 +1,13 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
3
5
|
|
4
6
|
RSpec::Core::RakeTask.new(:spec)
|
5
7
|
|
6
|
-
task :
|
7
|
-
|
8
|
+
task default: %i[spec lint]
|
9
|
+
|
10
|
+
desc 'Lint code with Rubocop'
|
11
|
+
task :lint do
|
12
|
+
exec('./bin/rubocop .')
|
13
|
+
end
|
data/bin/console
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'railway_ipc'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
8
8
|
|
9
|
-
require
|
9
|
+
require 'pry'
|
10
10
|
Pry.start
|
data/bin/rspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rspec' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rspec-core", "rspec")
|
data/bin/rubocop
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rubocop' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rubocop", "rubocop")
|
data/lib/railway_ipc.rb
CHANGED
@@ -1,42 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'railway_ipc/version'
|
2
4
|
require 'sneakers'
|
3
5
|
require 'bunny'
|
4
6
|
require 'active_record'
|
5
7
|
require 'railway_ipc/version'
|
6
|
-
require 'railway_ipc/errors'
|
7
8
|
require 'railway_ipc/logger'
|
8
9
|
require 'railway_ipc/unhandled_message_error'
|
9
10
|
require 'railway_ipc/response'
|
10
11
|
require 'railway_ipc/rabbitmq/payload'
|
11
|
-
require 'railway_ipc/
|
12
|
-
require 'railway_ipc/base_message.pb'
|
12
|
+
require 'railway_ipc/unknown_message.pb'
|
13
13
|
require 'railway_ipc/rabbitmq/adapter'
|
14
14
|
require 'railway_ipc/handler'
|
15
15
|
require 'railway_ipc/handler_store'
|
16
|
+
require 'railway_ipc/incoming_message'
|
16
17
|
require 'railway_ipc/publisher'
|
17
|
-
require 'railway_ipc/null_handler'
|
18
18
|
require 'railway_ipc/responder'
|
19
19
|
require 'railway_ipc/rpc/rpc'
|
20
20
|
require 'railway_ipc/consumer/consumer'
|
21
|
+
require 'railway_ipc/consumer/process_incoming_message'
|
21
22
|
require 'railway_ipc/models/published_message'
|
22
23
|
require 'railway_ipc/models/consumed_message'
|
23
24
|
require 'railway_ipc/railtie' if defined?(Rails)
|
25
|
+
require 'railway_ipc/errors'
|
24
26
|
|
25
27
|
module RailwayIpc
|
26
28
|
def self.start
|
27
29
|
Rake::Task['sneakers:run'].invoke
|
28
30
|
end
|
29
31
|
|
30
|
-
def self.configure(
|
31
|
-
@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)
|
32
34
|
end
|
33
35
|
|
34
36
|
def self.logger
|
35
|
-
@logger || RailwayIpc::Logger.new(
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.bunny_logger
|
39
|
-
logger.logger
|
37
|
+
@logger || RailwayIpc::Logger.new(STDOUT)
|
40
38
|
end
|
41
39
|
|
42
40
|
def self.bunny_connection
|
data/lib/railway_ipc/Rakefile
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
|
2
|
-
require "base64"
|
3
|
-
require "railway_ipc/consumer/consumer_response_handlers"
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
3
|
module RailwayIpc
|
6
4
|
class Consumer
|
7
5
|
include Sneakers::Worker
|
8
|
-
|
6
|
+
def self.inherited(base)
|
7
|
+
base.instance_eval do
|
8
|
+
def handlers
|
9
|
+
@handlers ||= RailwayIpc::HandlerStore.new
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
9
13
|
|
10
14
|
def self.listen_to(queue:, exchange:)
|
11
15
|
from_queue queue,
|
@@ -16,88 +20,44 @@ module RailwayIpc
|
|
16
20
|
end
|
17
21
|
|
18
22
|
def self.handle(message_type, with:)
|
19
|
-
|
23
|
+
handlers.register(message: message_type, handler: with)
|
20
24
|
end
|
21
25
|
|
22
|
-
def
|
23
|
-
|
26
|
+
def handlers
|
27
|
+
self.class.handlers
|
24
28
|
end
|
25
29
|
|
26
|
-
def
|
27
|
-
|
28
|
-
@decoded_payload = RailwayIpc::Rabbitmq::Payload.decode(payload)
|
29
|
-
@encoded_message = payload
|
30
|
-
|
31
|
-
case decoded_payload.type
|
32
|
-
when *registered_handlers
|
33
|
-
@handler = handler_for(decoded_payload)
|
34
|
-
message_klass = message_handler_for(decoded_payload)
|
35
|
-
@protobuf_message = message_klass.decode(decoded_payload.message)
|
36
|
-
process_known_message_type
|
37
|
-
else
|
38
|
-
@protobuf_message = RailwayIpc::BaseMessage.decode(decoded_payload.message)
|
39
|
-
process_unknown_message_type
|
40
|
-
end
|
41
|
-
ack!
|
42
|
-
rescue StandardError => e
|
43
|
-
RailwayIpc.logger.log_exception(
|
44
|
-
feature: "railway_consumer",
|
45
|
-
error: e.class,
|
46
|
-
error_message: e.message,
|
47
|
-
payload: payload,
|
48
|
-
)
|
49
|
-
raise e
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def process_protobuf!(message)
|
55
|
-
response = handler.handle(protobuf_message)
|
56
|
-
message.status = RailwayIpc::ConsumedMessage.response_to_status(response)
|
57
|
-
|
58
|
-
message.save!
|
30
|
+
def registered_handlers
|
31
|
+
handlers.registered
|
59
32
|
end
|
60
33
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
return if message && message.processed?
|
65
|
-
|
66
|
-
if message && !message.processed?
|
67
|
-
message.with_lock("FOR UPDATE NOWAIT") { process_protobuf!(message) }
|
68
|
-
else
|
69
|
-
message = create_message_with_status!(RailwayIpc::ConsumedMessage::STATUSES[:processing])
|
70
|
-
message.with_lock("FOR UPDATE NOWAIT") { process_protobuf!(message) }
|
71
|
-
end
|
34
|
+
def queue_name
|
35
|
+
queue.name
|
72
36
|
end
|
73
37
|
|
74
|
-
def
|
75
|
-
|
76
|
-
return
|
77
|
-
else
|
78
|
-
create_message_with_status!(RailwayIpc::ConsumedMessage::STATUSES[:unknown_message_type])
|
79
|
-
end
|
38
|
+
def exchange_name
|
39
|
+
queue.opts[:exchange]
|
80
40
|
end
|
81
41
|
|
82
|
-
def
|
83
|
-
RailwayIpc::
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
exchange:
|
91
|
-
|
42
|
+
def work(payload)
|
43
|
+
message = RailwayIpc::IncomingMessage.new(payload)
|
44
|
+
RailwayIpc::ProcessIncomingMessage.call(self, message)
|
45
|
+
ack!
|
46
|
+
rescue StandardError => e
|
47
|
+
RailwayIpc.logger.error(
|
48
|
+
e.message,
|
49
|
+
feature: 'railway_ipc_consumer',
|
50
|
+
exchange: exchange_name,
|
51
|
+
queue: queue_name,
|
52
|
+
error: e.class,
|
53
|
+
payload: payload
|
92
54
|
)
|
55
|
+
raise e
|
93
56
|
end
|
94
57
|
|
95
|
-
def
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
def handler_for(decoded_payload)
|
100
|
-
ConsumerResponseHandlers.instance.get(decoded_payload.type).handler.new
|
58
|
+
def get_handler(type)
|
59
|
+
manifest = handlers.get(type)
|
60
|
+
manifest ? manifest.handler.new : nil
|
101
61
|
end
|
102
62
|
end
|
103
63
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailwayIpc
|
4
|
+
class ProcessIncomingMessage
|
5
|
+
class UnknownMessageJob
|
6
|
+
attr_reader :incoming_message, :logger
|
7
|
+
|
8
|
+
def initialize(incoming_message, logger)
|
9
|
+
@incoming_message = incoming_message
|
10
|
+
@logger = logger
|
11
|
+
end
|
12
|
+
|
13
|
+
def status
|
14
|
+
'unknown_message_type'
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
logger.warn(
|
19
|
+
"Ignoring unknown message of type '#{incoming_message.type}'",
|
20
|
+
feature: 'railway_ipc_consumer',
|
21
|
+
protobuf: { type: incoming_message.type, data: incoming_message.decoded }
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class IgnoredMessageJob
|
27
|
+
attr_reader :incoming_message, :logger
|
28
|
+
|
29
|
+
def initialize(incoming_message, logger)
|
30
|
+
@incoming_message = incoming_message
|
31
|
+
@logger = logger
|
32
|
+
end
|
33
|
+
|
34
|
+
def status
|
35
|
+
'ignored'
|
36
|
+
end
|
37
|
+
|
38
|
+
def run
|
39
|
+
logger.warn(
|
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 }
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class NormalMessageJob
|
48
|
+
attr_reader :incoming_message, :handler, :status
|
49
|
+
|
50
|
+
def initialize(incoming_message, handler)
|
51
|
+
@incoming_message = incoming_message
|
52
|
+
@handler = handler
|
53
|
+
@status = 'not_processed'
|
54
|
+
end
|
55
|
+
|
56
|
+
def run
|
57
|
+
result = handler.handle(incoming_message.decoded)
|
58
|
+
@status = result.success? ? RailwayIpc::ConsumedMessage::STATUS_SUCCESS : RailwayIpc::ConsumedMessage::STATUS_FAILED_TO_PROCESS
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_reader :consumer, :incoming_message, :logger
|
63
|
+
|
64
|
+
def self.call(consumer, incoming_message)
|
65
|
+
new(consumer, incoming_message).call
|
66
|
+
end
|
67
|
+
|
68
|
+
def initialize(consumer, incoming_message, logger: RailwayIpc.logger)
|
69
|
+
@consumer = consumer
|
70
|
+
@incoming_message = incoming_message
|
71
|
+
@logger = logger
|
72
|
+
end
|
73
|
+
|
74
|
+
def call
|
75
|
+
raise_message_invalid_error unless incoming_message.valid?
|
76
|
+
message = find_or_create_consumed_message
|
77
|
+
return if message.processed?
|
78
|
+
|
79
|
+
message.update_with_lock(classify_message)
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def raise_message_invalid_error
|
85
|
+
error = "Message is invalid: #{incoming_message.stringify_errors}."
|
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
|
+
)
|
93
|
+
raise RailwayIpc::IncomingMessage::InvalidMessage.new(error)
|
94
|
+
end
|
95
|
+
|
96
|
+
def find_or_create_consumed_message
|
97
|
+
RailwayIpc::ConsumedMessage.find_by(uuid: incoming_message.uuid, queue: consumer.queue_name) ||
|
98
|
+
RailwayIpc::ConsumedMessage.create_processing(consumer, incoming_message)
|
99
|
+
end
|
100
|
+
|
101
|
+
def classify_message
|
102
|
+
if incoming_message.decoded.is_a?(RailwayIpc::Messages::Unknown)
|
103
|
+
UnknownMessageJob.new(incoming_message, logger)
|
104
|
+
elsif (handler = consumer.get_handler(incoming_message.type))
|
105
|
+
NormalMessageJob.new(incoming_message, handler)
|
106
|
+
else
|
107
|
+
IgnoredMessageJob.new(incoming_message, logger)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|