fastify / fastify-reply-from

fastify plugin to forward the current http request to another server
MIT License
148 stars 76 forks source link

[feature] custom retry callback #332

Closed MikePresman closed 9 months ago

MikePresman commented 10 months ago

This PR implements two fundamental changes.

Edit: 1. I have added PATCH and POST as given default retryMethods see review by airhorns

  1. I have added the option to pass a callback to handle retries in a custom fashion as defined by the client.

Point 2. Described

The motivation for this change is that out of the box reply-from does not retry 500's so gracefully handling such cases is not possible. As a result with this change you are able to write your own callback to retry 500's as you wish (or any other kind of error - using 500's here as an exemplar).

This can be done quite simply.

 const customRetryLogic = (req, res, registerDefaultRetry, defaultRetryAfter) => {
    if (res && res.statusCode === 500 && req.method === 'GET') {
      return 300
    }
    return null
  }

...
Fastify.reply(From, customRetry: { handler: customRetryLogic, retries: 10 }}

Note this new API is an object which has two keys. handler and retries where handler is a required key and retries is optional but strongly encouraged.


There is an important intricacy to this API.

If no customRetry object is passed then business as usual in the library. Retries work as they are expected for default cases.

But if a customRetry is passed then it is up to responsibility of the callback to be aware that if they expect default behaviour to co-exist they must register it. If they don't (the above example DID NOT) all default cases of errors (such as 503s) won't be retried.

Example to get default behaviour in a customRetry

 const customRetryLogic = (req, res, registerDefaultRetry, defaultRetryAfter) => {
    // Registering the default retry logic so if a default case occurs we handle it.
    if (registerDefaultRetry()){
      return defaultRetryAfter; // Some new magic is that we can override our headers and pass a new retry-after value.
    }

    if (res && res.statusCode === 500 && req.method === 'GET') {
      return 300
    }
    return null
  }

CC: @airhorns

Checklist