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

Merge pull request #5205 from weseek/feat/migrate-redirect-to-to-page-redirect

feat: Migrate redirect to to page redirect
Haku Mizuki 4 лет назад
Родитель
Сommit
cd8de7da33

+ 85 - 0
packages/app/src/migrations/20220131001218-convert-redirect-to-pages-to-page-redirect-documents.js

@@ -0,0 +1,85 @@
+import mongoose from 'mongoose';
+import { getModelSafely, getMongoUri, mongoOptions } from '@growi/core';
+
+import PageRedirectModel from '~/server/models/page-redirect';
+import loggerFactory from '~/utils/logger';
+import { createBatchStream } from '~/server/util/batch-stream';
+
+const logger = loggerFactory('growi:migrate:convert-redirect-to-pages-to-page-redirect-documents');
+
+const BATCH_SIZE = 100;
+
+
+module.exports = {
+  async up(db, client) {
+    mongoose.connect(getMongoUri(), mongoOptions);
+    const pageCollection = await db.collection('pages');
+    const PageRedirect = getModelSafely('PageRedirect') || PageRedirectModel;
+
+    const cursor = pageCollection.find({ redirectTo: { $exists: true, $ne: null } }, { path: 1, redirectTo: 1, _id: 0 }).stream();
+    const batchStream = createBatchStream(BATCH_SIZE);
+
+    // redirectTo => PageRedirect
+    for await (const pages of cursor.pipe(batchStream)) {
+      const insertPageRedirectOperations = pages.map((page) => {
+        return {
+          insertOne: {
+            document: {
+              fromPath: page.path,
+              toPath: page.redirectTo,
+            },
+          },
+        };
+      });
+
+      try {
+        await PageRedirect.bulkWrite(insertPageRedirectOperations);
+      }
+      catch (err) {
+        if (err.code !== 11000) {
+          throw Error(`Failed to migrate: ${err}`);
+        }
+      }
+    }
+
+    await pageCollection.deleteMany({ redirectTo: { $ne: null } });
+
+    logger.info('Migration has successfully applied');
+  },
+
+  async down(db, client) {
+    mongoose.connect(getMongoUri(), mongoOptions);
+    const pageCollection = await db.collection('pages');
+    const PageRedirect = getModelSafely('PageRedirect') || PageRedirectModel;
+
+    const cursor = PageRedirect.find().lean().cursor();
+    const batchStream = createBatchStream(BATCH_SIZE);
+
+    // PageRedirect => redirectTo
+    for await (const pageRedirects of cursor.pipe(batchStream)) {
+      const insertPageOperations = pageRedirects.map((pageRedirect) => {
+        return {
+          insertOne: {
+            document: {
+              path: pageRedirect.fromPath,
+              redirectTo: pageRedirect.toPath,
+            },
+          },
+        };
+      });
+
+      try {
+        await pageCollection.bulkWrite(insertPageOperations);
+      }
+      catch (err) {
+        if (err.code !== 11000) {
+          throw Error(`Failed to migrate: ${err}`);
+        }
+      }
+    }
+
+    await PageRedirect.deleteMany();
+
+    logger.info('Migration down has successfully applied');
+  },
+};

+ 13 - 1
packages/app/src/server/models/page.ts

@@ -6,13 +6,14 @@ import mongoose, {
 import mongoosePaginate from 'mongoose-paginate-v2';
 import uniqueValidator from 'mongoose-unique-validator';
 import nodePath from 'path';
-
 import { getOrCreateModel, pagePathUtils } from '@growi/core';
+
 import loggerFactory from '../../utils/logger';
 import Crowi from '../crowi';
 import { IPage } from '../../interfaces/page';
 import { getPageSchema, PageQueryBuilder } from './obsolete-page';
 import { ObjectIdLike } from '~/server/interfaces/mongoose-utils';
+import { PageRedirectModel } from './page-redirect';
 
 const { isTopPage, collectAncestorPaths } = pagePathUtils;
 
@@ -601,6 +602,17 @@ export default (crowi: Crowi): any => {
     /*
      * After save
      */
+    // Delete PageRedirect if exists
+    const PageRedirect = mongoose.model('PageRedirect') as unknown as PageRedirectModel;
+    try {
+      await PageRedirect.deleteOne({ from: path });
+      logger.warn(`Deleted page redirect after creating a new page at path "${path}".`);
+    }
+    catch (err) {
+      // no throw
+      logger.error('Failed to delete PageRedirect');
+    }
+
     const newRevision = Revision.prepareRevision(savedPage, body, null, user, { format });
     savedPage = await pushRevision(savedPage, newRevision, user);
     await savedPage.populateDataToShowRevision();