diff --git a/packages/data-center/src/provider/affine/affine.ts b/packages/data-center/src/provider/affine/affine.ts index 025ef96d3..d4c786f46 100644 --- a/packages/data-center/src/provider/affine/affine.ts +++ b/packages/data-center/src/provider/affine/affine.ts @@ -13,7 +13,11 @@ import { getApis, Workspace } from './apis/index.js'; import type { Apis, WorkspaceDetail, Callback } from './apis'; import { token } from './apis/token.js'; import { WebsocketClient } from './channel'; -import { loadWorkspaceUnit, createWorkspaceUnit } from './utils.js'; +import { + loadWorkspaceUnit, + createWorkspaceUnit, + migrateBlobDB, +} from './utils.js'; import { WorkspaceUnit } from '../../workspace-unit.js'; import { createBlocksuiteWorkspace, applyUpdate } from '../../utils/index.js'; import type { SyncMode } from '../../workspace-unit'; @@ -390,6 +394,8 @@ export class AffineProvider extends BaseProvider { syncMode: 'core', }); + await migrateBlobDB(workspaceUnit.id, id); + const blocksuiteWorkspace = createBlocksuiteWorkspace(id); assert(workspaceUnit.blocksuiteWorkspace); await applyUpdate( diff --git a/packages/data-center/src/provider/affine/idb-kv.ts b/packages/data-center/src/provider/affine/idb-kv.ts new file mode 100644 index 000000000..72f854dd8 --- /dev/null +++ b/packages/data-center/src/provider/affine/idb-kv.ts @@ -0,0 +1,23 @@ +import { createStore, keys, setMany, getMany } from 'idb-keyval'; +import * as idb from 'lib0/indexeddb.js'; + +type IDBInstance = { + keys: () => Promise; + deleteDB: () => Promise; + setMany: (entries: [string, T][]) => Promise; + getMany: (keys: string[]) => Promise; +}; + +export function getDatabase( + type: string, + database: string +): IDBInstance { + const name = `${database}_${type}`; + const db = createStore(name, type); + return { + keys: () => keys(db), + deleteDB: () => idb.deleteDB(name), + setMany: entries => setMany(entries, db), + getMany: keys => getMany(keys, db), + }; +} diff --git a/packages/data-center/src/provider/affine/utils.ts b/packages/data-center/src/provider/affine/utils.ts index 4bb401fbf..25e2127e5 100644 --- a/packages/data-center/src/provider/affine/utils.ts +++ b/packages/data-center/src/provider/affine/utils.ts @@ -4,6 +4,7 @@ import { createBlocksuiteWorkspace } from '../../utils/index.js'; import type { Apis } from './apis'; import { setDefaultAvatar } from '../utils.js'; import { applyUpdate } from '../../utils/index.js'; +import { getDatabase } from './idb-kv.js'; export const loadWorkspaceUnit = async ( params: WorkspaceUnitCtorParams, @@ -54,3 +55,34 @@ export const createWorkspaceUnit = async (params: WorkspaceUnitCtorParams) => { return workspaceUnit; }; + +interface PendingTask { + id: string; + blob: ArrayBufferLike; +} + +export const migrateBlobDB = async ( + oldWorkspaceId: string, + newWorkspaceId: string +) => { + const oldDB = getDatabase('blob', oldWorkspaceId); + const oldPendingDB = getDatabase('pending', newWorkspaceId); + + const newDB = getDatabase('blob', newWorkspaceId); + const newPendingDB = getDatabase('pending', newWorkspaceId); + + const keys = await oldDB.keys(); + const values = await oldDB.getMany(keys); + const entries = keys.map((key, index) => { + return [key, values[index]] as [string, ArrayBufferLike]; + }); + await newDB.setMany(entries); + + const pendingEntries = entries.map(([id, blob]) => { + return [id, { id, blob }] as [string, PendingTask]; + }); + await newPendingDB.setMany(pendingEntries); + + await oldDB.deleteDB(); + await oldPendingDB.deleteDB(); +};