Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
uoy-faculty-datasync / lib / datasync / sync_runner.rb
Size: Mime:
# frozen_string_literal: true

require 'delegate'
require 'time'

module Datasync
  # Delegator to provide sequencing and reporting
  class SyncRunner < SimpleDelegator
    attr_reader :terminating_exception

    def ok?
      !aborted? && errors.empty?
    end

    def aborted?
      @terminating_exception || false
    end

    def profile(name)
      @timing ||= {}
      @timing[name] = t = { start: Time.now }
      yield
    ensure
      t[:end] = Time.now
      t[:duration] = t[:end] - t[:start]
    end

    def runtime
      @timing[:total][:duration]
    end

    def run!
      profile(:total) { run_tasks }
    rescue StandardError => e
      @terminating_exception = e
    end

    def run_tasks
      profile(:load_data) { load_data }
      profile(:classify_links) { classify_links }
      profile(:do_match) { do_match }
      check_limits!
      profile(:handle_actions) { handle_actions }
      unload_data
    end

    def report
      @report = []
      append "Sync '#{mapper.title}' started at #{@timing[:total][:start].iso8601}"

      report_totals
      report_errors
      report_exception
      report_timing_information

      append "Sync '#{mapper.title}' ended at #{@timing[:total][:end].iso8601}"
      @report
    end

    private

    def append(*lines)
      @report += lines.flatten
    end

    def report_totals
      append 'Totals:'
      totals.each { |name, value| append "  #{name}: #{value}" if value.positive? }
      append "Dropped updates: #{dropped_updates}"
    end

    def report_errors
      return if ok?

      append 'The following errors occurred during the operation:'
      append(errors.map { |e| error_report_string e })
    end

    def report_exception
      return unless aborted?

      append "The sync terminated prematurely because of a #{@terminating_exception.class}"
      append "  #{@terminating_exception}"
      return if @terminating_exception.is_a? LimitError

      @terminating_exception.backtrace&.each do |line|
        append "    #{line}"
      end
    end

    def report_timing_information
      append 'Timing information:'
      @timing.each do |name, t|
        append format('  %<name>s: %<time>.1f seconds', name:, time: t[:duration])
      end
    end

    def error_report_string(error)
      e = error
      context = "Error processing #{e[:situation]} #{e[:source_id]}:#{e[:target_id]}"
      issue = "#{e[:error]}: #{e[:message]}"
      "#{context}: #{issue}"
    end
  end
end