diff --git a/packages/data-center/src/datacenter.ts b/packages/data-center/src/datacenter.ts index 00ca590ae3..907b0e310a 100644 --- a/packages/data-center/src/datacenter.ts +++ b/packages/data-center/src/datacenter.ts @@ -1,6 +1,6 @@ import { Workspaces } from './workspaces'; import type { WorkspacesChangeEvent } from './workspaces'; -import { BlobStorage, Workspace } from '@blocksuite/store'; +import { Workspace } from '@blocksuite/store'; import { BaseProvider } from './provider/base'; import { LocalProvider } from './provider/local/local'; import { AffineProvider } from './provider'; @@ -17,6 +17,7 @@ import { applyUpdate, encodeStateAsUpdate } from 'yjs'; export class DataCenter { private readonly _workspaces = new Workspaces(); private readonly _logger = getLogger('dc'); + private _workspaceInstances: Map = new Map(); /** * A mainProvider must exist as the only data trustworthy source. */ @@ -109,9 +110,14 @@ export class DataCenter { * @param {string} workspaceId workspace id */ private _getWorkspace(workspaceId: string) { - return new Workspace({ - room: workspaceId, - }).register(BlockSchema); + const workspaceInfo = this._workspaces.find(workspaceId); + assert(workspaceInfo, 'Workspace not found'); + return ( + this._workspaceInstances.get(workspaceId) || + new Workspace({ + room: workspaceId, + }).register(BlockSchema) + ); } /** @@ -149,8 +155,9 @@ export class DataCenter { const provider = this.providerMap.get(workspaceInfo.provider); assert(provider, `provide '${workspaceInfo.provider}' is not registered`); this._logger(`Loading ${workspaceInfo.provider} workspace: `, workspaceId); - - return await provider.warpWorkspace(this._getWorkspace(workspaceId)); + const workspace = this._getWorkspace(workspaceId); + this._workspaceInstances.set(workspaceId, workspace); + return await provider.warpWorkspace(workspace); } /** @@ -332,21 +339,23 @@ export class DataCenter { return; } - // /** - // * get blob url by workspaces id - // * @param id - // * @returns {Promise} blob url - // */ - // async getBlob(id: string): Promise { - // return await this._blobStorage.get(id); - // } + /** + * get blob url by workspaces id + * @param id + * @returns {Promise} blob url + */ + async getBlob(workspace: Workspace, id: string): Promise { + const blob = await workspace.blobs; + return (await blob?.get(id)) || ''; + } - // /** - // * up load blob and get a blob url - // * @param id - // * @returns {Promise} blob url - // */ - // async setBlob(blob: Blob): Promise { - // return await this._blobStorage.set(blob); - // } + /** + * up load blob and get a blob url + * @param id + * @returns {Promise} blob url + */ + async setBlob(workspace: Workspace, blob: Blob): Promise { + const blobStorage = await workspace.blobs; + return (await blobStorage?.set(blob)) || ''; + } } diff --git a/packages/data-center/src/provider/affine/affine.ts b/packages/data-center/src/provider/affine/affine.ts index cb9b1704d3..28cb19f1f6 100644 --- a/packages/data-center/src/provider/affine/affine.ts +++ b/packages/data-center/src/provider/affine/affine.ts @@ -69,7 +69,7 @@ export class AffineProvider extends BaseProvider { override async warpWorkspace(workspace: Workspace) { const { doc, room } = workspace; assert(room); - this._initWorkspaceDb(workspace); + this.linkLocal(workspace); const updates = await downloadWorkspace(room); if (updates) { await new Promise(resolve => { @@ -77,8 +77,12 @@ export class AffineProvider extends BaseProvider { applyUpdate(doc, new Uint8Array(updates)); }); } - const ws = new WebsocketProvider('/', room, doc); - this._wsMap.set(room, ws); + let ws = this._wsMap.get(room); + if (!ws) { + ws = new WebsocketProvider('/', room, doc); + this._wsMap.set(room, ws); + } + ws.connect(); await new Promise((resolve, reject) => { // TODO: synced will also be triggered on reconnection after losing sync // There needs to be an event mechanism to emit the synchronization state to the upper layer @@ -231,7 +235,7 @@ export class AffineProvider extends BaseProvider { return await removeMember({ permissionId }); } - private async _initWorkspaceDb(workspace: Workspace) { + public override async linkLocal(workspace: Workspace) { assert(workspace.room); let idb = this._idbMap.get(workspace.room); idb?.destroy(); @@ -239,7 +243,7 @@ export class AffineProvider extends BaseProvider { this._idbMap.set(workspace.room, idb); await idb.whenSynced; this._logger('Local data loaded'); - return idb; + return workspace; } public override async createWorkspace( @@ -252,7 +256,7 @@ export class AffineProvider extends BaseProvider { room: id, }).register(BlockSchema); nw.meta.setName(meta.name); - this._initWorkspaceDb(nw); + this.linkLocal(nw); const workspaceInfo: WS = { name: meta.name, diff --git a/packages/data-center/src/provider/base.ts b/packages/data-center/src/provider/base.ts index 249a536f21..5f531e2940 100644 --- a/packages/data-center/src/provider/base.ts +++ b/packages/data-center/src/provider/base.ts @@ -169,4 +169,13 @@ export class BaseProvider { email; return null; } + + /** + * link workspace to local caches + * @param workspace + * @returns + */ + public async linkLocal(workspace: Workspace): Promise { + return workspace; + } } diff --git a/packages/data-center/src/provider/local/local.ts b/packages/data-center/src/provider/local/local.ts index fb73ccce42..10df431481 100644 --- a/packages/data-center/src/provider/local/local.ts +++ b/packages/data-center/src/provider/local/local.ts @@ -22,21 +22,21 @@ export class LocalProvider extends BaseProvider { storage.setItem(WORKSPACE_KEY, JSON.stringify(workspaces)); } - private async _initWorkspaceDb(workspace: Workspace) { + public override async linkLocal(workspace: Workspace) { assert(workspace.room); let idb = this._idbMap.get(workspace.room); idb?.destroy(); idb = new IndexedDBProvider(workspace.room, workspace.doc); this._idbMap.set(workspace.room, idb); this._logger('Local data loaded'); - return idb; + return workspace; } public override async warpWorkspace( workspace: Workspace ): Promise { assert(workspace.room); - await this._initWorkspaceDb(workspace); + await this.linkLocal(workspace); return workspace; } @@ -93,7 +93,7 @@ export class LocalProvider extends BaseProvider { }; const workspace = new Workspace({ room: workspaceInfo.id }); - this._initWorkspaceDb(workspace); + this.linkLocal(workspace); workspace.meta.setName(meta.name); if (!meta.avatar) { // set default avatar