diff --git a/packages/backend/server/src/__tests__/utils/workspace.ts b/packages/backend/server/src/__tests__/utils/workspace.ts index 9918950812..b3a61ce9ef 100644 --- a/packages/backend/server/src/__tests__/utils/workspace.ts +++ b/packages/backend/server/src/__tests__/utils/workspace.ts @@ -85,6 +85,21 @@ export async function updateWorkspace( return res.updateWorkspace.public; } +export async function deleteWorkspace( + app: TestingApp, + workspaceId: string +): Promise { + const res = await app.gql( + ` + mutation { + deleteWorkspace(id: "${workspaceId}") + } + ` + ); + + return res.deleteWorkspace; +} + export async function publishDoc( app: TestingApp, workspaceId: string, diff --git a/packages/backend/server/src/__tests__/workspace/blobs.e2e.ts b/packages/backend/server/src/__tests__/workspace/blobs.e2e.ts index 963f214cdf..bf3e1ccdf0 100644 --- a/packages/backend/server/src/__tests__/workspace/blobs.e2e.ts +++ b/packages/backend/server/src/__tests__/workspace/blobs.e2e.ts @@ -1,10 +1,13 @@ import test from 'ava'; +import Sinon from 'sinon'; +import { WorkspaceBlobStorage } from '../../core/storage/wrappers/blob'; import { WorkspaceFeatureModel } from '../../models'; import { collectAllBlobSizes, createTestingApp, createWorkspace, + deleteWorkspace, getWorkspaceBlobsSize, listBlobs, setBlob, @@ -77,6 +80,25 @@ test('should list blobs', async t => { t.deepEqual(ret.sort(), [hash1, hash2].sort()); }); +test('should auto delete blobs when workspace is deleted', async t => { + await app.signup('u1@affine.pro'); + + const workspace = await createWorkspace(app); + const buffer1 = Buffer.from([0, 0]); + await setBlob(app, workspace.id, buffer1); + const buffer2 = Buffer.from([0, 1]); + await setBlob(app, workspace.id, buffer2); + const size = await collectAllBlobSizes(app); + t.is(size, 4); + const blobs = await listBlobs(app, workspace.id); + t.is(blobs.length, 2); + + const workspaceBlobStorage = Sinon.spy(app.get(WorkspaceBlobStorage)); + await deleteWorkspace(app, workspace.id); + // should not emit workspace.blob.sync event + t.is(workspaceBlobStorage.syncBlobMeta.callCount, 0); +}); + test('should calc blobs size', async t => { await app.signup('u1@affine.pro'); diff --git a/packages/backend/server/src/core/storage/wrappers/blob.ts b/packages/backend/server/src/core/storage/wrappers/blob.ts index 5c3959fa55..274031a492 100644 --- a/packages/backend/server/src/core/storage/wrappers/blob.ts +++ b/packages/backend/server/src/core/storage/wrappers/blob.ts @@ -42,7 +42,7 @@ export class WorkspaceBlobStorage { return this.provider.get(`${workspaceId}/${key}`); } - async list(workspaceId: string) { + async list(workspaceId: string, syncBlobMeta = true) { const blobsInDb = await this.db.blob.findMany({ where: { workspaceId, @@ -59,7 +59,9 @@ export class WorkspaceBlobStorage { blob.key = blob.key.slice(workspaceId.length + 1); }); - this.trySyncBlobsMeta(workspaceId, blobs); + if (syncBlobMeta) { + this.trySyncBlobsMeta(workspaceId, blobs); + } return blobs.map(blob => ({ key: blob.key, @@ -182,7 +184,8 @@ export class WorkspaceBlobStorage { @OnEvent('workspace.deleted') async onWorkspaceDeleted({ id }: Events['workspace.deleted']) { - const blobs = await this.list(id); + // do not sync blob meta to DB + const blobs = await this.list(id, false); // to reduce cpu time holding blobs.forEach(blob => {