瀏覽代碼

replace PageService.hasRevisionBodyDiff with YjsService.hasYdocsNewerThanLatestRevision

Yuki Takei 1 年之前
父節點
當前提交
53d8f52327

+ 1 - 1
apps/app/src/server/crowi/index.js

@@ -476,7 +476,7 @@ Crowi.prototype.start = async function() {
   this.socketIoService.attachServer(httpServer);
 
   // Initialization YjsService
-  initializeYjsService(this.socketIoService.io, this.pageService);
+  initializeYjsService(this.socketIoService.io);
 
   await this.autoInstall();
 

+ 1 - 19
apps/app/src/server/service/page/index.ts

@@ -4447,10 +4447,7 @@ class PageService implements IPageService {
     const yjsService = getYjsService();
 
     const currentYdoc = yjsService.getCurrentYdoc(pageId);
-    const persistedYdoc = await yjsService.getPersistedYdoc(pageId);
-
-    const yjsDraft = (currentYdoc ?? persistedYdoc)?.getText('codemirror').toString();
-    const hasRevisionBodyDiff = await this.hasRevisionBodyDiff(pageId, yjsDraft);
+    const hasRevisionBodyDiff = await yjsService.hasYdocsNewerThanLatestRevision(pageId);
 
     return {
       hasRevisionBodyDiff,
@@ -4458,21 +4455,6 @@ class PageService implements IPageService {
     };
   }
 
-  async hasRevisionBodyDiff(pageId: string, comparisonTarget?: string): Promise<boolean> {
-    if (comparisonTarget == null) {
-      return false;
-    }
-
-    const Revision = mongoose.model<IRevisionHasId>('Revision');
-    const revision = await Revision.findOne({ pageId }).sort({ createdAt: -1 });
-
-    if (revision == null) {
-      return false;
-    }
-
-    return revision.body !== comparisonTarget;
-  }
-
   async createTtlIndex(): Promise<void> {
     const wipPageExpirationSeconds = configManager.getConfig('crowi', 'app:wipPageExpirationSeconds') ?? 172800;
     const collection = mongoose.connection.collection('pages');

+ 0 - 1
apps/app/src/server/service/page/page-service.ts

@@ -32,5 +32,4 @@ export interface IPageService {
     page: PageDocument, creatorId: ObjectIdLike | null, operator: any | null, userRelatedGroups: PopulatedGrantedGroup[]
   ): boolean,
   getYjsData(pageId: string, revisionBody?: string): Promise<CurrentPageYjsData>,
-  hasRevisionBodyDiff(pageId: string, comparisonTarget?: string): Promise<boolean>,
 }

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

@@ -1,3 +1,4 @@
+import type { IRevisionHasId } from '@growi/core';
 import { GlobalSocketEventName } from '@growi/core';
 import mongoose from 'mongoose';
 import type { Server } from 'socket.io';
@@ -12,8 +13,6 @@ import loggerFactory from '~/utils/logger';
 import { getMongoUri } from '../util/mongoose-utils';
 import { RoomPrefix, getRoomNameWithId } from '../util/socket-io-helpers';
 
-import type { IPageService } from './page';
-
 
 const MONGODB_PERSISTENCE_COLLECTION_NAME = 'yjs-writings';
 const MONGODB_PERSISTENCE_FLUSH_SIZE = 100;
@@ -33,7 +32,7 @@ class YjsService {
 
   private mdb: MongodbPersistence;
 
-  constructor(io: Server, pageService: IPageService) {
+  constructor(io: Server) {
     const ysocketio = new YSocketIO(io);
     ysocketio.initialize();
     this.ysocketio = ysocketio;
@@ -61,9 +60,7 @@ class YjsService {
 
         // Triggered when the last user leaves the editor
         if (awarenessStateSize === 0) {
-          const currentYdoc = this.getCurrentYdoc(pageId);
-          const yjsDraft = currentYdoc?.getText('codemirror').toString();
-          const hasRevisionBodyDiff = await pageService.hasRevisionBodyDiff(pageId, yjsDraft);
+          const hasRevisionBodyDiff = await this.hasYdocsNewerThanLatestRevision(pageId);
           io
             .in(getRoomNameWithId(RoomPrefix.PAGE, pageId))
             .emit(SocketEventName.YjsHasRevisionBodyDiffUpdated, hasRevisionBodyDiff);
@@ -120,6 +117,28 @@ class YjsService {
     }
   }
 
+  public async hasYdocsNewerThanLatestRevision(pageId: string): Promise<boolean> {
+    // get the latest revision createdAt
+    const Revision = mongoose.model<IRevisionHasId>('Revision');
+    const result = await Revision
+      .findOne(
+        { pageId },
+        { createdAt: 1 },
+        { sort: { createdAt: -1 } },
+      );
+
+    const lastRevisionCreatedAt = (result == null)
+      ? 0
+      : result.createdAt.getTime();
+
+    // count yjs-writings documents with updatedAt > latestRevision.updatedAt
+    const ydocUpdatedAt: number | undefined = await this.mdb.getMeta(pageId, 'updatedAt');
+
+    return ydocUpdatedAt == null
+      ? false
+      : ydocUpdatedAt > lastRevisionCreatedAt;
+  }
+
   public async handleYDocSync(pageId: string, initialValue: string): Promise<void> {
     const currentYdoc = this.getCurrentYdoc(pageId);
     if (currentYdoc == null) {
@@ -186,7 +205,7 @@ class YjsService {
 
 let _instance: YjsService;
 
-export const initializeYjsService = (io: Server, pageService: IPageService): void => {
+export const initializeYjsService = (io: Server): void => {
   if (_instance != null) {
     throw new Error('YjsService is already initialized');
   }
@@ -195,7 +214,7 @@ export const initializeYjsService = (io: Server, pageService: IPageService): voi
     throw new Error("'io' is required if initialize YjsService");
   }
 
-  _instance = new YjsService(io, pageService);
+  _instance = new YjsService(io);
 };
 
 export const getYjsService = (): YjsService => {