Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failover logic may have the opposite effect to the intended #15

Closed
alexey-milovidov opened this issue Apr 21, 2024 · 2 comments
Closed
Assignees
Labels

Comments

@alexey-milovidov
Copy link
Member

I use Promise.race to use the first reply among the self-managed and Cloud service - so we can break and experiment with the Cloud service fearlessly, but it still provides scalability benefits.

But my implementation has the following flaws:

  • When a database quickly answers with an error, the promise is fulfilled, and that's how a totally broken database breaks the whole UI. In fact, there are two asynchronous operations - one is to receive the HTTP response headers, and another for receiving the body.
  • A browser like Chrome has a limit on the number of requests in flight. It means that if one of the databases is slow, after a while we will have a lot of pending, unneeded requests. If we don't cancel them, the service hangs after a while.
@alexey-milovidov
Copy link
Member Author

Zach (3 days ago)

you should use Promise.any() instead of Promise.race() I think - this should achieve the behavior you're looking for
Since you're already using fetch API, you can create some abortController s to cancel any remaining requests once the Promise.any() is fulfilled (I think it may work)

Fabio Neves (3 days ago)

Promise.any gives the desired semantics. With the AbortController we can prevent running out of max requests

const fetchRequests = [];
const abortController = new AbortController();

for (let i = 0; i < N; i++) {
  const fetchRequest = fetch(url, { signal: abortController.signal })
    .then(response => {
      if (response.ok) {
        abortController.abort();
        return response.json();
      }
      throw new Error('Request failed');
    })
    .catch(error => {
      console.error(error);
    });

  fetchRequests.push(fetchRequest);
}
Promise.any(fetchRequests)
    .then(data => {
      console.log('First request succeeded:', data);
      abortController.abort();
    })
    .catch(error => {
      console.error('All requests failed:', error);
    });

I think this is a sample that mimics what we want

alexey-milovidov added a commit that referenced this issue Apr 21, 2024
alexey-milovidov added a commit that referenced this issue Apr 21, 2024
@alexey-milovidov
Copy link
Member Author

Done.

Ideally, we can also cancel all pending requests on query change or on Zoom.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant