Skip to content
On this page

Barrier Circuit Breaker

Recipe based on the question from issue #458

Let us assume we have a basic Barrier that is activated on a 401 HTTP error code. The barrier is used to renew the token after failing to access the protected resource.

ts
import { createBarrier, isHttpErrorCode } from '@farfetched/core';

const authBarrier = createBarrier({
  activateOn: {
    failure: isHttpErrorCode(401),
  },
  perform: [renewTokenMutation],
});

TIP

It is a basic example based on the case-study Auth token.

In this setup, it is possible to get infinite loops if the token renewal in case of some mistake in Query declaration. For example, if we made a typo in the header name, the Barrier will be activated on every request, and the token will be renewed every time, which will not lead to successful Query execution.

ts
import { createJsonQuery, applyBarrier } from '@farfetched/core';

const buggyQuery = createJsonQuery({
  request: {
    method: 'GET',
    url: 'https://api.salo.com/protected',
    headers: combine($authToken, (token) => ({
      // 👇 typo in header name
      Authorisation: `Bearer ${token}`,
    })),
  },
  // ...
});

applyBarrier(buggyQuery, { barrier: authBarrier });

Solution

In this case, we can write some kind of circuit breaker that will stop the token renewal after a certain number of attempts.

ts
function barrierCircuitBreaker(barrier, { maxAttempts }) {
  const $currentAttempt = createStore(0).on(
    // every time after the Barrier is performed
    barrier.performed,
    // increment the current attempt
    (attempt) => attempt + 1
  );

  sample({
    // If the number of attempts exceeds the limit,
    clock: $currentAttempt,
    filter: (currentAttempt) => currentAttempt >= maxAttempts,
    target: [
      // force the Barrier to deactivate
      barrier.forceDeactivate,
      // and reset the current attempt counter
      $currentAttempt.reinit,
    ],
  });
}

This function can be applied to the existing Barrier to limit the number of attempts to renew the token 👇

ts
barrierCircuitBreaker(authBarrier, { maxAttempts: 3 });

That is it, authBarrier will perform the token renewal only three times, and after that, it will be deactivated forcibly, so all Queries will fail with the 401 HTTP error code.

Released under the MIT License.