class Longleaf::ServiceClassCache

Cache for loading and retrieving preservation service classes

Constants

STD_PRESERVATION_SERVICE_PATH

Public Class Methods

new(app_manager) click to toggle source
# File lib/longleaf/services/service_class_cache.rb, line 8
def initialize(app_manager)
  @app_manager = app_manager
  # Cache storing per service definition instances of service classes
  @service_instance_cache = Hash.new
  # Cache storing per script path class of service
  @class_cache = Hash.new
end

Public Instance Methods

service_class(service_def) click to toggle source

Load and return the PreservationService class assigned to the provided service definition, based on the work_script and work_class properties provided.

@param service_def [ServiceDefinition] definition of service to retrieve class for @return [Class] class of work_script

# File lib/longleaf/services/service_class_cache.rb, line 38
def service_class(service_def)
  service_name = service_def.name
  work_script = service_def.work_script

  if work_script.include?('/')
    expanded_path = Pathname.new(work_script).expand_path.to_s
    if !from_permitted_path?(expanded_path)
      raise ConfigurationError.new("Unable to load work_script for service #{service_name}, #{work_script} is not in a known library path.")
    end

    last_slash_index = work_script.rindex('/')
    script_path = work_script[0..last_slash_index]
    script_name = work_script[(last_slash_index + 1)..-1]
  else
    script_path = STD_PRESERVATION_SERVICE_PATH
    script_name = work_script
  end

  # Strip off the extension
  script_name.sub!('.rb', '')

  require_path = File.join(script_path, script_name)
  # Return the cached Class if this path has been encountered before
  if @class_cache.key?(require_path)
    return @class_cache[require_path]
  end

  # Load the script
  begin
    require require_path
  rescue LoadError
    raise ConfigurationError.new("Failed to load work_script '#{script_name}' for service #{service_name}")
  end

  # Generate the class name, either configured or from file naming convention if possible
  if service_def.work_class
    class_name = service_def.work_class
  else
    class_name = script_name.split('_').map(&:capitalize).join
    # Assume the longleaf module for classes in the standard path
    class_name = 'Longleaf::' + class_name if script_path == STD_PRESERVATION_SERVICE_PATH
  end

  begin
    class_constant = constantize(class_name)
    # cache the class for this work_script and return it
    @class_cache[require_path] = class_constant
  rescue NameError
    raise ConfigurationError.new("Failed to load work_script '#{script_name}' for service #{service_name}, class name #{class_name} was not found.")
  end
end
service_instance(service_def) click to toggle source

Returns an instance of the preversation service defined for the provided service definition, based on the work_script and work_class properties provided.

@param service_def [ServiceDefinition] definition of service to instantiate @return [PreservationService] Instance of the preservation service class for the definition.

# File lib/longleaf/services/service_class_cache.rb, line 21
def service_instance(service_def)
  service_name = service_def.name
  # Return the cached instance of the service
  if @service_instance_cache.key?(service_name)
    return @service_instance_cache[service_name]
  end

  clazz = service_class(service_def)
  # Cache and return the class instance
  @service_instance_cache[service_name] = clazz.new(service_def, @app_manager)
end

Private Instance Methods

constantize(str) click to toggle source

Borrowed from sidekiq implementation

# File lib/longleaf/services/service_class_cache.rb, line 92
def constantize(str)
  names = str.split('::')
  names.shift if names.empty? || names.first.empty?

  names.inject(Object) do |constant, name|
    # the false flag limits search for name to under the constant namespace
    #   which mimics Rails' behaviour
    constant.const_defined?(name, false) ? constant.const_get(name, false) : constant.const_missing(name)
  end
end
from_permitted_path?(script_path) click to toggle source
# File lib/longleaf/services/service_class_cache.rb, line 103
def from_permitted_path?(script_path)
  $LOAD_PATH.each do |lib_path|
    if script_path.start_with?(lib_path)
      return true
    end
  end
  false
end