Просмотр исходного кода

refactor hasYdocsNewerThanLatestRevision as getYDocStatus

Yuki Takei 1 год назад
Родитель
Сommit
ea59a659a5

+ 3 - 2
apps/app/src/server/service/page/index.ts

@@ -7,7 +7,7 @@ import type {
   IPage, IPageInfo, IPageInfoAll, IPageInfoForEntity, IPageWithMeta, IGrantedGroup, IRevisionHasId,
 } from '@growi/core';
 import {
-  PageGrant, PageStatus, getIdForRef,
+  PageGrant, PageStatus, YDocStatus, getIdForRef,
 } from '@growi/core';
 import {
   pagePathUtils, pathUtils,
@@ -4438,7 +4438,8 @@ class PageService implements IPageService {
     const yjsService = getYjsService();
 
     const currentYdoc = yjsService.getCurrentYdoc(pageId);
-    const hasYdocsNewerThanLatestRevision = await yjsService.hasYdocsNewerThanLatestRevision(pageId);
+    const ydocStatus = await yjsService.getYDocStatus(pageId);
+    const hasYdocsNewerThanLatestRevision = ydocStatus === YDocStatus.DRAFT;
 
     return {
       hasYdocsNewerThanLatestRevision,

+ 41 - 19
apps/app/src/server/service/yjs.integ.ts

@@ -1,3 +1,4 @@
+import { YDocStatus } from '@growi/editor/dist/consts';
 import { Types } from 'mongoose';
 import type { Server } from 'socket.io';
 import { mock } from 'vitest-mock-extended';
@@ -11,6 +12,7 @@ import { getYjsService, initializeYjsService } from './yjs';
 
 vi.mock('y-socket.io/dist/server', () => {
   const YSocketIO = vi.fn();
+  YSocketIO.prototype.on = vi.fn();
   YSocketIO.prototype.initialize = vi.fn();
   return { YSocketIO };
 });
@@ -26,7 +28,7 @@ const getPrivateMdbInstance = (yjsService: IYjsService): MongodbPersistence => {
 
 describe('YjsService', () => {
 
-  describe('hasYdocsNewerThanLatestRevision()', () => {
+  describe('getYDocStatus()', () => {
 
     beforeAll(async() => {
       const ioMock = mock<Server>();
@@ -45,20 +47,20 @@ describe('YjsService', () => {
       await privateMdb.flushDB();
     });
 
-    it('returns false when neither revisions nor YDocs exists', async() => {
+    it('returns ISOLATED when neither revisions nor YDocs exists', async() => {
       // arrange
       const yjsService = getYjsService();
 
       const pageId = new ObjectId();
 
       // act
-      const result = await yjsService.hasYdocsNewerThanLatestRevision(pageId.toString());
+      const result = await yjsService.getYDocStatus(pageId.toString());
 
       // assert
-      expect(result).toBe(false);
+      expect(result).toBe(YDocStatus.ISOLATED);
     });
 
-    it('returns true when no revisions exist', async() => {
+    it('returns ISOLATED when no revisions exist', async() => {
       // arrange
       const yjsService = getYjsService();
 
@@ -68,13 +70,30 @@ describe('YjsService', () => {
       await privateMdb.setMeta(pageId.toString(), 'updatedAt', 1000);
 
       // act
-      const result = await yjsService.hasYdocsNewerThanLatestRevision(pageId.toString());
+      const result = await yjsService.getYDocStatus(pageId.toString());
 
       // assert
-      expect(result).toBe(true);
+      expect(result).toBe(YDocStatus.ISOLATED);
     });
 
-    it('returns false when the latest revision is newer than meta data', async() => {
+    it('returns NEW when no YDocs exist', async() => {
+      // arrange
+      const yjsService = getYjsService();
+
+      const pageId = new ObjectId();
+
+      await Revision.insertMany([
+        { pageId, body: '' },
+      ]);
+
+      // act
+      const result = await yjsService.getYDocStatus(pageId.toString());
+
+      // assert
+      expect(result).toBe(YDocStatus.NEW);
+    });
+
+    it('returns DRAFT when the newer YDocs exist', async() => {
       // arrange
       const yjsService = getYjsService();
 
@@ -85,33 +104,36 @@ describe('YjsService', () => {
       ]);
 
       const privateMdb = getPrivateMdbInstance(yjsService);
-      await privateMdb.setMeta(pageId.toString(), 'updatedAt', (new Date(2024, 1, 1)).getTime());
+      await privateMdb.setMeta(pageId.toString(), 'updatedAt', (new Date(2034, 1, 1)).getTime());
 
       // act
-      const result = await yjsService.hasYdocsNewerThanLatestRevision(pageId.toString());
+      const result = await yjsService.getYDocStatus(pageId.toString());
 
       // assert
-      expect(result).toBe(false);
+      expect(result).toBe(YDocStatus.DRAFT);
     });
 
-    it('returns false when no YDocs exist', async() => {
+    it('returns SYNCED', async() => {
       // arrange
       const yjsService = getYjsService();
 
       const pageId = new ObjectId();
 
       await Revision.insertMany([
-        { pageId, body: '' },
+        { pageId, body: '', createdAt: new Date(2025, 1, 1) },
       ]);
 
+      const privateMdb = getPrivateMdbInstance(yjsService);
+      await privateMdb.setMeta(pageId.toString(), 'updatedAt', (new Date(2025, 1, 1)).getTime());
+
       // act
-      const result = await yjsService.hasYdocsNewerThanLatestRevision(pageId.toString());
+      const result = await yjsService.getYDocStatus(pageId.toString());
 
       // assert
-      expect(result).toBe(false);
+      expect(result).toBe(YDocStatus.SYNCED);
     });
 
-    it('returns true when the newer YDocs exist', async() => {
+    it('returns OUTDATED when the latest revision is newer than meta data', async() => {
       // arrange
       const yjsService = getYjsService();
 
@@ -122,13 +144,13 @@ describe('YjsService', () => {
       ]);
 
       const privateMdb = getPrivateMdbInstance(yjsService);
-      await privateMdb.setMeta(pageId.toString(), 'updatedAt', (new Date(2034, 1, 1)).getTime());
+      await privateMdb.setMeta(pageId.toString(), 'updatedAt', (new Date(2024, 1, 1)).getTime());
 
       // act
-      const result = await yjsService.hasYdocsNewerThanLatestRevision(pageId.toString());
+      const result = await yjsService.getYDocStatus(pageId.toString());
 
       // assert
-      expect(result).toBe(true);
+      expect(result).toBe(YDocStatus.OUTDATED);
     });
 
   });

+ 28 - 8
apps/app/src/server/service/yjs.ts

@@ -210,7 +210,11 @@ class YjsService implements IYjsService {
     }
   }
 
-  public async hasYdocsNewerThanLatestRevision(pageId: string): Promise<boolean> {
+  public async getYDocStatus(pageId: string): Promise<YDocStatus> {
+    const dumpLog = (status: YDocStatus, args?: { [key: string]: number }) => {
+      logger.debug(`getYDocStatus('${pageId}') detected '${status}'`, args ?? {});
+    };
+
     // get the latest revision createdAt
     const result = await Revision
       .findOne(
@@ -221,18 +225,34 @@ class YjsService implements IYjsService {
         { sort: { createdAt: -1 } },
       );
 
-    const lastRevisionCreatedAt = (result == null)
-      ? 0
-      : result.createdAt.getTime();
+    if (result == null) {
+      dumpLog(YDocStatus.ISOLATED);
+      return YDocStatus.ISOLATED;
+    }
 
     // count yjs-writings documents with updatedAt > latestRevision.updatedAt
     const ydocUpdatedAt: number | undefined = await this.mdb.getMeta(pageId, 'updatedAt');
 
-    logger.debug('hasYdocsNewerThanLatestRevision', { pageId, lastRevisionCreatedAt, ydocUpdatedAt });
+    if (ydocUpdatedAt == null) {
+      dumpLog(YDocStatus.NEW);
+      return YDocStatus.NEW;
+    }
+
+    const { createdAt } = result;
+    const lastRevisionCreatedAt = createdAt.getTime();
+
+    if (lastRevisionCreatedAt < ydocUpdatedAt) {
+      dumpLog(YDocStatus.DRAFT, { lastRevisionCreatedAt, ydocUpdatedAt });
+      return YDocStatus.DRAFT;
+    }
+
+    if (lastRevisionCreatedAt === ydocUpdatedAt) {
+      dumpLog(YDocStatus.SYNCED, { lastRevisionCreatedAt, ydocUpdatedAt });
+      return YDocStatus.SYNCED;
+    }
 
-    return ydocUpdatedAt == null
-      ? false
-      : ydocUpdatedAt > lastRevisionCreatedAt;
+    dumpLog(YDocStatus.OUTDATED, { lastRevisionCreatedAt, ydocUpdatedAt });
+    return YDocStatus.OUTDATED;
   }
 
   // public async handleYDocSync(pageId: string, initialValue: string): Promise<void> {

+ 1 - 0
packages/core/src/consts/index.ts

@@ -1,2 +1,3 @@
 export * from './accepted-upload-file-type';
 export * from './growi-plugin';
+export * from './ydoc-status';

+ 0 - 0
packages/editor/src/consts/ydoc-status.ts → packages/core/src/consts/ydoc-status.ts


+ 0 - 1
packages/editor/src/consts/index.ts

@@ -1,6 +1,5 @@
 export * from './global-code-mirror-editor-key';
 export * from './ydoc-awareness-user-color';
-export * from './ydoc-status';
 export * from './editor-settings';
 export * from './editor-themes';
 export * from './keymaps';