userDataSyncMachines.ts 5.6 KB
Newer Older
S
Sandeep Somavarapu 已提交
1 2 3 4 5 6 7 8 9 10 11
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Disposable } from 'vs/base/common/lifecycle';
import { getServiceMachineId } from 'vs/platform/serviceMachineId/common/serviceMachineId';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IFileService } from 'vs/platform/files/common/files';
import { IStorageService } from 'vs/platform/storage/common/storage';
S
Sandeep Somavarapu 已提交
12
import { IUserDataSyncStoreService, IUserData, IUserDataSyncLogService, IUserDataManifest } from 'vs/platform/userDataSync/common/userDataSync';
S
Sandeep Somavarapu 已提交
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
import { localize } from 'vs/nls';
import { IProductService } from 'vs/platform/product/common/productService';

interface IMachineData {
	id: string;
	name: string;
	disabled?: boolean;
}

interface IMachinesData {
	version: number;
	machines: IMachineData[];
}

export type IUserDataSyncMachine = Readonly<IMachineData> & { readonly isCurrent: boolean };


export const IUserDataSyncMachinesService = createDecorator<IUserDataSyncMachinesService>('IUserDataSyncMachinesService');
export interface IUserDataSyncMachinesService {
	_serviceBrand: any;

S
Sandeep Somavarapu 已提交
34 35
	getMachines(manifest?: IUserDataManifest): Promise<IUserDataSyncMachine[]>;
	updateName(name: string, manifest?: IUserDataManifest): Promise<void>;
S
Sandeep Somavarapu 已提交
36
	disable(id: string): Promise<void>
S
Sandeep Somavarapu 已提交
37 38

	unset(): Promise<void>;
S
Sandeep Somavarapu 已提交
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
}

export class UserDataSyncMachinesService extends Disposable implements IUserDataSyncMachinesService {

	private static readonly VERSION = 1;
	private static readonly RESOURCE = 'machines';

	_serviceBrand: any;

	private readonly currentMachineIdPromise: Promise<string>;
	private userData: IUserData | null = null;

	constructor(
		@IEnvironmentService environmentService: IEnvironmentService,
		@IFileService fileService: IFileService,
		@IStorageService storageService: IStorageService,
		@IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService,
		@IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
		@IProductService private readonly productService: IProductService,
	) {
		super();
		this.currentMachineIdPromise = getServiceMachineId(environmentService, fileService, storageService);
	}

S
Sandeep Somavarapu 已提交
63
	async getMachines(manifest?: IUserDataManifest): Promise<IUserDataSyncMachine[]> {
S
Sandeep Somavarapu 已提交
64
		const currentMachineId = await this.currentMachineIdPromise;
S
Sandeep Somavarapu 已提交
65
		const machineData = await this.readMachinesData(manifest);
S
Sandeep Somavarapu 已提交
66 67 68
		return machineData.machines.map<IUserDataSyncMachine>(machine => ({ ...machine, ...{ isCurrent: machine.id === currentMachineId } }));
	}

S
Sandeep Somavarapu 已提交
69
	async updateName(name: string, manifest?: IUserDataManifest): Promise<void> {
S
Sandeep Somavarapu 已提交
70
		const currentMachineId = await this.currentMachineIdPromise;
S
Sandeep Somavarapu 已提交
71
		const machineData = await this.readMachinesData(manifest);
S
Sandeep Somavarapu 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
		let currentMachine = machineData.machines.find(({ id }) => id === currentMachineId);
		if (currentMachine) {
			currentMachine.name = name;
		} else {
			machineData.machines.push({ id: currentMachineId, name });
		}
		await this.writeMachinesData(machineData);
	}

	async unset(): Promise<void> {
		const currentMachineId = await this.currentMachineIdPromise;
		const machineData = await this.readMachinesData();
		const updatedMachines = machineData.machines.filter(({ id }) => id !== currentMachineId);
		if (updatedMachines.length !== machineData.machines.length) {
			machineData.machines = updatedMachines;
			await this.writeMachinesData(machineData);
		}
	}

	async disable(machineId: string): Promise<void> {
		const machineData = await this.readMachinesData();
		const machine = machineData.machines.find(({ id }) => id === machineId);
		if (machine) {
			machine.disabled = true;
			await this.writeMachinesData(machineData);
		}
	}

S
Sandeep Somavarapu 已提交
100 101
	private async readMachinesData(manifest?: IUserDataManifest): Promise<IMachinesData> {
		this.userData = await this.readUserData(manifest);
S
Sandeep Somavarapu 已提交
102 103 104 105 106 107 108 109 110 111 112 113 114
		const machinesData = this.parse(this.userData);
		if (machinesData.version !== UserDataSyncMachinesService.VERSION) {
			throw new Error(localize('error incompatible', "Cannot read machines data as the current version is incompatible. Please update {0} and try again.", this.productService.nameLong));
		}
		return machinesData;
	}

	private async writeMachinesData(machinesData: IMachinesData): Promise<void> {
		const content = JSON.stringify(machinesData);
		const ref = await this.userDataSyncStoreService.write(UserDataSyncMachinesService.RESOURCE, content, this.userData?.ref || null);
		this.userData = { ref, content };
	}

S
Sandeep Somavarapu 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
	private async readUserData(manifest?: IUserDataManifest): Promise<IUserData> {
		if (this.userData) {

			const latestRef = manifest && manifest.latest ? manifest.latest[UserDataSyncMachinesService.RESOURCE] : undefined;

			// Last time synced resource and latest resource on server are same
			if (this.userData.ref === latestRef) {
				return this.userData;
			}

			// There is no resource on server and last time it was synced with no resource
			if (latestRef === undefined && this.userData.content === null) {
				return this.userData;
			}
		}

		return this.userDataSyncStoreService.read(UserDataSyncMachinesService.RESOURCE, this.userData);
	}

S
Sandeep Somavarapu 已提交
134 135 136 137 138 139 140 141 142 143 144 145 146 147
	private parse(userData: IUserData): IMachinesData {
		if (userData.content !== null) {
			try {
				return JSON.parse(userData.content);
			} catch (e) {
				this.logService.error(e);
			}
		}
		return {
			version: UserDataSyncMachinesService.VERSION,
			machines: []
		};
	}
}