Skip to content

Commit

Permalink
Introduce error handling policy
Browse files Browse the repository at this point in the history
  • Loading branch information
krzyzak committed Mar 16, 2017
1 parent 76771c2 commit a2ec5ee
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 11 deletions.
12 changes: 1 addition & 11 deletions lib/postmen.rb
Expand Up @@ -6,6 +6,7 @@
require 'forwardable'

require 'postmen/version'
require 'postmen/errors'
require 'postmen/types'
require 'postmen/connection'
require 'postmen/collection_proxy'
Expand Down Expand Up @@ -37,17 +38,6 @@
class Postmen
extend Dry::Configurable

# Generic Exception class, all other exceptions should inherit from this class
Error = Class.new(StandardError)
# Exception raised if rate limit was exceeded
RateLimitExceeded = Class.new(Error)
# Exception raised in case of any connection error
ConnectionError = Class.new(Error)
# Generic exception raised if the API returns an error
RequestError = Class.new(Error)
# Expcetion raised if resource was not found.
ResourceNotFound = Class.new(RequestError)

# @#!attribute [rw] api_key [String] API key taken from the application.
setting :api_key

Expand Down
23 changes: 23 additions & 0 deletions lib/postmen/connection.rb
Expand Up @@ -33,11 +33,34 @@ def get(path, options = {})
# Switch to failover domain & retry the request
Postmen.failover!
retry
# Handle Rate limits.
# Rate limits are being reset every 60 seconds - we're retrying
# given request after that.
# @see https://docs.postmen.com/ratelimit.html Documentation
rescue RateLimitExceeded
@requests += 1
raise if @requests > MAX_REQUESTS
sleep(60)
retry
# If the resource was not found, simply re-raise the exception
rescue ResourceNotFound
raise
# Handle request errors.
# Our current error handling policy depends on the error type.
# If the API returns information, that the request is retriable,
# We're waiting 5 seconds, and trying again with exact same request.
# To prevent having infinite loops, we're trying maximum 5 times.
# In case that we were unable to make successfull request with that 5 tries,
# MaximumNumberOfRetriesReachedError is being raised.
#
# @raise RequestError if the request is not retriable
# @raise MaximumNumberOfRetriesReachedError if the API returned error after 5 retries
rescue RequestError => error
raise unless error.retriable?
raise MaximumNumberOfRetriesReachedError, self if @requests > MAX_REQUESTS
@requests += 1
sleep(5)
retry
end

# Performs a HTTP POST request.
Expand Down
52 changes: 52 additions & 0 deletions lib/postmen/errors.rb
@@ -0,0 +1,52 @@
class Postmen
# Generic Exception class, all other exceptions should inherit from this class
Error = Class.new(StandardError)

# Generic exception raised if the API returns an error
class RequestError < Error
extend Forwardable

def_delegators :@request, :meta

def initialize(request)
@request = request
end

# Indicates whether request is retryable.
# @see https://docs.postmen.com/errors.html API Documentation
def retryable?
meta.fetch(:retryable, false)
end

# Returns details for the request error
# @see https://docs.postmen.com/#meta API Documentation
def details
meta[:details]
end

# Internal API error code
# @see https://docs.postmen.com/errors.html List of Error codes
def code
meta[:code]
end

# Returns human-readable error message
# @see https://docs.postmen.com/#meta API Documentation
def message
meta[:message]
end

private

attr_reader :request
end

# Exception raised if rate limit was exceeded
RateLimitExceeded = Class.new(Error)
# Exception raised in case of any connection error
ConnectionError = Class.new(Error)
# Exception raised if retriable request reached maximum number of attempts.
MaximumNumberOfRetriesReachedError = Class.new(Error)
# Expcetion raised if resource was not found.
ResourceNotFound = Class.new(RequestError)
end

0 comments on commit a2ec5ee

Please sign in to comment.