userDataSyncMachines.ts 6.2 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[]>;

S
Sandeep Somavarapu 已提交
36 37 38 39 40
	addCurrentMachine(name: string, manifest?: IUserDataManifest): Promise<void>;
	removeCurrentMachine(manifest?: IUserDataManifest): Promise<void>;

	renameMachine(machineId: string, name: string): Promise<void>;
	disableMachine(machineId: string): Promise<void>
S
Sandeep Somavarapu 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
}

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

S
Sandeep Somavarapu 已提交
71
	async addCurrentMachine(name: string, manifest?: IUserDataManifest): Promise<void> {
S
Sandeep Somavarapu 已提交
72
		const currentMachineId = await this.currentMachineIdPromise;
S
Sandeep Somavarapu 已提交
73
		const machineData = await this.readMachinesData(manifest);
S
Sandeep Somavarapu 已提交
74 75 76 77 78 79 80 81 82
		let currentMachine = machineData.machines.find(({ id }) => id === currentMachineId);
		if (currentMachine) {
			currentMachine.name = name;
		} else {
			machineData.machines.push({ id: currentMachineId, name });
		}
		await this.writeMachinesData(machineData);
	}

S
Sandeep Somavarapu 已提交
83
	async removeCurrentMachine(manifest?: IUserDataManifest): Promise<void> {
S
Sandeep Somavarapu 已提交
84
		const currentMachineId = await this.currentMachineIdPromise;
S
Sandeep Somavarapu 已提交
85
		const machineData = await this.readMachinesData(manifest);
S
Sandeep Somavarapu 已提交
86 87 88 89 90 91 92
		const updatedMachines = machineData.machines.filter(({ id }) => id !== currentMachineId);
		if (updatedMachines.length !== machineData.machines.length) {
			machineData.machines = updatedMachines;
			await this.writeMachinesData(machineData);
		}
	}

S
Sandeep Somavarapu 已提交
93 94 95 96 97 98 99 100 101 102
	async renameMachine(machineId: string, name: string, manifest?: IUserDataManifest): Promise<void> {
		const machineData = await this.readMachinesData(manifest);
		const currentMachine = machineData.machines.find(({ id }) => id === machineId);
		if (currentMachine) {
			currentMachine.name = name;
			await this.writeMachinesData(machineData);
		}
	}

	async disableMachine(machineId: string): Promise<void> {
S
Sandeep Somavarapu 已提交
103 104 105 106 107 108 109 110
		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 已提交
111 112
	private async readMachinesData(manifest?: IUserDataManifest): Promise<IMachinesData> {
		this.userData = await this.readUserData(manifest);
S
Sandeep Somavarapu 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125
		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 已提交
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
	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 已提交
145 146 147 148 149 150 151 152 153 154 155 156 157 158
	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: []
		};
	}
}