1
>
/*---------------------------------------------------------------------------------------------
userDataSyncService.ts
2
>
* Copyright (c) Microsoft Corporation. All rights reserved.
3
>
* Licensed under the MIT License. See License.txt in the project root for license information.
4
>
*--------------------------------------------------------------------------------------------*/
5
>
6
>
import { equals } from '../../../base/common/arrays.js';
7
>
import { CancelablePromise, createCancelablePromise, RunOnceScheduler } from '../../../base/common/async.js';
8
>
import { CancellationToken, CancellationTokenSource } from '../../../base/common/cancellation.js';
9
>
import { toErrorMessage } from '../../../base/common/errorMessage.js';
10
>
import { Emitter, Event } from '../../../base/common/event.js';
11
>
import { Disposable, DisposableStore, IDisposable, toDisposable } from '../../../base/common/lifecycle.js';
12
>
import { isEqual } from '../../../base/common/resources.js';
13
>
import { isBoolean, isUndefined } from '../../../base/common/types.js';
14
>
import { URI } from '../../../base/common/uri.js';
15
>
import { generateUuid } from '../../../base/common/uuid.js';
16
>
import { IConfigurationService } from '../../configuration/common/configuration.js';
17
>
import { IExtensionGalleryService } from '../../extensionManagement/common/extensionManagement.js';
18
>
import { IFileService } from '../../files/common/files.js';
19
>
import { IInstantiationService } from '../../instantiation/common/instantiation.js';
20
>
import { IStorageService, StorageScope, StorageTarget } from '../../storage/common/storage.js';
21
>
import { ITelemetryService } from '../../telemetry/common/telemetry.js';
22
>
import { IUserDataProfile, IUserDataProfilesService } from '../../userDataProfile/common/userDataProfile.js';
23
>
import { ExtensionsSynchroniser } from './extensionsSync.js';
24
>
import { GlobalStateSynchroniser } from './globalStateSync.js';
25
>
import { KeybindingsSynchroniser } from './keybindingsSync.js';
26
>
import { PromptsSynchronizer } from './promptsSync/promptsSync.js';
27
>
import { SettingsSynchroniser } from './settingsSync.js';
28
>
import { SnippetsSynchroniser } from './snippetsSync.js';
29
>
import { TasksSynchroniser } from './tasksSync.js';
30
>
import { McpSynchroniser } from './mcpSync.js';
31
>
import { UserDataProfilesManifestSynchroniser } from './userDataProfilesManifestSync.js';
32
>
import {
33
>
ALL_SYNC_RESOURCES, createSyncHeaders, IUserDataManualSyncTask, IUserDataSyncResourceConflicts, IUserDataSyncResourceError,
34
>
IUserDataSyncResource, ISyncResourceHandle, IUserDataSyncTask, ISyncUserDataProfile, IUserDataManifest, IUserDataSyncConfiguration,
35
>
IUserDataSyncEnablementService, IUserDataSynchroniser, IUserDataSyncLogService, IUserDataSyncService, IUserDataSyncStoreManagementService, IUserDataSyncStoreService,
36
>
SyncResource, SyncStatus, UserDataSyncError, UserDataSyncErrorCode, UserDataSyncStoreError, USER_DATA_SYNC_CONFIGURATION_SCOPE, IUserDataSyncResourceProviderService, IUserDataSyncActivityData, IUserDataSyncLocalStoreService,
37
>
IUserDataSyncLatestData,
38
>
IUserData,
39
>
isUserDataManifest,
40
>
} from './userDataSync.js';
41
>
42
>
type SyncErrorClassification = {
43
>
owner: 'sandy081';
44
>
comment: 'Information about the error that occurred while syncing';
45
>
code: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'error code' };
46
>
service: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Settings Sync service for which this error has occurred' };
47
>
serverCode?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Settings Sync service error code' };
48
>
url?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Settings Sync resource URL for which this error has occurred' };
49
>
resource?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Settings Sync resource for which this error has occurred' };
50
>
executionId?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Settings Sync execution id for which this error has occurred' };
51
>
};
52
>
53
>
type SyncErrorEvent = {
54
>
code: string;
55
>
service: string;
56
>
serverCode?: string;
57
>
url?: string;
58
>
resource?: string;
59
>
executionId?: string;
60
>
};
61
>
62
>
const LAST_SYNC_TIME_KEY = 'sync.lastSyncTime';
63
>
64
>
export class UserDataSyncService extends Disposable implements IUserDataSyncService {
65
>
66
>
_serviceBrand: undefined;
67
>
68
>
private _status: SyncStatus = SyncStatus.Uninitialized;
69
>
get status(): SyncStatus { return this._status; }
70
>
private _onDidChangeStatus: Emitter<SyncStatus> = this._register(new Emitter<SyncStatus>());
71
>
readonly onDidChangeStatus: Event<SyncStatus> = this._onDidChangeStatus.event;
72
>
73
>
private _onDidChangeLocal = this._register(new Emitter<SyncResource>());
74
>
readonly onDidChangeLocal = this._onDidChangeLocal.event;
75
>
76
>
private _conflicts: IUserDataSyncResourceConflicts[] = [];
77
>
get conflicts(): IUserDataSyncResourceConflicts[] { return this._conflicts; }
78
>
private _onDidChangeConflicts = this._register(new Emitter<IUserDataSyncResourceConflicts[]>());
79
>
readonly onDidChangeConflicts = this._onDidChangeConflicts.event;
80
>
81
>
private _syncErrors: IUserDataSyncResourceError[] = [];
82
>
private _onSyncErrors = this._register(new Emitter<IUserDataSyncResourceError[]>());
83
>
readonly onSyncErrors = this._onSyncErrors.event;
84
>
85
>
private _lastSyncTime: number | undefined = undefined;
86
>
get lastSyncTime(): number | undefined { return this._lastSyncTime; }
87
>
private _onDidChangeLastSyncTime: Emitter<number> = this._register(new Emitter<number>());
88
>
readonly onDidChangeLastSyncTime: Event<number> = this._onDidChangeLastSyncTime.event;
89
>
90
>
private _onDidResetLocal = this._register(new Emitter<void>());
91
>
readonly onDidResetLocal = this._onDidResetLocal.event;
92
>
93
>
private _onDidResetRemote = this._register(new Emitter<void>());
94
>
readonly onDidResetRemote = this._onDidResetRemote.event;
95
>
96
>
private activeProfileSynchronizers = new Map<string, [ProfileSynchronizer, IDisposable]>();
97
>
98
>
constructor(
99
@IFileService private readonly fileService: IFileService,
100
@IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService,