Skip to content

Commit 2ebd871

Browse files
committed
Avoids gating/grouping w/ cancellation tokens
1 parent 87449f5 commit 2ebd871

File tree

8 files changed

+39
-23
lines changed

8 files changed

+39
-23
lines changed

src/env/node/git/git.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ import type { GitDir } from '../../../git/gitProvider';
3333
import type { GitDiffFilter } from '../../../git/models/diff';
3434
import { parseGitRemoteUrl } from '../../../git/parsers/remoteParser';
3535
import { isUncommitted, isUncommittedStaged, shortenRevision } from '../../../git/utils/revision.utils';
36+
import { getCancellationTokenId } from '../../../system/-webview/cancellation';
3637
import { configuration } from '../../../system/-webview/configuration';
3738
import { splitPath } from '../../../system/-webview/path';
3839
import { getHostEditorCommand } from '../../../system/-webview/vscode';
40+
import { getScopedCounter } from '../../../system/counter';
3941
import { log } from '../../../system/decorators/log';
4042
import { Logger } from '../../../system/logger';
4143
import { slowCallWarningThreshold } from '../../../system/logger.constants';
@@ -165,13 +167,7 @@ function defaultExceptionHandler(ex: Error, cwd: string | undefined, start?: [nu
165167
throw ex;
166168
}
167169

168-
let _uniqueCounterForStdin = 0;
169-
function getStdinUniqueKey(): number {
170-
if (_uniqueCounterForStdin === Number.MAX_SAFE_INTEGER) {
171-
_uniqueCounterForStdin = 0;
172-
}
173-
return _uniqueCounterForStdin++;
174-
}
170+
const uniqueCounterForStdin = getScopedCounter();
175171

176172
type ExitCodeOnlyGitCommandOptions = GitCommandOptions & { exitCodeOnly: true };
177173
export type PushForceOptions = { withLease: true; ifIncludes?: boolean } | { withLease: false; ifIncludes?: never };
@@ -277,12 +273,12 @@ export class Git {
277273

278274
const gitCommand = `[${runOpts.cwd}] git ${runArgs.join(' ')}`;
279275

280-
const command = `${correlationKey !== undefined ? `${correlationKey}:` : ''}${
281-
options?.stdin != null ? `${getStdinUniqueKey()}:` : ''
282-
}${gitCommand}`;
276+
const cacheKey = `${correlationKey !== undefined ? `${correlationKey}:` : ''}${
277+
options?.stdin != null ? `${uniqueCounterForStdin.next()}:` : ''
278+
}${cancellation != null ? `${getCancellationTokenId(cancellation)}:` : ''}${gitCommand}`;
283279

284280
let waiting;
285-
let promise = this.pendingCommands.get(command);
281+
let promise = this.pendingCommands.get(cacheKey);
286282
if (promise == null) {
287283
waiting = false;
288284

@@ -309,11 +305,11 @@ export class Git {
309305
}
310306

311307
promise = runSpawn<T>(await this.path(), runArgs, encoding ?? 'utf8', runOpts).finally(() => {
312-
this.pendingCommands.delete(command);
308+
this.pendingCommands.delete(cacheKey);
313309
void disposeCancellation?.dispose();
314310
});
315311

316-
this.pendingCommands.set(command, promise);
312+
this.pendingCommands.set(cacheKey, promise);
317313
} else {
318314
waiting = true;
319315
Logger.debug(`${getLoggableScopeBlockOverride('GIT')} ${gitCommand} ${GlyphChars.Dot} waiting...`);

src/env/node/git/sub-providers/status.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import { createReference } from '../../../../git/utils/reference.utils';
2626
import { configuration } from '../../../../system/-webview/configuration';
2727
import { splitPath } from '../../../../system/-webview/path';
2828
import { gate } from '../../../../system/decorators/-webview/gate';
29-
import { defaultResolver } from '../../../../system/decorators/-webview/resolver';
3029
import { log } from '../../../../system/decorators/log';
3130
import { Logger } from '../../../../system/logger';
3231
import { getLogScope, setLogScopeExit } from '../../../../system/logger.scope';
@@ -565,7 +564,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider {
565564
}
566565
}
567566

568-
@gate<StatusGitSubProvider['getStatus']>(rp => rp ?? '')
567+
@gate()
569568
@log()
570569
async getStatus(repoPath: string | undefined, cancellation?: CancellationToken): Promise<GitStatus | undefined> {
571570
if (repoPath == null) return undefined;
@@ -618,7 +617,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider {
618617
return this.getStatusForPathCore(repoPath, pathOrUri, { ...options, exact: false }, cancellation);
619618
}
620619

621-
@gate<StatusGitSubProvider['getStatusForPathCore']>((...args) => defaultResolver(...args.slice(0, 3)))
620+
@gate()
622621
private async getStatusForPathCore(
623622
repoPath: string,
624623
pathOrUri: string | Uri,

src/git/models/commit.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,6 @@ export class GitCommit implements GitRevisionReference {
309309
}
310310

311311
const pathspec = this.fileset?.filtered?.pathspec;
312-
if (pathspec) {
313-
debugger;
314-
}
315312
this.fileset = pathspec
316313
? { files: undefined, filtered: { files: files, pathspec: pathspec } }
317314
: { files: files };

src/plus/gk/subscriptionService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1082,7 +1082,7 @@ export class SubscriptionService implements Disposable {
10821082
return result.value;
10831083
}
10841084

1085-
@gate<SubscriptionService['checkInAndValidateCore']>(s => s.account.id)
1085+
@gate<SubscriptionService['checkInAndValidateCore']>((s, _, orgId) => `${s.account.id}:${orgId}`)
10861086
@debug<SubscriptionService['checkInAndValidateCore']>({ args: { 0: s => s?.account?.label } })
10871087
private async checkInAndValidateCore(
10881088
session: AuthenticationSession,

src/plus/integrations/providers/github/sub-providers/status.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider {
1313
private readonly provider: GitHubGitProviderInternal,
1414
) {}
1515

16-
@gate<StatusGitSubProvider['getStatus']>(rp => rp ?? '')
16+
@gate()
1717
@log()
1818
async getStatus(repoPath: string | undefined, _cancellation?: CancellationToken): Promise<GitStatus | undefined> {
1919
if (repoPath == null) return undefined;

src/plus/launchpad/launchpadProvider.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
getRepositoryIdentityForPullRequest,
2727
isMaybeNonSpecificPullRequestSearchUrl,
2828
} from '../../git/utils/pullRequest.utils';
29+
import { getCancellationTokenId } from '../../system/-webview/cancellation';
2930
import { executeCommand, registerCommand } from '../../system/-webview/command';
3031
import { configuration } from '../../system/-webview/configuration';
3132
import { setContext } from '../../system/-webview/context';
@@ -648,10 +649,10 @@ export class LaunchpadProvider implements Disposable {
648649
}
649650

650651
@gate<LaunchpadProvider['getCategorizedItems']>(
651-
o =>
652+
(o, c) =>
652653
`${o?.force ?? false}|${
653654
o?.search != null && typeof o.search !== 'string' ? o.search.map(pr => pr.url).join(',') : o?.search
654-
}`,
655+
}${getCancellationTokenId(c)}`,
655656
)
656657
@log<LaunchpadProvider['getCategorizedItems']>({ args: { 0: o => `force=${o?.force}`, 1: false } })
657658
async getCategorizedItems(

src/system/-webview/cancellation.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { CancellationToken, Disposable } from 'vscode';
22
import { CancellationTokenSource } from 'vscode';
3+
import { getScopedCounter } from '../counter';
34

45
export class TimedCancellationSource implements CancellationTokenSource, Disposable {
56
private readonly cancellation = new CancellationTokenSource();
@@ -23,3 +24,23 @@ export class TimedCancellationSource implements CancellationTokenSource, Disposa
2324
return this.cancellation.token;
2425
}
2526
}
27+
28+
export function isCancellationToken(arg: unknown): arg is CancellationToken {
29+
return (
30+
typeof arg === 'object' && arg != null && 'isCancellationRequested' in arg && 'onCancellationRequested' in arg
31+
);
32+
}
33+
34+
const cancellationWeakmap = new WeakMap<CancellationToken, number>();
35+
const counter = getScopedCounter();
36+
37+
export function getCancellationTokenId(cancellation: CancellationToken | undefined): string {
38+
if (cancellation == null) return '';
39+
40+
let id = cancellationWeakmap.get(cancellation);
41+
if (id == null) {
42+
id = counter.next();
43+
cancellationWeakmap.set(cancellation, id);
44+
}
45+
return String(id);
46+
}

src/system/decorators/-webview/resolver.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Uri } from 'vscode';
22
import { loggingJsonReplacer } from '@env/json';
3+
import { getCancellationTokenId, isCancellationToken } from '../../-webview/cancellation';
34
import { isContainer } from '../../../container';
45
import { isBranch } from '../../../git/models/branch';
56
import { isCommit } from '../../../git/models/commit';
@@ -47,6 +48,7 @@ export function defaultResolver(...args: unknown[]): string {
4748
return arg.toString();
4849
}
4950
if (isContainer(arg)) return '<container>';
51+
if (isCancellationToken(arg)) return getCancellationTokenId(arg);
5052

5153
return JSON.stringify(arg, loggingJsonReplacer);
5254
}

0 commit comments

Comments
 (0)