Skip to content

Commit 2b181f1

Browse files
authored
Can't enable settings sync UI State option - "too large payload" (microsoft#203544)
Fixes microsoft#202359
1 parent d9bc6b0 commit 2b181f1

File tree

1 file changed

+72
-15
lines changed

1 file changed

+72
-15
lines changed

src/vs/workbench/services/remote/common/tunnelModel.ts

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,25 @@ import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common
2727

2828
const MISMATCH_LOCAL_PORT_COOLDOWN = 10 * 1000; // 10 seconds
2929
const TUNNELS_TO_RESTORE = 'remote.tunnels.toRestore';
30+
const TUNNELS_TO_RESTORE_EXPIRATION = 'remote.tunnels.toRestoreExpiration';
31+
const RESTORE_EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 14; // 2 weeks
3032
export const ACTIVATION_EVENT = 'onTunnel';
3133
export const forwardedPortsViewEnabled = new RawContextKey<boolean>('forwardedPortsViewEnabled', false, nls.localize('tunnel.forwardedPortsViewEnabled', "Whether the Ports view is enabled."));
3234

35+
export interface RestorableTunnel {
36+
remoteHost: string;
37+
remotePort: number;
38+
localAddress: string;
39+
localUri: URI;
40+
protocol: TunnelProtocol;
41+
localPort?: number;
42+
name?: string;
43+
source: {
44+
source: TunnelSource;
45+
description: string;
46+
};
47+
}
48+
3349
export interface Tunnel {
3450
remoteHost: string;
3551
remotePort: number;
@@ -406,7 +422,7 @@ export class TunnelModel extends Disposable {
406422
private knownPortsRestoreValue: string | undefined;
407423
private restoreComplete = false;
408424
private onRestoreComplete: Emitter<void> = new Emitter();
409-
private unrestoredExtensionTunnels: Map<string, Tunnel> = new Map();
425+
private unrestoredExtensionTunnels: Map<string, RestorableTunnel> = new Map();
410426
private sessionCachedProperties: Map<string, Partial<TunnelProperties>> = new Map();
411427

412428
private portAttributesProviders: PortAttributesProvider[] = [];
@@ -526,14 +542,22 @@ export class TunnelModel extends Disposable {
526542
return URI.parse(`${protocol}://${localAddress}`);
527543
}
528544

529-
private async getStorageKey(): Promise<string | undefined> {
545+
private async addStorageKeyPostfix(prefix: string): Promise<string | undefined> {
530546
const workspace = this.workspaceContextService.getWorkspace();
531547
const workspaceHash = workspace.configuration ? hash(workspace.configuration.path) : (workspace.folders.length > 0 ? hash(workspace.folders[0].uri.path) : undefined);
532548
if (workspaceHash === undefined) {
533549
this.logService.debug('Could not get workspace hash for forwarded ports storage key.');
534550
return undefined;
535551
}
536-
return `${TUNNELS_TO_RESTORE}.${this.environmentService.remoteAuthority}.${workspaceHash}`;
552+
return `${prefix}.${this.environmentService.remoteAuthority}.${workspaceHash}`;
553+
}
554+
555+
private async getTunnelRestoreStorageKey(): Promise<string | undefined> {
556+
return this.addStorageKeyPostfix(TUNNELS_TO_RESTORE);
557+
}
558+
559+
private async getRestoreExpirationStorageKey(): Promise<string | undefined> {
560+
return this.addStorageKeyPostfix(TUNNELS_TO_RESTORE_EXPIRATION);
537561
}
538562

539563
private async getTunnelRestoreValue(): Promise<string | undefined> {
@@ -543,18 +567,19 @@ export class TunnelModel extends Disposable {
543567
await this.storeForwarded();
544568
return deprecatedValue;
545569
}
546-
const storageKey = await this.getStorageKey();
570+
const storageKey = await this.getTunnelRestoreStorageKey();
547571
if (!storageKey) {
548572
return undefined;
549573
}
550574
return this.storageService.get(storageKey, StorageScope.PROFILE);
551575
}
552576

553577
async restoreForwarded() {
578+
this.cleanupExpiredTunnelsForRestore();
554579
if (this.configurationService.getValue('remote.restoreForwardedPorts')) {
555580
const tunnelRestoreValue = await this.tunnelRestoreValue;
556581
if (tunnelRestoreValue && (tunnelRestoreValue !== this.knownPortsRestoreValue)) {
557-
const tunnels = <Tunnel[] | undefined>JSON.parse(tunnelRestoreValue) ?? [];
582+
const tunnels = <RestorableTunnel[] | undefined>JSON.parse(tunnelRestoreValue) ?? [];
558583
this.logService.trace(`ForwardedPorts: (TunnelModel) restoring ports ${tunnels.map(tunnel => tunnel.remotePort).join(', ')}`);
559584
for (const tunnel of tunnels) {
560585
const alreadyForwarded = mapHasAddressLocalhostOrAllInterfaces(this.detected, tunnel.remoteHost, tunnel.remotePort);
@@ -564,7 +589,6 @@ export class TunnelModel extends Disposable {
564589
remote: { host: tunnel.remoteHost, port: tunnel.remotePort },
565590
local: tunnel.localPort,
566591
name: tunnel.name,
567-
privacy: tunnel.privacy,
568592
elevateIfNeeded: true,
569593
source: tunnel.source
570594
});
@@ -580,7 +604,7 @@ export class TunnelModel extends Disposable {
580604

581605
if (!this.restoreListener) {
582606
// It's possible that at restore time the value hasn't synced.
583-
const key = await this.getStorageKey();
607+
const key = await this.getTunnelRestoreStorageKey();
584608
this.restoreListener = this._register(new DisposableStore());
585609
this.restoreListener.add(this.storageService.onDidChangeValue(StorageScope.PROFILE, undefined, this.restoreListener)(async (e) => {
586610
if (e.key === key) {
@@ -591,17 +615,50 @@ export class TunnelModel extends Disposable {
591615
}
592616
}
593617

618+
private cleanupExpiredTunnelsForRestore() {
619+
const keys = this.storageService.keys(StorageScope.PROFILE, StorageTarget.USER).filter(key => key.startsWith(TUNNELS_TO_RESTORE_EXPIRATION));
620+
for (const key of keys) {
621+
const expiration = this.storageService.getNumber(key, StorageScope.PROFILE);
622+
if (expiration && expiration < Date.now()) {
623+
this.tunnelRestoreValue = Promise.resolve(undefined);
624+
const storageKey = key.replace(TUNNELS_TO_RESTORE_EXPIRATION, TUNNELS_TO_RESTORE);
625+
this.storageService.remove(key, StorageScope.PROFILE);
626+
this.storageService.remove(storageKey, StorageScope.PROFILE);
627+
}
628+
}
629+
}
630+
594631
@debounce(1000)
595632
private async storeForwarded() {
596633
if (this.configurationService.getValue('remote.restoreForwardedPorts')) {
597-
const valueToStore = JSON.stringify(Array.from(this.forwarded.values()));
598-
if (valueToStore !== this.knownPortsRestoreValue) {
599-
this.knownPortsRestoreValue = valueToStore;
600-
const key = await this.getStorageKey();
601-
if (key) {
602-
this.storageService.store(key, this.knownPortsRestoreValue, StorageScope.PROFILE, StorageTarget.USER);
603-
}
634+
const forwarded = Array.from(this.forwarded.values());
635+
const restorableTunnels: RestorableTunnel[] = forwarded.map(tunnel => {
636+
return {
637+
remoteHost: tunnel.remoteHost,
638+
remotePort: tunnel.remotePort,
639+
localPort: tunnel.localPort,
640+
name: tunnel.name,
641+
localAddress: tunnel.localAddress,
642+
localUri: tunnel.localUri,
643+
protocol: tunnel.protocol,
644+
source: tunnel.source,
645+
};
646+
});
647+
let valueToStore: string | undefined;
648+
if (forwarded.length > 0) {
649+
valueToStore = JSON.stringify(restorableTunnels);
650+
}
651+
652+
const key = await this.getTunnelRestoreStorageKey();
653+
const expirationKey = await this.getRestoreExpirationStorageKey();
654+
if (!valueToStore && key && expirationKey) {
655+
this.storageService.remove(key, StorageScope.PROFILE);
656+
this.storageService.remove(expirationKey, StorageScope.PROFILE);
657+
} else if ((valueToStore !== this.knownPortsRestoreValue) && key && expirationKey) {
658+
this.storageService.store(key, valueToStore, StorageScope.PROFILE, StorageTarget.USER);
659+
this.storageService.store(expirationKey, Date.now() + RESTORE_EXPIRATION_TIME, StorageScope.PROFILE, StorageTarget.USER);
604660
}
661+
this.knownPortsRestoreValue = valueToStore;
605662
}
606663
}
607664

@@ -699,7 +756,7 @@ export class TunnelModel extends Disposable {
699756
if (updateProps) {
700757
tunnelProperties.name = updateProps.name ?? tunnelProperties.name;
701758
tunnelProperties.local = (('local' in updateProps) ? updateProps.local : (('localPort' in updateProps) ? updateProps.localPort : undefined)) ?? tunnelProperties.local;
702-
tunnelProperties.privacy = updateProps.privacy ?? tunnelProperties.privacy;
759+
tunnelProperties.privacy = tunnelProperties.privacy;
703760
}
704761
}
705762
return tunnelProperties;

0 commit comments

Comments
 (0)