Skip to content

Commit

Permalink
Merge pull request #191 from lyrasis/err-handling
Browse files Browse the repository at this point in the history
Improve lookup file prep failure error handling
  • Loading branch information
kspurgin authored Sep 19, 2023
2 parents b65cb79 + 0d30b53 commit 46c147a
Show file tree
Hide file tree
Showing 13 changed files with 208 additions and 98 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ These changes are merged into the `main` branch, but have not been released. Aft

=== Dev

* Improve error handling for resolution of lookups for individual jobs (PR#191)

== Releases

=== 4.0.1 - 2023-09-13
Expand Down
77 changes: 77 additions & 0 deletions lib/kiba/extend/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,83 @@ class IterativeCleanupSettingUndefinedError < StandardError
include Kiba::Extend::ErrMod
end

class JobCannotBeUsedAsLookupError < TypeError
include Kiba::Extend::ErrMod
def initialize(key, klass, for_job)
@key = key
@klass = klass
@for_job = for_job
@msg = ":#{key} cannot be used as a lookup in :#{for_job} because "\
"its src_class (#{klass}) does not include "\
"Kiba::Extend::Soures::Lookupable"
super(msg)
end

def formatted
<<~STR
JOB FAILED: LOOKUP FILE SETUP ERROR FOR: #{for_job}
#{msg}
STR
end

private

attr_reader :key, :klass, :for_job, :type, :msg
end

# Exception raised if {Kiba::Extend::FileRegistry} contains no lookup
# key for file
class NoLookupOnError < NameError
include Kiba::Extend::ErrMod
# @param filekey [Symbol] key not found in
# {Kiba::Extend::FileRegistry}
def initialize(filekey, for_job)
@filekey = filekey
@for_job = for_job
msg = "No lookup_on value in registry entry hash for :#{filekey} -- "\
"Used as lookup in job: :#{for_job})"
super(msg)
end

def formatted
<<~STR
JOB FAILED: LOOKUP FILE SETUP ERROR FOR: #{for_job}
To fix: Add `lookup_on` to registry entry hash for
:#{filekey}
STR
end

private

attr_reader :filekey, :for_job
end

# Exception raised if the lookup key value for the file is not a Symbol
class NonSymbolLookupOnError < TypeError
include Kiba::Extend::ErrMod
# @param filekey [Symbol] registry entry key having the non-symbol
# `lookup_on` value
def initialize(filekey, for_job)
@filekey = filekey
@for_job = for_job
@msg = "The `lookup_on` value in the registry entry hash for "\
":#{filekey} is not a Ruby Symbol. "\
"Prepend a : to the field name to fix."
super(msg)
end

def formatted
<<~STR
JOB FAILED: LOOKUP FILE SETUP ERROR FOR: #{for_job}
#{msg}
STR
end

private

attr_reader :filekey, :for_job, :msg
end

class ProjectSettingUndefinedError < StandardError
include Kiba::Extend::ErrMod
end
Expand Down
25 changes: 17 additions & 8 deletions lib/kiba/extend/jobs/base_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ class BaseJob
# running any necessary jobs to create sources and/or lookups needed
# by the job. :run does all of the above and runs the job. Since 4.0.0
def initialize(files:, transformer:, mode: :run)
@destination_key = files[:destination].is_a?(Symbol) ?
files[:destination] :
files[:destination].first

if caller(2, 5).join(" ")["block in handle_requirements"]
@dependency = true
end
Expand Down Expand Up @@ -60,6 +64,8 @@ def run

private

attr_reader :destination_key

def job_data
@files[:destination].first.data
end
Expand All @@ -70,7 +76,8 @@ def setup_files(files)
tmp = {}
files.each do |type, arr|
meth = Kiba::Extend.registry.method("as_#{type}")
tmp[type] = [arr].flatten.map { |key| prep_file(meth, key) }
tmp[type] = [arr].flatten
.map { |key| prep_file(meth, key, destination_key) }
end
tmp
end
Expand All @@ -90,13 +97,15 @@ def pre_process
end
end

def prep_file(meth, key)
meth.call(key)
# rubocop:todo Layout/LineLength
rescue Kiba::Extend::Registry::FileRegistry::KeyNotRegisteredError => err
# rubocop:enable Layout/LineLength
puts "JOB FAILED: TRANSFORM ERROR IN: #{err.calling_job}"
err.info
def prep_file(meth, key, for_job)
meth.call(key, for_job)
rescue Kiba::Extend::ErrMod => err
if err.respond_to?(:formatted)
puts err.formatted
else
puts "JOB FAILED: TRANSFORM ERROR IN: #{err.calling_job}"
err.info
end
exit
end

Expand Down
58 changes: 38 additions & 20 deletions lib/kiba/extend/registry/file_registry.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

# rubocop:todo Layout/LineLength

require "dry-container"

require_relative "registered_source"
Expand All @@ -13,10 +11,12 @@
module Kiba
module Extend
module Registry
# Transforms a file_registry hash into an object that can return source, lookup, or destination
# config for that file, for passing to jobs
# Transforms a file_registry hash into an object that can return
# source, lookup, or destination config for that file, for
# passing to jobs
#
# An example of a file registry setup in a project can be found at:
# An example of a file registry setup in a project can be found
# at:
# https://github.com/lyrasis/fwm-cspace-migration/blob/main/lib/fwm/registry_data.rb
class FileRegistry
include Dry::Container::Mixin
Expand All @@ -39,26 +39,41 @@ def initialize(key, type = nil)
end
end

# @param filekey [String, Symbol] file registry key for file to be used as destination
# @param filekey [String, Symbol] file registry key for file
# to be used as destination
# @return [Kiba::Extend::Registry::RegisteredDestination]
def as_destination(filekey)
RegisteredDestination.new(key: filekey, data: lookup(filekey))
def as_destination(filekey, for_job)
RegisteredDestination.new(
key: filekey,
data: lookup(filekey),
for_job: for_job
)
rescue KeyNotRegisteredError => err
raise KeyNotRegisteredError.new(err.key, :destination)
end

# @param filekey [String, Symbol] file registry key for file to be used as a lookup source
# @param filekey [String, Symbol] file registry key for file to be used
# as a lookup source
# @return [Kiba::Extend::Registry::RegisteredLookup]
def as_lookup(filekey)
RegisteredLookup.new(key: filekey, data: lookup(filekey))
def as_lookup(filekey, for_job)
RegisteredLookup.new(
key: filekey,
data: lookup(filekey),
for_job: for_job
)
rescue KeyNotRegisteredError => err
raise KeyNotRegisteredError.new(err.key, :lookup)
end

# @param filekey [String, Symbol] file registry key for file to be used as a source
# @param filekey [String, Symbol] file registry key for file to be used
# as a source
# @return [Kiba::Extend::Registry::RegisteredSource]
def as_source(filekey)
RegisteredSource.new(key: filekey, data: lookup(filekey))
def as_source(filekey, for_job)
RegisteredSource.new(
key: filekey,
data: lookup(filekey),
for_job: for_job
)
rescue KeyNotRegisteredError => err
raise KeyNotRegisteredError.new(err.key, :source)
end
Expand All @@ -68,15 +83,18 @@ def entries
@entries ||= populate_entries
end

# Convenience method combining the steps of transforming initial registry entry hashes
# into FileRegistryEntry objects, and then making the registry immutable for the
# rest of the application's run. `:freeze` is from dry-container.
# Convenience method combining the steps of transforming
# initial registry entry hashes into FileRegistryEntry
# objects, and then making the registry immutable for the
# rest of the application's run. `:freeze` is from
# dry-container.
def finalize
transform
freeze
end

# Transforms registered file hashes into Kiba::Extend::Registry::FileRegistryEntry objects
# Transforms registered file hashes into
# {Kiba::Extend::Registry::FileRegistryEntry} objects
def transform
each { |key, val| decorate(key) { FileRegistryEntry.new(val) } }
@entries = populate_entries
Expand Down Expand Up @@ -123,7 +141,8 @@ def verify_supplied_files_exist
end.map(&:path).uniq.each do |file|
next if file.exist?

puts %(#{Kiba::Extend.warning_label}: Missing supplied file: #{file})
puts "#{Kiba::Extend.warning_label}: Missing supplied "\
"file: #{file}"
end
end

Expand All @@ -134,4 +153,3 @@ def validator
end
end
end
# rubocop:enable Layout/LineLength
2 changes: 1 addition & 1 deletion lib/kiba/extend/registry/registered_destination.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def initialize(entry_key)
end
end

def initialize(key:, data:)
def initialize(key:, data:, for_job:)
super
fail SuppliedEntryError.new(key) if supplied
end
Expand Down
24 changes: 15 additions & 9 deletions lib/kiba/extend/registry/registered_file.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
# frozen_string_literal: true

# rubocop:todo Layout/LineLength

module Kiba
module Extend
module Registry
# Abstract base class defining interface for destination files, lookup files, and source files
# returned by {Kiba::Extend::FileRegistry}
# Abstract base class defining interface for destination files,
# lookup files, and source files returned by
# {Kiba::Extend::FileRegistry}
class RegisteredFile
# Exception raised if no path is given in {FileRegistry} hash
class NoFilePathError < StandardError
# @param filekey [Symbol] key for which a file path was not found in {Kiba::Extend::FileRegistry}
# @param filekey [Symbol] key for which a file path was not found in
# {Kiba::Extend::FileRegistry}
def initialize(filekey)
msg = "No file path for :#{filekey} is recorded in file registry hash"
msg = "No file path for :#{filekey} is recorded in file registry "\
"hash"
super(msg)
end
end
Expand All @@ -24,13 +25,17 @@ def initialize(filekey)
:desc

# @param key [Symbol] the {Kiba::Extend::FileRegistry} lookup key
# @param data [Hash] the hash of data for the file from {Kiba::Extend::FileRegistry}
def initialize(key:, data:)
# @param data [Hash] the hash of data for the file from
# {Kiba::Extend::FileRegistry}
# @param for_job [Symbol] registry entry job key of the job for which
# this registered file is being prepared
def initialize(key:, data:, for_job:)
raise FileNotRegisteredError, key unless data
raise NoFilePathError, key if data.errors.keys.any?(:missing_path)

@key = key
@data = data
@for_job = for_job
@path = data.path.to_s
@dest_class = data.dest_class
@dest_opt = data.dest_opt
Expand All @@ -47,6 +52,8 @@ def src_class

private

attr_reader :for_job

# returns equivalent source class for given destination class
def dest_src
src = dest_class.as_source_class
Expand All @@ -58,4 +65,3 @@ def dest_src
end
end
end
# rubocop:enable Layout/LineLength
47 changes: 13 additions & 34 deletions lib/kiba/extend/registry/registered_lookup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,30 @@
module Kiba
module Extend
module Registry
# Value object representing a file registered in a {Kiba::Extend::FileRegistry} that is being
# called into another job as a lookup table
# Value object representing a file registered in a
# {Kiba::Extend::FileRegistry} that is being called into
# another job as a lookup table
#
# Assumes this file will be used to build a {Kiba::Extend::Lookup}
class RegisteredLookup < RegisteredFile
include RequirableFile

class CannotBeUsedAsLookupError < TypeError
include Kiba::Extend::ErrMod
def initialize(klass)
super("The result of a registry entry with a #{klass} "\
"dest_class cannot be used as source file in a job")
end
end

# Exception raised if {Kiba::Extend::FileRegistry} contains no lookup key for file
class NoLookupKeyError < NameError
include Kiba::Extend::ErrMod
# @param filekey [Symbol] key not found in {Kiba::Extend::FileRegistry}
def initialize(filekey)
msg = "No lookup key column found for :#{filekey} in file registry hash"
super(msg)
end
end

# Exception raised if the lookup key value for the file is not a Symbol
class NonSymbolLookupKeyError < TypeError
include Kiba::Extend::ErrMod
# @param filekey [Symbol] key not found in {Kiba::Extend::FileRegistry}
def initialize(filekey)
msg = "Lookup key found for :#{filekey} is not a Ruby Symbol. Prepend a : to the field name to fix."
super(msg)
end
end

# @param key [Symbol] file key from {FileRegistry} data hash
# @param data [Hash] file data from {FileRegistry}
def initialize(key:, data:)
# @param for_job [Symbol] registry entry job key of the job for which
# this registered file is being prepared
def initialize(key:, data:, for_job:)
super
unless src_class.respond_to?(:is_lookupable?)
fail CannotBeUsedAsLookupError.new(src_class)
fail Kiba::Extend::JobCannotBeUsedAsLookupError.new(
key, src_class, for_job
)
end
unless lookup_on
fail Kiba::Extend::NoLookupOnError.new(key, for_job)
end
fail NoLookupKeyError, @key unless lookup_on
unless lookup_on.is_a?(Symbol)
fail NonSymbolLookupKeyError, @key
fail Kiba::Extend::NonSymbolLookupOnError.new(key, for_job)
end
end

Expand Down
Loading

0 comments on commit 46c147a

Please sign in to comment.