Semaphore-Based Request Handling with Session Refresh

Hey! I'd like to know if the following is possible, or if it's just a fundamental misunderstanding on my end on semaphores:

Let's say I'm making a request and I get a 401 error. In that case, I need to try and refresh the session. The problem is, if there are concurrent requests, all of them would try to refresh the token. A simple solution would be to wrap the refresh operation in withPermits(1), which works fine. However, I'd also like to block subsequent requests while refreshing the session. So, not only would I prevent others from trying to refresh the session, but I'd also queue up any subsequent requests made after we've started refreshing the session (blocking them with another semaphore) until the session is refreshed successfully.

Here's the basic flow I'm envisioning:
1. The request starts without acquiring any semaphores.
1. If the request is successful, it ends normally.
3. If a 401 is received, we attempt to acquire both semaphores in sequence.
3.1. If we make a new request after both semaphores have been acquired by another request (meaning we're already refreshing the session), wait until they are freed and then make the request.
3.2. If we made a concurrent request and got a 401, but we're already refreshing the session, wait until it is refreshed, and then retry the operation.

Is this possible or not worth the hassle? https://effect.website/play#e704da2ec1be
withPermitsIfAvailable(permits: number) is close to what I want but it doesn't block - it just returns none if permits aren't available (but I also don't want to optimistically take it, otherwise all requests would be sequential).
Was this page helpful?