fix(firebase-frameworks): don't delete an in-flight app on concurrent - #689
Merged
Merged
Conversation
same-uid requests Concurrent requests for one uid each created their own app, and every set() disposed the previous one while it was still signing in. The losers threw app/app-deleted and the request ended in a 500. Now: - the cache is re-checked after the await so only the first request creates the app - allowStale is gone because a stale get() handed back an already deleted app - an auth failure falls through as an unauthenticated request. Fixes #685
Contributor
There was a problem hiding this comment.
Code Review
This pull request removes the allowStale option from the LRU cache, handles concurrent app initialization in handleAuth by checking the cache again after awaiting session cookie verification, and catches authentication errors in handleFactory to treat them as unauthenticated requests. The review feedback highlights a potential race condition and performance bottleneck with concurrent requests executing signInWithCustomToken simultaneously, suggesting caching the sign-in promise on the app instance to prevent redundant operations.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #685
Problem
firebaseAppsLRUis keyed by uid and disposes withdeleteApp. Two separate paths hand a request an app that is already being deleted.Concurrent requests with the same
__sessioncookie all miss the cache, so each one callsinitializeAppand eachset()deletes the app the previous request is still signing in with. The losers throwapp/app-deleted,handleFactorydoes not catch, and Express answers 500.A single request does it too, once the entry goes stale. A stale
get()deletes the entry, which firesdisposeanddeleteApp, then returns that same app.deleteAppis async and nothing awaits it, and the rest ofhandleAuthis synchronous, so the request never notices. Teardown finishes while the page is awaiting, and the next use ofres.locals.firebaseAppthrows.Fix
allowStale.handleFactory, so an auth failure degrades to an unauthenticated request instead of a 500.Verification
Next.js 14.2 with the Firebase JS SDK, deployed to Hosting preview channels. Statuses come from the SSR function's own request log.
App Router, the reported scenario: eight
<Link>s mount right after sign-in and prefetch at once against a cold entry.app/app-deleted, one 200The 0.11.8 latencies match the table in the issue.
The stale path was checked on its own, with a page that awaits
getIdToken()and then readsapp.options. Once the entry is left idle past its 5 minuteLRU_TTL, 0.11.8 serves the stale entry and the page fails withapp/app-deleted, while this branch re-initializes and succeeds.