module LocalLinksManager
  module CheckLinks
    class LinkChecker
      TIMEOUT = 5
      REDIRECT_LIMIT = 10

      def check_link(link)
        {
          status: fetch_status(link),
          checked_at: Time.zone.now,
        }
      end

    private

      def fetch_status(link)
        begin
          response = connection.get(URI.parse(link)) do |request|
            request.options[:timeout] = TIMEOUT
            request.options[:open_timeout] = TIMEOUT
          end
          response.status.to_s
        rescue Faraday::ConnectionFailed
          "Connection failed"
        rescue Faraday::TimeoutError
          "Timeout Error"
        rescue Faraday::SSLError
          "SSL Error"
        rescue FaradayMiddleware::RedirectLimitReached
          "Too many redirects"
        rescue URI::InvalidURIError
          "Invalid URI"
        rescue => e
          e.class.to_s
        end
      end

      def connection
        @connection ||= Faraday.new(headers: { accept_encoding: 'none' }) do |faraday|
          faraday.use FaradayMiddleware::FollowRedirects, limit: REDIRECT_LIMIT
          faraday.adapter Faraday.default_adapter
        end
      end
    end
  end
end

module LocalLinksManager
  module CheckLinks
    class LinkChecker
      TIMEOUT = 10
      REDIRECT_LIMIT = 10

      def check_link(link)
        {
          status: fetch_status(link),
          checked_at: Time.zone.now,
        }
      end

    private

      def fetch_status(link)
        begin
          response = connection.get(URI.parse(link)) do |request|
            request.options[:timeout] = TIMEOUT
            request.options[:open_timeout] = TIMEOUT
          end
          response.status.to_s
        rescue Faraday::ConnectionFailed
          "Connection failed"
        rescue Faraday::TimeoutError
          "Timeout Error"
        rescue Faraday::SSLError
          "SSL Error"
        rescue FaradayMiddleware::RedirectLimitReached
          "Too many redirects"
        rescue URI::InvalidURIError
          "Invalid URI"
        rescue => e
          e.class.to_s
        end
      end

      def connection
        @connection ||= Faraday.new(headers: { accept_encoding: 'none' }) do |faraday|
          faraday.use FaradayMiddleware::FollowRedirects, limit: REDIRECT_LIMIT
          faraday.adapter Faraday.default_adapter
        end
      end
    end
  end
end

Increase link check timeout to 10 seconds
Increase link check timeout to 10 seconds

We have a number of sites that persitently fail link checking with a
"Timeout Error" status.  I've visited a few pages and found that although they
are slow initally, they do render eventually.  I suspect that they are low
traffic pages and just need a bit of time to "warm up".  These errors are
frustrating as they list as broken links, but there's not much a link
administrator can do about them.

We had 284 pages that failed like this last night.  If all of those took the
maximum time to open a connection and the maximum response time, then this
would increase the link checker time by about 45 minutes.  Given that the link
checker starts at 2am and usually finishes at approx 8:30am, I don't think
this is too bad.

Tim L-B and I will keep an eye on this to see if it improves matters.  It's
possible that we might get a really long run once in a while, but I think
that's OK.
