require 'tochtli/version' require 'tochtli/engine' if defined?(::Rails) require 'bunny' require 'json' require 'uber/inheritable_attr' require 'virtus' unless defined?(ActiveSupport) require 'facets/module/cattr' require 'facets/array/extract_options' require 'facets/hash/symbolize_keys' require 'facets/hash/except' require 'facets/string/underscore' require 'facets/array/extract_options' require 'facets/string/camelcase' class String # ActiveSupport compatibility def camelize split('::').map { |s| s.camelcase(true) }.join('::') end end end module Tochtli autoload :RabbitConnection, 'tochtli/rabbit_connection' autoload :Application, 'tochtli/application' autoload :Middleware, 'tochtli/application' autoload :BaseController, 'tochtli/base_controller' autoload :BaseClient, 'tochtli/base_client' autoload :ControllerManager, 'tochtli/controller_manager' autoload :SimpleValidation, 'tochtli/simple_validation' autoload :Message, 'tochtli/message' autoload :ReplyQueue, 'tochtli/reply_queue' autoload :RabbitClient, 'tochtli/rabbit_client' autoload :Test, 'tochtli/test' autoload :ActiveRecordConnectionCleaner, 'tochtli/active_record_connection_cleaner' class MessageError < StandardError attr_reader :tochtli_message def initialize(error_message, tochtli_message) super error_message @tochtli_message = tochtli_message end end class InvalidMessageError < MessageError end class MessageDropped < MessageError end class << self # Global logger for services (default: RAILS_ROOT/log/service.log) attr_writer :logger # Global cache store for services (default: Rails.cache) attr_writer :cache # If set to true bunny log level would be set to DEBUG (by default it is WARN) attr_accessor :debug_bunny def logger unless @logger if defined?(Rails) @logger = Logger.new(File.join(Rails.root, 'log/service.log')) @logger.level = Rails.env.production? ? Logger::WARN : Logger::DEBUG else @logger = Logger.new(STDERR) @logger.level = Logger::WARN end end @logger end def cache if !@cache && defined?(Rails) @cache = Rails.cache end @cache end def application unless @application @application = Tochtli::Application.new @application.use_default_middlewares end @application end # Should be invoked only once def load_services eager_load_service_messages eager_load_service_controllers end def start_services(rabbit_config=nil, logger=nil) ControllerManager.setup(config: rabbit_config, logger: logger) ControllerManager.start true rescue if logger logger.error "Error during service start" logger.error "#{$!.class}: #{$!}" logger.error $!.backtrace.join("\n") end false end def stop_services(logger=nil) ControllerManager.stop true rescue if logger logger.error "Error during service stop" logger.error "#{$!.class}: #{$!}" logger.error $!.backtrace.join("\n") end false end def services_running? ControllerManager.running? end def restart_services(rabbit_config=nil, logger=nil) ControllerManager.stop if ControllerManager.running? ControllerManager.start(rabbit_config, logger) true rescue if logger logger.error "Error during service restart" logger.error "#{$!.class}: #{$!}" logger.error $!.backtrace.join("\n") end false end def eager_load_service_messages existent_engine_paths('messages').each do |load_path| Dir.glob("#{load_path}/**/*.rb").sort.each do |file| require file end end end def eager_load_service_controllers existent_engine_paths('controllers').each do |load_path| Dir.glob("#{load_path}/**/*.rb").sort.each do |file| require file end end end def existent_engine_paths(type) engines = ::Rails::Engine.subclasses.map(&:instance) engines += [Rails.application] engines.collect do |railtie| railtie.paths["service/#{type}"].try(:existent) end.compact.flatten end end end #### # TEMPORARY see: https://github.com/apotonick/uber/pull/10 #### class Uber::InheritableAttr::Clone def self.uncloneable [Symbol, TrueClass, FalseClass, NilClass, Numeric] end end