railway-ipc 0.1.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -3
  3. data/CHANGELOG.md +61 -0
  4. data/Gemfile +2 -2
  5. data/README.md +2 -2
  6. data/Rakefile +10 -4
  7. data/bin/console +3 -3
  8. data/bin/rspec +29 -0
  9. data/bin/rubocop +29 -0
  10. data/lib/railway_ipc.rb +9 -11
  11. data/lib/railway_ipc/Rakefile +2 -0
  12. data/lib/railway_ipc/consumer/consumer.rb +33 -73
  13. data/lib/railway_ipc/consumer/process_incoming_message.rb +111 -0
  14. data/lib/railway_ipc/errors.rb +9 -1
  15. data/lib/railway_ipc/handler.rb +17 -3
  16. data/lib/railway_ipc/handler_store.rb +5 -2
  17. data/lib/railway_ipc/incoming_message.rb +51 -0
  18. data/lib/railway_ipc/logger.rb +32 -26
  19. data/lib/railway_ipc/models/consumed_message.rb +40 -35
  20. data/lib/railway_ipc/models/published_message.rb +11 -9
  21. data/lib/railway_ipc/publisher.rb +77 -3
  22. data/lib/railway_ipc/rabbitmq/adapter.rb +23 -15
  23. data/lib/railway_ipc/rabbitmq/payload.rb +9 -4
  24. data/lib/railway_ipc/railtie.rb +2 -0
  25. data/lib/railway_ipc/responder.rb +10 -3
  26. data/lib/railway_ipc/response.rb +4 -1
  27. data/lib/railway_ipc/rpc/client/client.rb +43 -18
  28. data/lib/railway_ipc/rpc/client/client_response_handlers.rb +2 -0
  29. data/lib/railway_ipc/rpc/client/errors/timeout_error.rb +2 -0
  30. data/lib/railway_ipc/rpc/concerns/error_adapter_configurable.rb +2 -0
  31. data/lib/railway_ipc/rpc/concerns/message_observation_configurable.rb +2 -0
  32. data/lib/railway_ipc/rpc/concerns/publish_location_configurable.rb +2 -0
  33. data/lib/railway_ipc/rpc/rpc.rb +2 -0
  34. data/lib/railway_ipc/rpc/server/server.rb +25 -7
  35. data/lib/railway_ipc/rpc/server/server_response_handlers.rb +2 -0
  36. data/lib/railway_ipc/tasks/generate_migrations.rake +16 -16
  37. data/lib/railway_ipc/tasks/start_consumers.rake +3 -1
  38. data/lib/railway_ipc/tasks/start_servers.rake +3 -1
  39. data/lib/railway_ipc/unhandled_message_error.rb +2 -0
  40. data/lib/railway_ipc/unknown_message.pb.rb +18 -0
  41. data/lib/railway_ipc/version.rb +3 -1
  42. data/priv/migrations/add_railway_ipc_consumed_messages.rb +5 -3
  43. data/priv/migrations/add_railway_ipc_published_messages.rb +3 -1
  44. data/railway_ipc.gemspec +34 -30
  45. metadata +65 -66
  46. data/.rspec +0 -3
  47. data/.travis.yml +0 -7
  48. data/Gemfile.lock +0 -186
  49. data/lib/railway_ipc/base_message.pb.rb +0 -21
  50. data/lib/railway_ipc/consumer/consumer_response_handlers.rb +0 -14
  51. data/lib/railway_ipc/handler_manifest.rb +0 -10
  52. data/lib/railway_ipc/null_handler.rb +0 -7
  53. data/lib/railway_ipc/null_message.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 110c82fedd170e47574c5cce683f08a1bad9b6fe27ce4ed91428c04153b4c317
4
- data.tar.gz: 70da4ff747fbb8ca79f161c3e8148d7034ed1975ad5a9aa5f5f619d67e30dd31
3
+ metadata.gz: 11e49c11ff3e5815f7c8050ad5fcdfde1510cf7646d10cfa5d1104a5c1868422
4
+ data.tar.gz: 3fbdeab2e555f9c4b3402cf27e3b072d33c833f85659eaccc09f31d11fddc219
5
5
  SHA512:
6
- metadata.gz: ffa82d046eacfd17e63bd27c99a3078ed0fa7a5e9521e28b87e29bbda3da81167ec6d8940657c4d5fc298c814872910c3bbe8e11f82e17333fc7aa547a95c151
7
- data.tar.gz: c332dfdb14d28209fe2f07ded7784bd5a82c98b5cb2810a547ddfb3f406d8879a9aab3f74ff44c0d8555f99de0a947e96fba3333626d2f5e7efe00e024118101
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/*
@@ -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
@@ -1,5 +1,5 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  gemspec
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
@@ -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
- RABBITMQ_CONNECTION_URL=amqp://<railway_user>:<railway_password>@localhost:5672
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
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
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 :default => :spec
7
- task :test => :spec
8
+ task default: %i[spec lint]
9
+
10
+ desc 'Lint code with Rubocop'
11
+ task :lint do
12
+ exec('./bin/rubocop .')
13
+ end
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "railway_ipc"
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 "pry"
9
+ require 'pry'
10
10
  Pry.start
@@ -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")
@@ -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")
@@ -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/null_message'
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(logger: ::Logger.new(STDOUT))
31
- @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)
32
34
  end
33
35
 
34
36
  def self.logger
35
- @logger || RailwayIpc::Logger.new(::Logger.new(STDOUT))
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'railway_ipc'
2
4
 
3
5
  path = File.expand_path(__dir__)
@@ -1,11 +1,15 @@
1
- require "json"
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
- attr_reader :message, :handler, :protobuf_message, :delivery_info, :decoded_payload, :encoded_message
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
- ConsumerResponseHandlers.instance.register(message: message_type, handler: with)
23
+ handlers.register(message: message_type, handler: with)
20
24
  end
21
25
 
22
- def registered_handlers
23
- ConsumerResponseHandlers.instance.registered
26
+ def handlers
27
+ self.class.handlers
24
28
  end
25
29
 
26
- def work_with_params(payload, delivery_info, _metadata)
27
- @delivery_info = delivery_info
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 process_known_message_type
62
- message = RailwayIpc::ConsumedMessage.find_by(uuid: protobuf_message.uuid)
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 process_unknown_message_type
75
- if RailwayIpc::ConsumedMessage.exists?(uuid: protobuf_message.uuid)
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 create_message_with_status!(status)
83
- RailwayIpc::ConsumedMessage.create!(
84
- uuid: protobuf_message.uuid,
85
- status: status,
86
- message_type: decoded_payload.type,
87
- user_uuid: protobuf_message.user_uuid,
88
- correlation_id: protobuf_message.correlation_id,
89
- queue: delivery_info.consumer.queue.name,
90
- exchange: delivery_info.exchange,
91
- encoded_message: encoded_message
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 message_handler_for(decoded_payload)
96
- ConsumerResponseHandlers.instance.get(decoded_payload.type).message
97
- end
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