fix: prevent config watcher feedback loop during OAuth token refresh#1059
Open
QiuYi111 wants to merge 1 commit into
Open
fix: prevent config watcher feedback loop during OAuth token refresh#1059QiuYi111 wants to merge 1 commit into
QiuYi111 wants to merge 1 commit into
Conversation
Contributor
|
instead of that, we propose to first change the in memory, then to update the file. the lack of differences between the in memory and the file will mean no further restarts or cyclical change loop |
Contributor
|
can you give this a try and let us know if that holds up for you? |
c743454 to
4013cf0
Compare
Author
|
Great suggestion! Updated the approach: we now update in-memory config first via This is cleaner and simpler. All 642 tests pass. |
…xhaustion Three changes to prevent the OAuth token refresh cycle that forces users to repeatedly re-authenticate: 1. EdgeWorker.saveOAuthTokens: update in-memory config BEFORE writing to disk. When the config watcher fires, it sees no diff between in-memory and on-disk state, so no feedback loop is triggered. 2. LinearIssueTrackerService.doTokenRefresh: keep the resolved pendingRefreshes promise for 5 seconds (cooldown) instead of clearing immediately in finally. Late-arriving 401s coalesce onto the resolved promise instead of triggering redundant HTTP refresh calls that would fail because the refresh token is single-use. 3. LinearIssueTrackerService retry catch: if the retry with a refreshed token also returns 401, clear the stale refreshPromise so the next request can trigger a fresh refresh. Without this, the instance-level coalesce holds a stale promise forever and the token can never be refreshed again after natural expiration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9ee340d to
eb681d8
Compare
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.
Summary
Fixes the OAuth token refresh feedback loop and concurrent token exhaustion that forces users to repeatedly re-authenticate.
Three changes across two files:
1. Update in-memory config before writing to disk (
EdgeWorker.saveOAuthTokens)When the file watcher fires after
config.jsonis updated, it compares in-memory vs on-disk state. By updating in-memory first, no diff is detected, preventing the feedback loop.2. Cooldown on static refresh coalescing (
LinearIssueTrackerService.doTokenRefresh)Keep the resolved
pendingRefreshespromise for 5 seconds instead of clearing immediately infinally. Late-arriving 401s coalesce onto the resolved promise instead of triggering redundant HTTP refresh calls that fail because the OAuth refresh token is single-use.3. Clear stale instance promise on retry failure (
LinearIssueTrackerService)If the retry with a refreshed token also returns 401, clear the stale
refreshPromiseso the next request can trigger a fresh refresh. Without this, the instance-level coalesce holds a stale promise forever and the token can never be refreshed again after natural expiration (~1 hour).Problem
When OAuth tokens are refreshed,
saveOAuthTokenswrites toconfig.json→ chokidar detects the change →handleConfigChangefires →detectGlobalConfigChangesseeslinearWorkspaceschanged →updateLinearWorkspaceTokenscallssetAccessToken()which clears instance-level coalescing → concurrent 401s trigger new refreshes → refresh token already consumed → 400 → token exhaustion → user must re-auth.Test Plan
pnpm biome checkpassestypecheckpasses🤖 Generated with Claude Code