Bug Description
In src/github/folderRepositoryManager.ts, both getAssignableUsers() and getMentionableUsers() have an identical cache-bypass bug. On the first call, they correctly return globalStateCache ?? fetchPromise, allowing the UI to display cached data immediately while a background fetch updates the data. However, on subsequent calls (when the fetch promise already exists from a prior invocation), they skip the globalState cache entirely and return only the fetch promise, blocking the UI on the network request.
Affected Methods
getAssignableUsers()
async getAssignableUsers(clearCache?: boolean): Promise<{ [key: string]: IAccount[] }> {
if (clearCache) {
delete this._assignableUsers;
}
if (this._assignableUsers) {
return this._assignableUsers;
}
const globalStateAssignableUsers = await this.getCachedFromGlobalState('assignableUsers');
if (!this._fetchAssignableUsersPromise) {
// First call: creates fetch promise
this._fetchAssignableUsersPromise = new Promise(resolve => { /* ... */ });
return globalStateAssignableUsers ?? this._fetchAssignableUsersPromise; // ✅ Uses cache
}
return this._fetchAssignableUsersPromise; // ❌ Ignores globalStateAssignableUsers
}
getMentionableUsers()
async getMentionableUsers(clearCache?: boolean): Promise<{ [key: string]: IAccount[] }> {
if (clearCache) {
delete this._mentionableUsers;
}
if (this._mentionableUsers) {
return this._mentionableUsers;
}
const globalStateMentionableUsers = await this.getCachedFromGlobalState('mentionableUsers');
if (!this._fetchMentionableUsersPromise) {
this._fetchMentionableUsersPromise = this.createFetchMentionableUsersPromise();
return globalStateMentionableUsers ?? this._fetchMentionableUsersPromise; // ✅ Uses cache
}
return this._fetchMentionableUsersPromise; // ❌ Ignores globalStateMentionableUsers
}
The Bug
Logic flow on first call (when _fetchPromise is undefined):
- Check in-memory cache → miss
- Load globalState cache from disk
- Enter
if (!this._fetchPromise) block → create fetch promise
- Return
globalStateCache ?? fetchPromise ✅ (cached data returned immediately)
Logic flow on subsequent calls (when _fetchPromise already exists):
- Check in-memory cache → miss (fetch hasn't completed yet, or in-memory was cleared)
- Load globalState cache from disk ← this succeeds, valid data is available
- Check
if (!this._fetchPromise) → false, skip the block
- Return
this._fetchPromise ❌ (blocks on network, ignores loaded cache)
Impact
On the first call after extension activation, cached user data is returned immediately while a background fetch refreshes it — correct behavior. On any subsequent call where the in-memory cache was cleared but the fetch promise still exists (e.g., after updateRepositories triggers getAssignableUsers(true)), the UI blocks on the network request even though valid cached data is sitting right there in globalStateAssignableUsers / globalStateMentionableUsers.
This causes noticeable delays when:
- Assigning reviewers to a PR
- Using @-mention autocomplete in PR comments/descriptions
- Any UI interaction that triggers these methods after the initial load
This is especially impactful in enterprise environments with large organizations (10K+ members) behind corporate proxies or VPNs, where the assignable/mentionable user fetch can take significantly longer. During that window, every concurrent caller is forced to wait on the network rather than getting the instant disk-cached response.
Suggested Fix
For both methods, the final return should also check the globalState cache:
getAssignableUsers():
- return this._fetchAssignableUsersPromise;
+ return globalStateAssignableUsers ?? this._fetchAssignableUsersPromise;
getMentionableUsers():
- return this._fetchMentionableUsersPromise;
+ return globalStateMentionableUsers ?? this._fetchMentionableUsersPromise;
Version
Observed in v0.132.2.
Bug Description
In
src/github/folderRepositoryManager.ts, bothgetAssignableUsers()andgetMentionableUsers()have an identical cache-bypass bug. On the first call, they correctly returnglobalStateCache ?? fetchPromise, allowing the UI to display cached data immediately while a background fetch updates the data. However, on subsequent calls (when the fetch promise already exists from a prior invocation), they skip the globalState cache entirely and return only the fetch promise, blocking the UI on the network request.Affected Methods
getAssignableUsers()getMentionableUsers()The Bug
Logic flow on first call (when
_fetchPromiseis undefined):if (!this._fetchPromise)block → create fetch promiseglobalStateCache ?? fetchPromise✅ (cached data returned immediately)Logic flow on subsequent calls (when
_fetchPromisealready exists):if (!this._fetchPromise)→ false, skip the blockthis._fetchPromise❌ (blocks on network, ignores loaded cache)Impact
On the first call after extension activation, cached user data is returned immediately while a background fetch refreshes it — correct behavior. On any subsequent call where the in-memory cache was cleared but the fetch promise still exists (e.g., after
updateRepositoriestriggersgetAssignableUsers(true)), the UI blocks on the network request even though valid cached data is sitting right there inglobalStateAssignableUsers/globalStateMentionableUsers.This causes noticeable delays when:
This is especially impactful in enterprise environments with large organizations (10K+ members) behind corporate proxies or VPNs, where the assignable/mentionable user fetch can take significantly longer. During that window, every concurrent caller is forced to wait on the network rather than getting the instant disk-cached response.
Suggested Fix
For both methods, the final return should also check the globalState cache:
getAssignableUsers():getMentionableUsers():Version
Observed in v0.132.2.