Implementing Mutex for GraphQL Requests with Effect and Token Refresh

Hey everyone! I'm trying to wrap this up into a mutex (which would be a semaphore with 1 permit), that way, if the request fails due to a 401, I call a refreshSession function to get the new access token, and retry the original mutation while queuing up all mutations (to ensure they are executed with a valid access token). I'm trying to wrap my head around how I can achieve this with Effect to no avail 😅 Can someone guide me through?
import { gql } from "@...";
import type { RequestDocument, Variables } from "graphql-request";
import type { VariablesAndRequestHeadersArgs } from "graphql-request/build/esm/types";
import type { TypedDocumentNode } from "@graphql-typed-document-node/core";
import { Effect } from "effect";
import { GqlRequestError } from "@exceptions";

export function makeGqlRequest<T, V extends Variables = Variables>(
  document: RequestDocument | TypedDocumentNode<T, V>,
  ...variablesAndRequestHeaders: VariablesAndRequestHeadersArgs<V>
): Effect.Effect<T, GqlRequestError, never> {
  return Effect.tryPromise({
    try: () => gql.request(document, ...variablesAndRequestHeaders),
    catch: () => new GqlRequestError(),
  });
}

I can achieve this without Effect with async-mutex with (pseudo-code) something like:
if (result.error.status !== 401) return;

if (!mutex.isLocked()) {
  const release = await mutex.acquire();

  const refreshResult = await fetch(...);

  if (refreshResult.ok) {
    // ... update token

    result = await // make original request again
  };

  // ...

// finally block, log out
Was this page helpful?