# frozen_string_literal: true module Dor module Workflow class Client # Builds Faraday connections that follow redirects class ConnectionFactory def self.build_connection(url, timeout:, logger:) new(url, timeout: timeout, logger: logger).build_connection end def initialize(url, timeout:, logger:) @url = url @timeout = timeout @logger = logger end def build_connection Faraday.new(url: url) do |faraday| faraday.use Faraday::Response::RaiseError # raise exceptions on 40x, 50x responses faraday.options.params_encoder = Faraday::FlatParamsEncoder if timeout faraday.options.timeout = timeout faraday.options.open_timeout = timeout end faraday.headers[:user_agent] = user_agent faraday.request :retry, max: 2, interval: 5.0, interval_randomness: 0.01, backoff_factor: 2.0, methods: retriable_methods, exceptions: retriable_exceptions, retry_block: retry_block, retry_statuses: retry_statuses faraday.adapter Faraday.default_adapter # Last middleware must be the adapter end end def user_agent "dor-workflow-client #{VERSION}" end private attr_reader :logger, :timeout, :url def retriable_methods Faraday::Retry::Middleware::IDEMPOTENT_METHODS + [:post] end def retriable_exceptions Faraday::Retry::Middleware::DEFAULT_EXCEPTIONS + [Faraday::ConnectionFailed] end def retry_block lambda do |env:, options:, retry_count:, exception:, will_retry_in:| logger.warn "retrying connection (#{retry_count + 1}) to #{env.url}: (#{exception.class}) " \ "#{exception.message} #{env.status}" end end def retry_statuses [429, 500, 502, 503, 504, 599] end end end end end