Taichi Masuyama 4 лет назад
Родитель
Сommit
9cc4c21be5
1 измененных файлов с 22 добавлено и 18 удалено
  1. 22 18
      packages/app/src/server/service/page.ts

+ 22 - 18
packages/app/src/server/service/page.ts

@@ -1,5 +1,5 @@
 import { pagePathUtils } from '@growi/core';
-import mongoose from 'mongoose';
+import mongoose, { QueryCursor } from 'mongoose';
 import escapeStringRegexp from 'escape-string-regexp';
 import streamToPromise from 'stream-to-promise';
 import pathlib from 'path';
@@ -33,40 +33,47 @@ class PageOnlyDescendantsIterableFactory {
 
   private shouldIncludeEmpty: boolean;
 
-  private initialCursor: Readable;
+  private initialCursor: QueryCursor<any>; // TODO: wait for mongoose update
 
   private Page: PageModel;
 
-  private isReady: boolean;
-
   constructor(user: any, rootPage: any, shouldIncludeEmpty: boolean) {
     this.user = user;
     this.rootPage = rootPage;
     this.shouldIncludeEmpty = shouldIncludeEmpty;
 
-    this.isReady = false;
-
     this.Page = mongoose.model('Page') as unknown as PageModel;
   }
 
-  async init() {
+  // prepare initial cursor
+  private async init() {
     const initialCursor = await this.generateCursorToFindChildren(this.rootPage);
     this.initialCursor = initialCursor;
-    this.isReady = true;
   }
 
+  /**
+   * Returns Iterable that yields only descendant pages unorderedly
+   * @returns Promise<AsyncGenerator>
+   */
   async generateIterable(): Promise<AsyncGenerator> {
-    if (!this.isReady) {
-      throw Error('Run init first');
-    }
+    // initialize cursor
+    await this.init();
 
     return this.generateOnlyDescendants(this.initialCursor);
   }
 
+  /**
+   * Returns Readable that produces only descendant pages unorderedly
+   * @returns Promise<Readable>
+   */
+  async generateReadable(): Promise<Readable> {
+    return Readable.from(await this.generateIterable());
+  }
+
   /**
    * Generator that unorderedly yields descendant pages
    */
-  private async* generateOnlyDescendants(cursor: any) {
+  private async* generateOnlyDescendants(cursor: QueryCursor<any>) {
     for await (const page of cursor) {
       const nextCursor = await this.generateCursorToFindChildren(page);
       yield* this.generateOnlyDescendants(nextCursor); // recursively yield
@@ -75,14 +82,14 @@ class PageOnlyDescendantsIterableFactory {
     }
   }
 
-  private async generateCursorToFindChildren(page: any): Promise<any> {
+  private async generateCursorToFindChildren(page: any): Promise<QueryCursor<any>> {
     const { PageQueryBuilder } = this.Page;
 
     const builder = new PageQueryBuilder(this.Page.find(), this.shouldIncludeEmpty);
     builder.addConditionToFilteringByParentId(page._id);
     await this.Page.addConditionToFilteringByViewerToEdit(builder, this.user);
 
-    const cursor = builder.query.lean().cursor({ batchSize: BULK_REINDEX_SIZE });
+    const cursor = builder.query.lean().cursor({ batchSize: BULK_REINDEX_SIZE }) as QueryCursor<any>;
 
     return cursor;
   }
@@ -470,11 +477,8 @@ class PageService {
       return this.renameDescendantsWithStreamV4(targetPage, newPagePath, user, options);
     }
 
-    // const readStream = await this.generateReadStreamToOperateOnlyDescendants(targetPage.path, user);
     const iterableFactory = new PageOnlyDescendantsIterableFactory(user, targetPage, true);
-    await iterableFactory.init();
-    const iterable = await iterableFactory.generateIterable();
-    const readStream = Readable.from(iterable);
+    const readStream = await iterableFactory.generateReadable();
 
     const newPagePathPrefix = newPagePath;
     const pathRegExp = new RegExp(`^${escapeStringRegexp(targetPage.path)}`, 'i');