mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-14 18:46:34 -05:00
Merge from vscode 7eaf220cafb9d9e901370ffce02229171cbf3ea6
This commit is contained in:
committed by
Anthony Dresser
parent
39d9eed585
commit
a63578e6f7
@@ -38,7 +38,7 @@ interface IKeybindingsResourcePreview extends IFileResourcePreview {
|
||||
|
||||
export function getKeybindingsContentFromSyncContent(syncContent: string, platformSpecific: boolean): string | null {
|
||||
const parsed = <ISyncContent>JSON.parse(syncContent);
|
||||
if (platformSpecific) {
|
||||
if (!platformSpecific) {
|
||||
return isUndefined(parsed.all) ? null : parsed.all;
|
||||
}
|
||||
switch (OS) {
|
||||
|
||||
@@ -131,8 +131,8 @@ export class UserDataAutoSyncService extends UserDataAutoSyncEnablementService i
|
||||
|
||||
this._register(userDataSyncAccountService.onDidChangeAccount(() => this.updateAutoSync()));
|
||||
this._register(userDataSyncStoreService.onDidChangeDonotMakeRequestsUntil(() => this.updateAutoSync()));
|
||||
this._register(Event.debounce<string, string[]>(userDataSyncService.onDidChangeLocal, (last, source) => last ? [...last, source] : [source], 1000)(sources => this.triggerSync(sources, false)));
|
||||
this._register(Event.filter(this.userDataSyncResourceEnablementService.onDidChangeResourceEnablement, ([, enabled]) => enabled)(() => this.triggerSync(['resourceEnablement'], false)));
|
||||
this._register(Event.debounce<string, string[]>(userDataSyncService.onDidChangeLocal, (last, source) => last ? [...last, source] : [source], 1000)(sources => this.triggerSync(sources, false, false)));
|
||||
this._register(Event.filter(this.userDataSyncResourceEnablementService.onDidChangeResourceEnablement, ([, enabled]) => enabled)(() => this.triggerSync(['resourceEnablement'], false, false)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ export class UserDataAutoSyncService extends UserDataAutoSyncEnablementService i
|
||||
}
|
||||
|
||||
private sources: string[] = [];
|
||||
async triggerSync(sources: string[], skipIfSyncedRecently: boolean): Promise<void> {
|
||||
async triggerSync(sources: string[], skipIfSyncedRecently: boolean, disableCache: boolean): Promise<void> {
|
||||
if (this.autoSync.value === undefined) {
|
||||
return this.syncTriggerDelayer.cancel();
|
||||
}
|
||||
@@ -337,7 +337,7 @@ export class UserDataAutoSyncService extends UserDataAutoSyncEnablementService i
|
||||
this.telemetryService.publicLog2<{ sources: string[] }, AutoSyncClassification>('sync/triggered', { sources: this.sources });
|
||||
this.sources = [];
|
||||
if (this.autoSync.value) {
|
||||
await this.autoSync.value.sync('Activity');
|
||||
await this.autoSync.value.sync('Activity', disableCache);
|
||||
}
|
||||
}, this.successiveFailures
|
||||
? this.getSyncTriggerDelayTime() * 1 * Math.min(Math.pow(2, this.successiveFailures), 60) /* Delay exponentially until max 1 minute */
|
||||
@@ -393,14 +393,14 @@ class AutoSync extends Disposable {
|
||||
this.logService.info('Auto Sync: Stopped');
|
||||
}));
|
||||
this.logService.info('Auto Sync: Started');
|
||||
this.sync(AutoSync.INTERVAL_SYNCING);
|
||||
this.sync(AutoSync.INTERVAL_SYNCING, false);
|
||||
}
|
||||
|
||||
private waitUntilNextIntervalAndSync(): void {
|
||||
this.intervalHandler.value = disposableTimeout(() => this.sync(AutoSync.INTERVAL_SYNCING), this.interval);
|
||||
this.intervalHandler.value = disposableTimeout(() => this.sync(AutoSync.INTERVAL_SYNCING, false), this.interval);
|
||||
}
|
||||
|
||||
sync(reason: string): Promise<void> {
|
||||
sync(reason: string, disableCache: boolean): Promise<void> {
|
||||
const syncPromise = createCancelablePromise(async token => {
|
||||
if (this.syncPromise) {
|
||||
try {
|
||||
@@ -414,7 +414,7 @@ class AutoSync extends Disposable {
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.doSync(reason, token);
|
||||
return this.doSync(reason, disableCache, token);
|
||||
});
|
||||
this.syncPromise = syncPromise;
|
||||
this.syncPromise.finally(() => this.syncPromise = undefined);
|
||||
@@ -435,12 +435,12 @@ class AutoSync extends Disposable {
|
||||
!isEqual(current.stableUrl, previous.stableUrl));
|
||||
}
|
||||
|
||||
private async doSync(reason: string, token: CancellationToken): Promise<void> {
|
||||
private async doSync(reason: string, disableCache: boolean, token: CancellationToken): Promise<void> {
|
||||
this.logService.info(`Auto Sync: Triggered by ${reason}`);
|
||||
this._onDidStartSync.fire();
|
||||
let error: Error | undefined;
|
||||
try {
|
||||
this.syncTask = await this.userDataSyncService.createSyncTask();
|
||||
this.syncTask = await this.userDataSyncService.createSyncTask(disableCache);
|
||||
if (token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ export function getDefaultIgnoredSettings(): string[] {
|
||||
|
||||
export function registerConfiguration(): IDisposable {
|
||||
const ignoredSettingsSchemaId = 'vscode://schemas/ignoredSettings';
|
||||
const ignoredExtensionsSchemaId = 'vscode://schemas/ignoredExtensions';
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
id: 'settingsSync',
|
||||
@@ -60,7 +59,11 @@ export function registerConfiguration(): IDisposable {
|
||||
'settingsSync.ignoredExtensions': {
|
||||
'type': 'array',
|
||||
markdownDescription: localize('settingsSync.ignoredExtensions', "List of extensions to be ignored while synchronizing. The identifier of an extension is always `${publisher}.${name}`. For example: `vscode.csharp`."),
|
||||
$ref: ignoredExtensionsSchemaId,
|
||||
items: [{
|
||||
type: 'string',
|
||||
pattern: EXTENSION_IDENTIFIER_PATTERN,
|
||||
errorMessage: localize('app.extension.identifier.errorMessage', "Expected format '${publisher}.${name}'. Example: 'vscode.csharp'.")
|
||||
}],
|
||||
'default': [],
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
uniqueItems: true,
|
||||
@@ -102,11 +105,6 @@ export function registerConfiguration(): IDisposable {
|
||||
};
|
||||
jsonRegistry.registerSchema(ignoredSettingsSchemaId, ignoredSettingsSchema);
|
||||
};
|
||||
jsonRegistry.registerSchema(ignoredExtensionsSchemaId, {
|
||||
type: 'string',
|
||||
pattern: EXTENSION_IDENTIFIER_PATTERN,
|
||||
errorMessage: localize('app.extension.identifier.errorMessage', "Expected format '${publisher}.${name}'. Example: 'vscode.csharp'.")
|
||||
});
|
||||
return configurationRegistry.onDidUpdateConfiguration(() => registerIgnoredSettingsSchema());
|
||||
}
|
||||
|
||||
@@ -437,7 +435,7 @@ export interface IUserDataSyncService {
|
||||
readonly onDidResetRemote: Event<void>;
|
||||
readonly onDidResetLocal: Event<void>;
|
||||
|
||||
createSyncTask(): Promise<ISyncTask>;
|
||||
createSyncTask(disableCache?: boolean): Promise<ISyncTask>;
|
||||
createManualSyncTask(): Promise<IManualSyncTask>;
|
||||
|
||||
replace(uri: URI): Promise<void>;
|
||||
@@ -465,7 +463,7 @@ export interface IUserDataAutoSyncService {
|
||||
canToggleEnablement(): boolean;
|
||||
turnOn(): Promise<void>;
|
||||
turnOff(everywhere: boolean): Promise<void>;
|
||||
triggerSync(sources: string[], hasToLimitSync: boolean): Promise<void>;
|
||||
triggerSync(sources: string[], hasToLimitSync: boolean, disableCache: boolean): Promise<void>;
|
||||
}
|
||||
|
||||
export const IUserDataSyncUtilService = createDecorator<IUserDataSyncUtilService>('IUserDataSyncUtilService');
|
||||
|
||||
@@ -128,7 +128,7 @@ export class UserDataAutoSyncChannel implements IServerChannel {
|
||||
|
||||
call(context: any, command: string, args?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'triggerSync': return this.service.triggerSync(args[0], args[1]);
|
||||
case 'triggerSync': return this.service.triggerSync(args[0], args[1], args[2]);
|
||||
case 'turnOn': return this.service.turnOn();
|
||||
case 'turnOff': return this.service.turnOff(args[0]);
|
||||
}
|
||||
|
||||
@@ -106,13 +106,17 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
||||
this.onDidChangeLocal = Event.any(...this.synchronisers.map(s => Event.map(s.onDidChangeLocal, () => s.resource)));
|
||||
}
|
||||
|
||||
async createSyncTask(): Promise<ISyncTask> {
|
||||
async createSyncTask(disableCache?: boolean): Promise<ISyncTask> {
|
||||
await this.checkEnablement();
|
||||
|
||||
const executionId = generateUuid();
|
||||
let manifest: IUserDataManifest | null;
|
||||
try {
|
||||
manifest = await this.userDataSyncStoreService.manifest(createSyncHeaders(executionId));
|
||||
const syncHeaders = createSyncHeaders(executionId);
|
||||
if (disableCache) {
|
||||
syncHeaders['Cache-Control'] = 'no-cache';
|
||||
}
|
||||
manifest = await this.userDataSyncStoreService.manifest(syncHeaders);
|
||||
} catch (error) {
|
||||
error = UserDataSyncError.toUserDataSyncError(error);
|
||||
this.telemetryService.publicLog2<{ code: string, service: string, resource?: string, executionId?: string }, SyncErrorClassification>('sync/error', { code: error.code, resource: error.resource, executionId, service: this.userDataSyncStoreManagementService.userDataSyncStore!.url.toString() });
|
||||
|
||||
@@ -394,7 +394,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync
|
||||
this._onTokenSucceed.fire();
|
||||
|
||||
if (context.res.statusCode === 409) {
|
||||
throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of Conflict (409). There is new data exists for this resource. Make the request again with latest data.`, UserDataSyncErrorCode.Conflict, operationId);
|
||||
throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of Conflict (409). There is new data for this resource. Make the request again with latest data.`, UserDataSyncErrorCode.Conflict, operationId);
|
||||
}
|
||||
|
||||
if (context.res.statusCode === 410) {
|
||||
@@ -402,7 +402,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync
|
||||
}
|
||||
|
||||
if (context.res.statusCode === 412) {
|
||||
throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of Precondition Failed (412). There is new data exists for this resource. Make the request again with latest data.`, UserDataSyncErrorCode.PreconditionFailed, operationId);
|
||||
throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of Precondition Failed (412). There is new data for this resource. Make the request again with latest data.`, UserDataSyncErrorCode.PreconditionFailed, operationId);
|
||||
}
|
||||
|
||||
if (context.res.statusCode === 413) {
|
||||
@@ -482,7 +482,7 @@ export class RequestsSession {
|
||||
|
||||
if (this.requests.length >= this.limit) {
|
||||
this.logService.info('Too many requests', ...this.requests);
|
||||
throw new UserDataSyncStoreError(`Too many requests. Allowed only ${this.limit} requests in ${this.interval / (1000 * 60)} minutes.`, UserDataSyncErrorCode.LocalTooManyRequests, undefined);
|
||||
throw new UserDataSyncStoreError(`Too many requests. Only ${this.limit} requests allowed in ${this.interval / (1000 * 60)} minutes.`, UserDataSyncErrorCode.LocalTooManyRequests, undefined);
|
||||
}
|
||||
|
||||
this.startTime = this.startTime || new Date();
|
||||
|
||||
@@ -33,7 +33,7 @@ export class UserDataAutoSyncService extends BaseUserDataAutoSyncService {
|
||||
this._register(Event.debounce<string, string[]>(Event.any<string>(
|
||||
Event.map(electronService.onWindowFocus, () => 'windowFocus'),
|
||||
Event.map(electronService.onWindowOpen, () => 'windowOpen'),
|
||||
), (last, source) => last ? [...last, source] : [source], 1000)(sources => this.triggerSync(sources, true)));
|
||||
), (last, source) => last ? [...last, source] : [source], 1000)(sources => this.triggerSync(sources, true, false)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class TestUserDataAutoSyncService extends UserDataAutoSyncService {
|
||||
protected getSyncTriggerDelayTime(): number { return 50; }
|
||||
|
||||
sync(): Promise<void> {
|
||||
return this.triggerSync(['sync'], false);
|
||||
return this.triggerSync(['sync'], false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ suite('UserDataAutoSyncService', () => {
|
||||
const testObject: UserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService);
|
||||
|
||||
// Trigger auto sync with settings change
|
||||
await testObject.triggerSync([SyncResource.Settings], false);
|
||||
await testObject.triggerSync([SyncResource.Settings], false, false);
|
||||
|
||||
// Filter out machine requests
|
||||
const actual = target.requests.filter(request => !request.url.startsWith(`${target.url}/v1/resource/machines`));
|
||||
@@ -66,7 +66,7 @@ suite('UserDataAutoSyncService', () => {
|
||||
|
||||
// Trigger auto sync with settings change multiple times
|
||||
for (let counter = 0; counter < 2; counter++) {
|
||||
await testObject.triggerSync([SyncResource.Settings], false);
|
||||
await testObject.triggerSync([SyncResource.Settings], false, false);
|
||||
}
|
||||
|
||||
// Filter out machine requests
|
||||
@@ -91,7 +91,7 @@ suite('UserDataAutoSyncService', () => {
|
||||
const testObject: UserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService);
|
||||
|
||||
// Trigger auto sync with window focus once
|
||||
await testObject.triggerSync(['windowFocus'], true);
|
||||
await testObject.triggerSync(['windowFocus'], true, false);
|
||||
|
||||
// Filter out machine requests
|
||||
const actual = target.requests.filter(request => !request.url.startsWith(`${target.url}/v1/resource/machines`));
|
||||
@@ -114,7 +114,7 @@ suite('UserDataAutoSyncService', () => {
|
||||
|
||||
// Trigger auto sync with window focus multiple times
|
||||
for (let counter = 0; counter < 2; counter++) {
|
||||
await testObject.triggerSync(['windowFocus'], true);
|
||||
await testObject.triggerSync(['windowFocus'], true, false);
|
||||
}
|
||||
|
||||
// Filter out machine requests
|
||||
@@ -401,4 +401,28 @@ suite('UserDataAutoSyncService', () => {
|
||||
assert.deepEqual(target.requests, []);
|
||||
});
|
||||
|
||||
test('test cache control header with no cache is sent when triggered with disable cache option', async () => {
|
||||
const target = new UserDataSyncTestServer(5, 1);
|
||||
|
||||
// Set up and sync from the test client
|
||||
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||
await testClient.setUp();
|
||||
const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService);
|
||||
|
||||
await testObject.triggerSync(['some reason'], true, true);
|
||||
assert.equal(target.requestsWithAllHeaders[0].headers!['Cache-Control'], 'no-cache');
|
||||
});
|
||||
|
||||
test('test cache control header is not sent when triggered without disable cache option', async () => {
|
||||
const target = new UserDataSyncTestServer(5, 1);
|
||||
|
||||
// Set up and sync from the test client
|
||||
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||
await testClient.setUp();
|
||||
const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService);
|
||||
|
||||
await testObject.triggerSync(['some reason'], true, false);
|
||||
assert.equal(target.requestsWithAllHeaders[0].headers!['Cache-Control'], undefined);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { IRequestService } from 'vs/platform/request/common/request';
|
||||
import { IRequestOptions, IRequestContext, IHeaders } from 'vs/base/parts/request/common/request';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IUserData, IUserDataManifest, ALL_SYNC_RESOURCES, IUserDataSyncLogService, IUserDataSyncStoreService, IUserDataSyncUtilService, IUserDataSyncResourceEnablementService, IUserDataSyncService, getDefaultIgnoredSettings, IUserDataSyncBackupStoreService, SyncResource, ServerResource, IUserDataSyncStoreManagementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IUserData, IUserDataManifest, ALL_SYNC_RESOURCES, IUserDataSyncLogService, IUserDataSyncStoreService, IUserDataSyncUtilService, IUserDataSyncResourceEnablementService, IUserDataSyncService, getDefaultIgnoredSettings, IUserDataSyncBackupStoreService, SyncResource, ServerResource, IUserDataSyncStoreManagementService, registerConfiguration } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { bufferToStream, VSBuffer } from 'vs/base/common/buffer';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService';
|
||||
@@ -49,6 +49,7 @@ export class UserDataSyncClient extends Disposable {
|
||||
}
|
||||
|
||||
async setUp(empty: boolean = false): Promise<void> {
|
||||
registerConfiguration();
|
||||
const userRoamingDataHome = URI.file('userdata').with({ scheme: Schemas.inMemory });
|
||||
const userDataSyncHome = joinPath(userRoamingDataHome, '.sync');
|
||||
const environmentService = this.instantiationService.stub(IEnvironmentService, <Partial<IEnvironmentService>>{
|
||||
|
||||
Reference in New Issue
Block a user