Skip to content

Retries

Matt Muller edited this page Apr 11, 2024 · 6 revisions

Retries are performed when the encountered error is a throttling error, transient error, server error, or a modeled error marked with the retryable trait. Retry Strategies can customize when and how to perform a retry.

@error("client")
@retryable
@httpError(422)
structure UnprocessableEntityError {
    @httpPayload
    errors: AttributeErrors
}

Usage

When an error is modeled as retryable, the request is retried up to the amount determined in the retry strategy. Assuming that UnprocessableEntityError is modeled as retryable, the following would occur:

client = HighScoreService::Client.new(endpoint: 'http://127.0.0.1:3000')
# => #<HighScoreService::Client ... >

# Assumes service has a validation of "game" having a length of at least 2
# If validation fails, service is expected to return a status code of 422
client.create_high_score(high_score: { game: 'X', score: 123 })
# <Makes 3 total requests with 2 retries>
# raises UnprocessableEntityError (HighScoreService::Errors::UnprocessableEntityError)

Retry Strategy

A Retry Strategy can be any class that responds to the following methods:

  • acquire_initial_retry_token(token_scope)
  • refresh_retry_token(retry_token, error_info)
  • record_success(retry_token)

A Retry Strategy is used as follows:

  1. Retry Middleware will first call acquire_initial_retry_token before attempting the request. This method should initialize a new Hearth::Retry::Token. token_scope is currently not supported and can be ignored.
  2. If the service encounters an error, a Hearth::HTTP::ErrorInspector is created that wraps the error and Response objects.
  3. The retry token and error inspector are passed to the refresh_retry_token method. Using the error info, the strategy determines if the error is retryable, and if so, updates the retry token with the retry count and delay.
  4. If the error is not retryable, the token is not returned by the strategy, and the error is returned by the operation. If the error is retryable, the token is updated and returned. The middleware will sleep for the token's delay and then retry.
  5. If the request is successful, the record_success method should release any throttling capacity and return the retry token.

Hearth provides two canned retry strategy implementations that can be used: Hearth::Retry::Standard and Hearth::Retry::Adaptive. Both strategies take options such as :max_attempts and :backoff.

client = HighScoreService::Client.new(
  endpoint: 'http://127.0.0.1:3000',
  retry_strategy: Hearth::Retry::Adaptive.new(max_attempts: 2)
)
# => #<HighScoreService::Client ... >

client.list_high_scores
# <Retries up to 1 time>
# => #<Hearth::Output @data=... >