UNPKG

@sussudio/platform

Version:

Internal APIs for VS Code's service injection the base services.

163 lines (162 loc) 6.75 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Promises } from '@sussudio/base/common/async.mjs'; import { DisposableStore } from '@sussudio/base/common/lifecycle.mjs'; import { joinPath } from '@sussudio/base/common/resources.mjs'; import { Storage } from '@sussudio/base/parts/storage/common/storage.mjs'; import { AbstractStorageService, isProfileUsingDefaultStorage, WillSaveStateReason } from '../common/storage.mjs'; import { ApplicationStorageDatabaseClient, ProfileStorageDatabaseClient, WorkspaceStorageDatabaseClient, } from '../common/storageIpc.mjs'; import { isUserDataProfile } from '../../userDataProfile/common/userDataProfile.mjs'; export class NativeStorageService extends AbstractStorageService { initialWorkspace; initialProfiles; mainProcessService; environmentService; applicationStorageProfile = this.initialProfiles.defaultProfile; applicationStorage = this.createApplicationStorage(); profileStorageProfile = this.initialProfiles.currentProfile; profileStorageDisposables = this._register(new DisposableStore()); profileStorage = this.createProfileStorage(this.profileStorageProfile); workspaceStorageId = this.initialWorkspace?.id; workspaceStorageDisposables = this._register(new DisposableStore()); workspaceStorage = this.createWorkspaceStorage(this.initialWorkspace); constructor(initialWorkspace, initialProfiles, mainProcessService, environmentService) { super(); this.initialWorkspace = initialWorkspace; this.initialProfiles = initialProfiles; this.mainProcessService = mainProcessService; this.environmentService = environmentService; } createApplicationStorage() { const storageDataBaseClient = this._register( new ApplicationStorageDatabaseClient(this.mainProcessService.getChannel('storage')), ); const applicationStorage = this._register(new Storage(storageDataBaseClient)); this._register( applicationStorage.onDidChangeStorage((key) => this.emitDidChangeValue(-1 /* StorageScope.APPLICATION */, key)), ); return applicationStorage; } createProfileStorage(profile) { // First clear any previously associated disposables this.profileStorageDisposables.clear(); // Remember profile associated to profile storage this.profileStorageProfile = profile; let profileStorage; if (isProfileUsingDefaultStorage(profile)) { // If we are using default profile storage, the profile storage is // actually the same as application storage. As such we // avoid creating the storage library a second time on // the same DB. profileStorage = this.applicationStorage; } else { const storageDataBaseClient = this.profileStorageDisposables.add( new ProfileStorageDatabaseClient(this.mainProcessService.getChannel('storage'), profile), ); profileStorage = this.profileStorageDisposables.add(new Storage(storageDataBaseClient)); } this.profileStorageDisposables.add( profileStorage.onDidChangeStorage((key) => this.emitDidChangeValue(0 /* StorageScope.PROFILE */, key)), ); return profileStorage; } createWorkspaceStorage(workspace) { // First clear any previously associated disposables this.workspaceStorageDisposables.clear(); // Remember workspace ID for logging later this.workspaceStorageId = workspace?.id; let workspaceStorage = undefined; if (workspace) { const storageDataBaseClient = this.workspaceStorageDisposables.add( new WorkspaceStorageDatabaseClient(this.mainProcessService.getChannel('storage'), workspace), ); workspaceStorage = this.workspaceStorageDisposables.add(new Storage(storageDataBaseClient)); this.workspaceStorageDisposables.add( workspaceStorage.onDidChangeStorage((key) => this.emitDidChangeValue(1 /* StorageScope.WORKSPACE */, key)), ); } return workspaceStorage; } async doInitialize() { // Init all storage locations await Promises.settled([ this.applicationStorage.init(), this.profileStorage.init(), this.workspaceStorage?.init() ?? Promise.resolve(), ]); } getStorage(scope) { switch (scope) { case -1 /* StorageScope.APPLICATION */: return this.applicationStorage; case 0 /* StorageScope.PROFILE */: return this.profileStorage; default: return this.workspaceStorage; } } getLogDetails(scope) { switch (scope) { case -1 /* StorageScope.APPLICATION */: return this.applicationStorageProfile.globalStorageHome.fsPath; case 0 /* StorageScope.PROFILE */: return this.profileStorageProfile?.globalStorageHome.fsPath; default: return this.workspaceStorageId ? `${joinPath(this.environmentService.workspaceStorageHome, this.workspaceStorageId, 'state.vscdb').fsPath}` : undefined; } } async close() { // Stop periodic scheduler and idle runner as we now collect state normally this.stopFlushWhenIdle(); // Signal as event so that clients can still store data this.emitWillSaveState(WillSaveStateReason.SHUTDOWN); // Do it await Promises.settled([ this.applicationStorage.close(), this.profileStorage.close(), this.workspaceStorage?.close() ?? Promise.resolve(), ]); } async switchToProfile(toProfile, preserveData) { if (!this.canSwitchProfile(this.profileStorageProfile, toProfile)) { return; } const oldProfileStorage = this.profileStorage; const oldItems = oldProfileStorage.items; // Close old profile storage but only if this is // different from application storage! if (oldProfileStorage !== this.applicationStorage) { await oldProfileStorage.close(); } // Create new profile storage & init this.profileStorage = this.createProfileStorage(toProfile); await this.profileStorage.init(); // Handle data switch and eventing this.switchData(oldItems, this.profileStorage, 0 /* StorageScope.PROFILE */, preserveData); } async switchToWorkspace(toWorkspace, preserveData) { const oldWorkspaceStorage = this.workspaceStorage; const oldItems = oldWorkspaceStorage?.items ?? new Map(); // Close old workspace storage await oldWorkspaceStorage?.close(); // Create new workspace storage & init this.workspaceStorage = this.createWorkspaceStorage(toWorkspace); await this.workspaceStorage.init(); // Handle data switch and eventing this.switchData(oldItems, this.workspaceStorage, 1 /* StorageScope.WORKSPACE */, preserveData); } hasScope(scope) { if (isUserDataProfile(scope)) { return this.profileStorageProfile.id === scope.id; } return this.workspaceStorageId === scope.id; } }