railway-ipc 0.1.4 → 1.0.1
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 +43 -0
- data/Gemfile +2 -2
- data/README.md +1 -1
- data/Rakefile +10 -4
- data/bin/console +3 -3
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/lib/railway_ipc.rb +6 -4
- data/lib/railway_ipc/Rakefile +2 -0
- data/lib/railway_ipc/consumer/consumer.rb +21 -81
- data/lib/railway_ipc/consumer/consumer_response_handlers.rb +2 -0
- data/lib/railway_ipc/consumer/process_incoming_message.rb +105 -0
- data/lib/railway_ipc/errors.rb +9 -1
- data/lib/railway_ipc/handler.rb +5 -6
- data/lib/railway_ipc/handler_manifest.rb +2 -0
- data/lib/railway_ipc/handler_store.rb +3 -0
- data/lib/railway_ipc/incoming_message.rb +51 -0
- data/lib/railway_ipc/logger.rb +4 -3
- data/lib/railway_ipc/models/consumed_message.rb +41 -27
- data/lib/railway_ipc/models/published_message.rb +11 -9
- data/lib/railway_ipc/publisher.rb +58 -1
- data/lib/railway_ipc/rabbitmq/adapter.rb +24 -14
- data/lib/railway_ipc/rabbitmq/payload.rb +9 -4
- data/lib/railway_ipc/railtie.rb +2 -0
- data/lib/railway_ipc/responder.rb +6 -3
- data/lib/railway_ipc/response.rb +4 -1
- data/lib/railway_ipc/rpc/client/client.rb +27 -17
- 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 +10 -3
- 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 +3 -1
- data/priv/migrations/add_railway_ipc_published_messages.rb +3 -1
- data/railway_ipc.gemspec +33 -30
- metadata +64 -65
- data/.rspec +0 -3
- data/.tool-versions +0 -1
- data/.travis.yml +0 -7
- data/Gemfile.lock +0 -186
- data/lib/railway_ipc/base_message.pb.rb +0 -21
- 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: 6b0a9b840874946f0f7e80b0221e3df161eed5ce0926299356856cb5b81f76db
         | 
| 4 | 
            +
              data.tar.gz: 252e1f3e84801e50cfccc47d6674c985a690e514cd2732b62c5f6cbbef71f0fc
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 69cde1dbbfcabb1ed5f3a27ace4a126f7cf231096aa8b8761c6ac3f19f0c36a4a79183a44140367117eab13f01e1507e53ef9a484abb89510df17ff040395407
         | 
| 7 | 
            +
              data.tar.gz: a2a85998d976faa746820474bb9e5597964bb92f379b95b7b55cc5936a72af532d3b5321d3228194f4209dbdab3b76dc430dbd2d357df33e9929ff3748465b6a
         | 
    
        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,43 @@ | |
| 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 | 
            +
            ## [1.0.1] - 2020-07-23
         | 
| 14 | 
            +
            ### Fixed
         | 
| 15 | 
            +
            * Fix publisher connection by using default connection if one isn't provided
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            ## [1.0.0] - 2020-07-20
         | 
| 18 | 
            +
            ### Added
         | 
| 19 | 
            +
            * CircleCI build that runs the specs
         | 
| 20 | 
            +
            * Rubocop (also ran by CircleCI)
         | 
| 21 | 
            +
            * New error types for incoming messages
         | 
| 22 | 
            +
            * RailwayIpc::Messages::Unknown protobuf
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            ### Changed
         | 
| 25 | 
            +
            * Refactored worker to use ProcessIncomingMessage and IncomingMessage abstractions
         | 
| 26 | 
            +
            * Moved decoding logic from ConsumedMessage to IncomingMessage
         | 
| 27 | 
            +
            * Removed STATUSES constant from ConsumedMessage
         | 
| 28 | 
            +
            * Publisher is no longer a Singleton; kept a Singleton version of the Publisher for backwards compatibility that gives a "deprecated" warning
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            ### Removed
         | 
| 31 | 
            +
            * Removed `BaseMessage` protobuf
         | 
| 32 | 
            +
            * NullMessage and NullHandler were removed
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            ### Fixed
         | 
| 35 | 
            +
            * Fixed all Rubocop warnings and errors
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            ## [0.1.7] - 2020-06-29
         | 
| 38 | 
            +
            ### Added
         | 
| 39 | 
            +
            - 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)
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            [Unreleased]: https://github.com/learn-co/railway_ipc_gem/compare/v1.0.0...HEAD
         | 
| 42 | 
            +
            [1.0.0]: https://github.com/learn-co/railway_ipc_gem/compare/v0.1.7...v1.0.0
         | 
| 43 | 
            +
            [0.1.7]: https://github.com/learn-co/railway_ipc_gem/releases/tag/v0.1.7
         | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -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,26 +1,28 @@ | |
| 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
         | 
    
        data/lib/railway_ipc/Rakefile
    CHANGED
    
    
| @@ -1,11 +1,10 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
            require  | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'railway_ipc/consumer/consumer_response_handlers'
         | 
| 4 4 |  | 
| 5 5 | 
             
            module RailwayIpc
         | 
| 6 6 | 
             
              class Consumer
         | 
| 7 7 | 
             
                include Sneakers::Worker
         | 
| 8 | 
            -
                attr_reader :message, :handler, :protobuff_message, :delivery_info, :decoded_payload
         | 
| 9 8 |  | 
| 10 9 | 
             
                def self.listen_to(queue:, exchange:)
         | 
| 11 10 | 
             
                  from_queue queue,
         | 
| @@ -23,90 +22,31 @@ module RailwayIpc | |
| 23 22 | 
             
                  ConsumerResponseHandlers.instance.registered
         | 
| 24 23 | 
             
                end
         | 
| 25 24 |  | 
| 26 | 
            -
                def  | 
| 27 | 
            -
                   | 
| 28 | 
            -
                  @decoded_payload = RailwayIpc::Rabbitmq::Payload.decode(payload)
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                  case decoded_payload.type
         | 
| 31 | 
            -
                  when *registered_handlers
         | 
| 32 | 
            -
                    @handler = handler_for(decoded_payload)
         | 
| 33 | 
            -
                    message_klass = message_handler_for(decoded_payload)
         | 
| 34 | 
            -
                    @protobuff_message = message_klass.decode(decoded_payload.message)
         | 
| 35 | 
            -
                    process_known_message_type
         | 
| 36 | 
            -
                  else
         | 
| 37 | 
            -
                    @handler = RailwayIpc::NullHandler.new
         | 
| 38 | 
            -
                    @protobuff_message = RailwayIpc::BaseMessage.decode(decoded_payload.message)
         | 
| 39 | 
            -
                    process_unknown_message_type
         | 
| 40 | 
            -
                  end
         | 
| 41 | 
            -
             | 
| 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
         | 
| 25 | 
            +
                def queue_name
         | 
| 26 | 
            +
                  queue.name
         | 
| 50 27 | 
             
                end
         | 
| 51 28 |  | 
| 52 | 
            -
                 | 
| 53 | 
            -
             | 
| 54 | 
            -
                def process_protobuff!(message)
         | 
| 55 | 
            -
                  if handler.handle(protobuff_message).success?
         | 
| 56 | 
            -
                    message.status = RailwayIpc::ConsumedMessage::STATUSES[:success]
         | 
| 57 | 
            -
                  else
         | 
| 58 | 
            -
                    message.status = RailwayIpc::ConsumedMessage::STATUSES[:failed_to_process]
         | 
| 59 | 
            -
                  end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                  message.save!
         | 
| 29 | 
            +
                def exchange_name
         | 
| 30 | 
            +
                  queue.opts[:exchange]
         | 
| 62 31 | 
             
                end
         | 
| 63 32 |  | 
| 64 | 
            -
                def  | 
| 65 | 
            -
                  message = RailwayIpc:: | 
| 66 | 
            -
             | 
| 67 | 
            -
                   | 
| 68 | 
            -
             | 
| 69 | 
            -
                   | 
| 70 | 
            -
                     | 
| 71 | 
            -
             | 
| 72 | 
            -
                    message | 
| 73 | 
            -
                     | 
| 74 | 
            -
                  end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                  nil
         | 
| 77 | 
            -
                end
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                def process_unknown_message_type
         | 
| 80 | 
            -
                  handler.ack!
         | 
| 81 | 
            -
             | 
| 82 | 
            -
                  if RailwayIpc::ConsumedMessage.exists?(uuid: protobuff_message.uuid)
         | 
| 83 | 
            -
                    return
         | 
| 84 | 
            -
                  else
         | 
| 85 | 
            -
                    create_message_with_status!(RailwayIpc::ConsumedMessage::STATUSES[:unknown_message_type])
         | 
| 86 | 
            -
                  end
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                  nil
         | 
| 89 | 
            -
                end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                def create_message_with_status!(status)
         | 
| 92 | 
            -
                  RailwayIpc::ConsumedMessage.create!(
         | 
| 93 | 
            -
                    uuid: protobuff_message.uuid,
         | 
| 94 | 
            -
                    status: status,
         | 
| 95 | 
            -
                    message_type: decoded_payload.type,
         | 
| 96 | 
            -
                    user_uuid: protobuff_message.user_uuid,
         | 
| 97 | 
            -
                    correlation_id: protobuff_message.correlation_id,
         | 
| 98 | 
            -
                    queue: delivery_info.consumer.queue.name,
         | 
| 99 | 
            -
                    exchange: delivery_info.exchange,
         | 
| 100 | 
            -
                    encoded_message: decoded_payload.message
         | 
| 33 | 
            +
                def work(payload)
         | 
| 34 | 
            +
                  message = RailwayIpc::IncomingMessage.new(payload)
         | 
| 35 | 
            +
                  RailwayIpc::ProcessIncomingMessage.call(self, message)
         | 
| 36 | 
            +
                  ack!
         | 
| 37 | 
            +
                rescue StandardError => e
         | 
| 38 | 
            +
                  RailwayIpc.logger.log_exception(
         | 
| 39 | 
            +
                    feature: 'railway_consumer',
         | 
| 40 | 
            +
                    error: e.class,
         | 
| 41 | 
            +
                    error_message: e.message,
         | 
| 42 | 
            +
                    payload: payload
         | 
| 101 43 | 
             
                  )
         | 
| 44 | 
            +
                  raise e
         | 
| 102 45 | 
             
                end
         | 
| 103 46 |  | 
| 104 | 
            -
                def  | 
| 105 | 
            -
                  ConsumerResponseHandlers.instance.get( | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
                def handler_for(decoded_payload)
         | 
| 109 | 
            -
                  ConsumerResponseHandlers.instance.get(decoded_payload.type).handler.new
         | 
| 47 | 
            +
                def get_handler(type)
         | 
| 48 | 
            +
                  manifest = ConsumerResponseHandlers.instance.get(type)
         | 
| 49 | 
            +
                  manifest ? manifest.handler.new : nil
         | 
| 110 50 | 
             
                end
         | 
| 111 51 | 
             
              end
         | 
| 112 52 | 
             
            end
         | 
| @@ -0,0 +1,105 @@ | |
| 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 | 
            +
                      incoming_message.decoded,
         | 
| 20 | 
            +
                      "Ignoring unknown message of type '#{incoming_message.type}'"
         | 
| 21 | 
            +
                    )
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                class IgnoredMessageJob
         | 
| 26 | 
            +
                  attr_reader :incoming_message, :logger
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def initialize(incoming_message, logger)
         | 
| 29 | 
            +
                    @incoming_message = incoming_message
         | 
| 30 | 
            +
                    @logger = logger
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  def status
         | 
| 34 | 
            +
                    'ignored'
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def run
         | 
| 38 | 
            +
                    logger.warn(
         | 
| 39 | 
            +
                      incoming_message.decoded,
         | 
| 40 | 
            +
                      "Ignoring message, no registered handler for '#{incoming_message.type}'"
         | 
| 41 | 
            +
                    )
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                class NormalMessageJob
         | 
| 46 | 
            +
                  attr_reader :incoming_message, :handler, :status
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def initialize(incoming_message, handler)
         | 
| 49 | 
            +
                    @incoming_message = incoming_message
         | 
| 50 | 
            +
                    @handler = handler
         | 
| 51 | 
            +
                    @status = 'not_processed'
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  def run
         | 
| 55 | 
            +
                    result = handler.handle(incoming_message.decoded)
         | 
| 56 | 
            +
                    @status = result.success? ? RailwayIpc::ConsumedMessage::STATUS_SUCCESS : RailwayIpc::ConsumedMessage::STATUS_FAILED_TO_PROCESS
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                attr_reader :consumer, :incoming_message, :logger
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def self.call(consumer, incoming_message)
         | 
| 63 | 
            +
                  new(consumer, incoming_message).call
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def initialize(consumer, incoming_message, logger: RailwayIpc.logger)
         | 
| 67 | 
            +
                  @consumer = consumer
         | 
| 68 | 
            +
                  @incoming_message = incoming_message
         | 
| 69 | 
            +
                  @logger = logger
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                def call
         | 
| 73 | 
            +
                  raise_message_invalid_error unless incoming_message.valid?
         | 
| 74 | 
            +
                  message = find_or_create_consumed_message
         | 
| 75 | 
            +
                  return if message.processed?
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  message.update_with_lock(classify_message)
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                private
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                def raise_message_invalid_error
         | 
| 83 | 
            +
                  error = "Message is invalid: #{incoming_message.stringify_errors}."
         | 
| 84 | 
            +
                  logger.error(incoming_message.decoded, error)
         | 
| 85 | 
            +
                  raise RailwayIpc::IncomingMessage::InvalidMessage.new(error)
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                def find_or_create_consumed_message
         | 
| 89 | 
            +
                  RailwayIpc::ConsumedMessage.find_by(uuid: incoming_message.uuid) ||
         | 
| 90 | 
            +
                    RailwayIpc::ConsumedMessage.create_processing(consumer, incoming_message)
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                # rubocop:disable Metrics/AbcSize
         | 
| 94 | 
            +
                def classify_message
         | 
| 95 | 
            +
                  if incoming_message.decoded.is_a?(RailwayIpc::Messages::Unknown)
         | 
| 96 | 
            +
                    UnknownMessageJob.new(incoming_message, logger)
         | 
| 97 | 
            +
                  elsif (handler = consumer.get_handler(incoming_message.type))
         | 
| 98 | 
            +
                    NormalMessageJob.new(incoming_message, handler)
         | 
| 99 | 
            +
                  else
         | 
| 100 | 
            +
                    IgnoredMessageJob.new(incoming_message, logger)
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
                # rubocop:enable Metrics/AbcSize
         | 
| 104 | 
            +
              end
         | 
| 105 | 
            +
            end
         |