fix(auth): do not await PowerSync disconnect during session clear - #1313
Merged
rolandgeider merged 1 commit intoAug 13, 2026
Merged
Conversation
A rejected refresh token runs clearSessionOnly inside the single-flight refresh future. PowerSync's disconnect can block on an in-flight sync fetch that is itself awaiting that same refresh future through AuthHttpClient's pre-emptive refresh, closing a three-party cycle (refresh -> disconnect -> sync fetch -> refresh) that permanently wedges every authenticated request behind the never-completing refresh. The session-expired message never appears because it is sequenced after the hanging call, and an app restart re-triggers the same rejected refresh during startup revalidation, so the deadlock re-forms immediately. On the keep-data path the DB is not wiped, so there is no re-attach race to guard against; the disconnect is only a courtesy stop of the sync loop and is now fire-and-forget. The wipe path (explicit logout) keeps its ordering. The disconnect hook is injectable for tests because PowerSyncDatabase is a base class that cannot be faked.
bentucker
force-pushed
the
fix/session-clear-deadlock
branch
from
August 13, 2026 00:08
d3fc354 to
57fe126
Compare
bentucker
pushed a commit
to bentucker/flutter
that referenced
this pull request
Aug 13, 2026
Persists a device-local active-workout pointer (routine, day, iteration, cursor, validity window) so an OS-killed app can resume gym mode where it left off, surfaced through a dashboard resume card that deep links back into gym mode. The pointer is cleared on explicit session save and on any local-data wipe (logout, user switch) so another user never inherits a stale in-progress workout. Also stamps a reused day-less workout session with the routine day at log time; upstream sets the day on newly created sessions (6eb6197) but the reuse branch left existing sessions day-less, which stalls log-driven scheduling (Day.need_logs_to_advance) on the backend. Rebased onto the lib/core + lib/features layout; the session-clear deadlock fix formerly on this branch was merged upstream (wger-project#1313) and the gym-mode day stamping half became redundant with upstream's dayId work.
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.
Proposed Changes
(clearSessionOnly). The await closes a three-party circular wait when a
refresh token is rejected: the refresh future runs the session teardown,
the teardown awaits PowerSync's disconnect, the disconnect waits for the
in-flight sync fetch to abort, and that fetch is awaiting the same
single-flight refresh future through AuthHttpClient's pre-emptive refresh.
The refresh future then never completes and every later authenticated
request queues behind it forever (15 second timeouts on every endpoint,
surviving app restarts). See the issue for the full production diagnosis.
kept, so there is no wipe to race with: once the cleared state is
published, the wedged sync fetch resumes without a credential, gets a 401
and PowerSync backs off, letting the deferred disconnect finish. The wipe
path (explicit logout) keeps its wipe-before-publish ordering.
regression test can install a never-completing disconnect;
PowerSyncDatabase is a base class and cannot be faked directly.
logged-out state even when the PowerSync disconnect hangs forever.
Related Issue(s)
Closes #1312
Checklist