Class: RServiceBus2::HandlerLoader

Inherits:
Object
  • Object
show all
Defined in:
lib/rservicebus2/handler_loader.rb

Overview

Given a directory, this class is responsible for finding

msgnames,
handlernames, and
loading handlers

Instance Method Summary collapse

Constructor Details

#initialize(host, handler_manager) ⇒ HandlerLoader

Constructor

Parameters:

  • host (RServiceBus2::Host)

    instance

  • appResources (Hash)

    As hash where k is the name of a resource, and v is the resource



16
17
18
19
20
21
22
# File 'lib/rservicebus2/handler_loader.rb', line 16

def initialize(host, handler_manager)
  @host = host

  @handler_manager = handler_manager

  @list_of_loaded_paths = {}
end

Instance Method Details

#get_list_of_files_for_dir(path) ⇒ Array

This method is overloaded for unit tests

Parameters:

  • path (String)

    directory to check

Returns:

  • (Array)

    a list of paths to files found in the given path



95
96
97
98
99
100
# File 'lib/rservicebus2/handler_loader.rb', line 95

def get_list_of_files_for_dir(path)
  list = Dir["#{path}/*"]
  RServiceBus2.rlog "HandlerLoader.getListOfFilesForDir. path: #{path},
    list: #{list}"
  list
end

#get_msg_name(file_path) ⇒ Object

Extract the top level dir or file name as it is the msg name

Parameters:

  • file_path (String)

    path to check - this can be a directory or file



127
128
129
130
131
# File 'lib/rservicebus2/handler_loader.rb', line 127

def get_msg_name(file_path)
  base_name = File.basename(file_path)
  ext_name = File.extname(base_name)
  base_name.sub(ext_name, '')
end

#get_require_path(file_path) ⇒ Object

Cleans the given path to ensure it can be used for as a parameter for the require statement.

Parameters:

  • file_path (String)

    the path to be cleaned



26
27
28
29
30
31
32
# File 'lib/rservicebus2/handler_loader.rb', line 26

def get_require_path(file_path)
  file_path = "./#{file_path}" unless file_path.start_with?('/')

  return file_path.sub('.rb', '') if File.exist?(file_path)

  abort("Filepath, #{file_path}, given for messagehandler require doesn't exist")
end

#load_handler(msg_name, file_path, handler_name) ⇒ Object

Wrapper function

rubocop:disable Metrics/MethodLength

Parameters:

  • file_path (String)
  • handler_name (String)


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/rservicebus2/handler_loader.rb', line 66

def load_handler(msg_name, file_path, handler_name)
  if @list_of_loaded_paths.key?(file_path)
    RServiceBus2.log "Not reloading, #{file_path}"
    return
  end

  begin
    RServiceBus2.rlog "file_path: #{file_path}"
    RServiceBus2.rlog "handler_name: #{handler_name}"

    handler = load_handler_from_file(handler_name, file_path)
    RServiceBus2.log "Loaded Handler: #{handler_name}"

    @handler_manager.add_handler(msg_name, handler)

    @list_of_loaded_paths[file_path] = 1
  rescue StandardError => e
    puts "Exception loading handler from file: #{file_path}"
    puts e.message
    puts e.backtrace[0]
    abort
  end
end

#load_handler_from_file(handler_name, file_path) ⇒ RServiceBus2::Handler

Instantiate the handler named in handlerName from the file name in file_path. Exceptions will be raised if encountered when loading handlers. This is a load time activity, so handlers should load correctly. As much information as possible is returned to enable the handler to be fixed, or configuration corrected. rubocop:disable Metrics/MethodLength

Parameters:

  • handler_name (String)

    name of the handler to instantiate

  • file_path (String)

    the path to the file to be loaded

Returns:

  • (RServiceBus2::Handler)

    the loader



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/rservicebus2/handler_loader.rb', line 43

def load_handler_from_file(handler_name, file_path)
  require_path = get_require_path(file_path)

  require require_path
  begin
    handler = Object.const_get(handler_name).new
  rescue StandardError => e
    puts "Expected class name: #{handler_name}, not found after require: #{require_path}\n" \
         "**** Check in #{file_path} that the class is named: #{handler_name}\n" \
         '( In case its not that )'
    raise e
  end

  handler
end

#load_handlers_from_path(base_dir) ⇒ Object

Entry point for loading handlers

Parameters:

  • baseDir (String)

    directory to check - should not have trailing slash



164
165
166
167
168
# File 'lib/rservicebus2/handler_loader.rb', line 164

def load_handlers_from_path(base_dir)
  load_handlers_from_top_level_path(base_dir)

  self
end

#load_handlers_from_second_level_path(msg_name, base_dir) ⇒ Object

Multiple handlers for the same msg can be placed inside a top level directory. The msg name is than taken from the directory, and the handlers from the files inside that directory

Parameters:

  • msg_name (String)

    name of message

  • base_dir (String)

    directory to check for handlers of [msg_name]



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/rservicebus2/handler_loader.rb', line 108

def load_handlers_from_second_level_path(msg_name, base_dir)
  get_list_of_files_for_dir(base_dir).each do |file_path|
    next if file_path.end_with?('.')
    next unless !File.directory?(file_path) && File.extname(file_path) == '.rb'

    file_name = File.basename(file_path).sub('.rb', '')
    # Classify
    handler_name = "message_handler_#{msg_name}_#{file_name}"
                   .gsub(/(?<=_|^)(\w)/) { Regexp.last_match(1).upcase }.gsub(/(?:_)(\w)/, '\1')

    load_handler(msg_name, file_path, handler_name)
  end

  self
end

#load_handlers_from_top_level_path(base_dir) ⇒ Object

Load top level handlers from the given directory

rubocop:disable Metrics/MethodLength

Parameters:

  • baseDir (String)

    directory to check - should not have trailing slash



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/rservicebus2/handler_loader.rb', line 137

def load_handlers_from_top_level_path(base_dir)
  RServiceBus2.rlog "HandlerLoader.loadHandlersFromTopLevelPath. baseDir: #{base_dir}"
  get_list_of_files_for_dir(base_dir).each do |file_path|
    next if file_path.end_with?('.')

    msg_name = get_msg_name(file_path)
    YamlSafeLoader.instance.add_permitted_class(msg_name
                   .gsub(/(?<=_|^)(\w)/) { Regexp.last_match(1).upcase }.gsub(/(?:_)(\w)/, '\1'))
    if File.directory?(file_path)
      load_handlers_from_second_level_path(msg_name, file_path)
      next
    end

    # Classify
    handler_name = "message_handler_#{msg_name}"
                   .gsub(/(?<=_|^)(\w)/) { Regexp.last_match(1).upcase }.gsub(/(?:_)(\w)/, '\1')
    load_handler(msg_name, file_path, handler_name)
  end

  self
end