diff --git a/packages/backend/server/src/core/doc/__tests__/reader-from-database.spec.ts b/packages/backend/server/src/core/doc/__tests__/reader-from-database.spec.ts index b7b88e4e7..baafb8f0d 100644 --- a/packages/backend/server/src/core/doc/__tests__/reader-from-database.spec.ts +++ b/packages/backend/server/src/core/doc/__tests__/reader-from-database.spec.ts @@ -251,4 +251,22 @@ test('should get workspace content with custom avatar', async t => { avatarKey, avatarUrl: `http://localhost:3010/api/workspaces/${workspace.id}/blobs/${avatarKey}`, }); + // should save to database + const workspace2 = await t.context.models.workspace.get(workspace.id); + t.truthy(workspace2); + t.is(workspace2!.name, 'Test Workspace'); + t.is(workspace2!.avatarKey, avatarKey); + + // read from database + await t.context.models.workspace.update(workspace.id, { + name: 'Test Workspace 2', + }); + const workspaceContent2 = await docReader.getWorkspaceContent(workspace.id); + t.truthy(workspaceContent2); + t.deepEqual(workspaceContent2, { + id: workspace.id, + name: 'Test Workspace 2', + avatarKey, + avatarUrl: `http://localhost:3010/api/workspaces/${workspace.id}/blobs/${avatarKey}`, + }); }); diff --git a/packages/backend/server/src/core/doc/reader.ts b/packages/backend/server/src/core/doc/reader.ts index d6dac0984..f0b13b6a3 100644 --- a/packages/backend/server/src/core/doc/reader.ts +++ b/packages/backend/server/src/core/doc/reader.ts @@ -14,6 +14,7 @@ import { getOrGenRequestId, UserFriendlyError, } from '../../base'; +import { Models } from '../../models'; import { WorkspaceBlobStorage } from '../storage'; import { type PageDocContent, @@ -33,7 +34,13 @@ export interface WorkspaceDocInfo { } export abstract class DocReader { - constructor(protected readonly cache: Cache) {} + protected readonly logger = new Logger(DocReader.name); + + constructor( + protected readonly cache: Cache, + protected readonly models: Models, + protected readonly blobStorage: WorkspaceBlobStorage + ) {} parseDocContent(bin: Uint8Array) { const doc = new YDoc(); @@ -78,19 +85,36 @@ export abstract class DocReader { return content; } - // TODO(@fengmk2): should remove this method after frontend support workspace content update + /** + * Get workspace content, try to read from database first. + * If not exists, read from `getWorkspaceContentWithoutCache()` and save it back to database. + */ async getWorkspaceContent( workspaceId: string ): Promise { - const cacheKey = this.cacheKey(workspaceId, workspaceId); - const cachedResult = await this.cache.get(cacheKey); - if (cachedResult) { - return cachedResult; + const workspace = await this.models.workspace.get(workspaceId); + if (!workspace) { + return null; + } + if (workspace.name) { + return { + id: workspaceId, + name: workspace.name, + avatarKey: workspace.avatarKey ?? undefined, + avatarUrl: workspace.avatarKey + ? this.blobStorage.getAvatarUrl(workspaceId, workspace.avatarKey) + : undefined, + }; } const content = await this.getWorkspaceContentWithoutCache(workspaceId); if (content) { - await this.cache.set(cacheKey, content); + await this.models.workspace.update(workspaceId, { + name: content.name, + avatarKey: content.avatarKey, + }); + } else { + this.logger.warn(`Workspace ${workspaceId} content not found`); } return content; } @@ -128,10 +152,11 @@ export abstract class DocReader { export class DatabaseDocReader extends DocReader { constructor( protected override readonly cache: Cache, - protected readonly workspace: PgWorkspaceDocStorageAdapter, - protected readonly blobStorage: WorkspaceBlobStorage + protected override readonly models: Models, + protected override readonly blobStorage: WorkspaceBlobStorage, + protected readonly workspace: PgWorkspaceDocStorageAdapter ) { - super(cache); + super(cache, models, blobStorage); } async getDoc(workspaceId: string, docId: string): Promise { @@ -190,16 +215,17 @@ export class DatabaseDocReader extends DocReader { @Injectable() export class RpcDocReader extends DatabaseDocReader { - private readonly logger = new Logger(DocReader.name); + protected override readonly logger = new Logger(DocReader.name); constructor( private readonly config: Config, private readonly crypto: CryptoHelper, protected override readonly cache: Cache, - protected override readonly workspace: PgWorkspaceDocStorageAdapter, - protected override readonly blobStorage: WorkspaceBlobStorage + protected override readonly models: Models, + protected override readonly blobStorage: WorkspaceBlobStorage, + protected override readonly workspace: PgWorkspaceDocStorageAdapter ) { - super(cache, workspace, blobStorage); + super(cache, models, blobStorage, workspace); } private async fetch( diff --git a/packages/backend/server/src/core/notification/service.ts b/packages/backend/server/src/core/notification/service.ts index f49539402..7a5c63a93 100644 --- a/packages/backend/server/src/core/notification/service.ts +++ b/packages/backend/server/src/core/notification/service.ts @@ -74,18 +74,7 @@ export class NotificationService { } private async ensureWorkspaceContentExists(workspaceId: string) { - const workspace = await this.models.workspace.get(workspaceId); - if (!workspace || workspace.name) { - return; - } - const content = await this.docReader.getWorkspaceContent(workspaceId); - if (!content?.name) { - return; - } - await this.models.workspace.update(workspaceId, { - name: content.name, - avatarKey: content.avatarKey, - }); + await this.docReader.getWorkspaceContent(workspaceId); } async markAsRead(userId: string, notificationId: string) {