sul-dlss/argo

View on GitHub
app/services/virtual_objects_creator.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
# frozen_string_literal: true

# Creates virtual objects using the dor services API
class VirtualObjectsCreator
  SECONDS_BETWEEN_REQUESTS = 10

  # @param [Array] virtual_objects an array of virtual object hashes
  # @return [Array] an array of errors (empty if no errors)
  def self.create(virtual_objects:)
    new(virtual_objects:).create
  end

  attr_reader :virtual_objects

  # @param [Array] virtual_objects an array of virtual object hashes
  def initialize(virtual_objects:)
    if !virtual_objects.is_a?(Array) || virtual_objects.empty?
      raise ArgumentError,
            'virtual_objects must be a non-empty array'
    end

    @virtual_objects = virtual_objects
  end

  # @return [Array] an array of errors (empty if no errors)
  def create
    background_result_url = Dor::Services::Client.virtual_objects.create(virtual_objects:)
    job_output = poll_until_complete(url: background_result_url)
    # If job output hash lacks an `:errors` key, we interpret that as complete success
    return [] if job_output[:errors].nil?

    Honeybadger.notify("WARN: Argo virtual object job errors from #{background_result_url}: #{job_output[:errors].inspect}")

    job_output[:errors].map do |error|
      "Problematic objects for #{error.keys.first}: #{error.values.flatten.to_sentence}"
    end
  end

  private

  # @param [String] url the URL we should poll for updates
  # @return [Hash] a hash of output from the background job
  def poll_until_complete(url:)
    loop do
      results = Dor::Services::Client.background_job_results.show(job_id: job_id_from(url:))

      if results[:status] != 'complete'
        sleep(SECONDS_BETWEEN_REQUESTS)
        redo
      end

      break results[:output]
    end
  end

  def job_id_from(url:)
    url.split('/').last
  end
end