|
@@ -1,5 +1,5 @@
|
|
|
import { pagePathUtils } from '@growi/core';
|
|
import { pagePathUtils } from '@growi/core';
|
|
|
-import Page from '~/components/Page';
|
|
|
|
|
|
|
+import { callbackify } from 'util';
|
|
|
import loggerFactory from '~/utils/logger';
|
|
import loggerFactory from '~/utils/logger';
|
|
|
|
|
|
|
|
const mongoose = require('mongoose');
|
|
const mongoose = require('mongoose');
|
|
@@ -776,6 +776,28 @@ class PageService {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ async v5MigrationByPageIds(pageIds) {
|
|
|
|
|
+ const Page = this.crowi.model('Page');
|
|
|
|
|
+
|
|
|
|
|
+ if (pageIds == null || pageIds.length === 0) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // generate regexps
|
|
|
|
|
+ const regexps = await this._generateRegExpsByPageIds(pageIds);
|
|
|
|
|
+
|
|
|
|
|
+ // migrate recursively
|
|
|
|
|
+ try {
|
|
|
|
|
+ await this._v5RecursiveMigration(Page.GRANT_PUBLIC, regexps);
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (err) {
|
|
|
|
|
+ logger.error('V5 initial miration failed.', err);
|
|
|
|
|
+ // socket.emit('v5InitialMirationFailed', { error: err.message }); TODO: use socket to tell user
|
|
|
|
|
+
|
|
|
|
|
+ throw err;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
async v5InitialMigration(grant) {
|
|
async v5InitialMigration(grant) {
|
|
|
const socket = this.crowi.socketIoService.getAdminSocket();
|
|
const socket = this.crowi.socketIoService.getAdminSocket();
|
|
|
try {
|
|
try {
|
|
@@ -809,6 +831,27 @@ class PageService {
|
|
|
await this._setIsV5CompatibleTrue();
|
|
await this._setIsV5CompatibleTrue();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
|
+ * returns an array of js RegExp instance instead of RE2 instance for mongo filter
|
|
|
|
|
+ */
|
|
|
|
|
+ async _generateRegExpsByPageIds(pageIds) {
|
|
|
|
|
+ const Page = mongoose.model('Page');
|
|
|
|
|
+
|
|
|
|
|
+ let result;
|
|
|
|
|
+ try {
|
|
|
|
|
+ result = await Page.findListByPageIds(pageIds, null, false);
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (err) {
|
|
|
|
|
+ logger.error('Failed to find pages by ids');
|
|
|
|
|
+ throw err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const { pages } = result;
|
|
|
|
|
+ const regexps = pages.map(page => new RegExp(`^${page.path}`));
|
|
|
|
|
+
|
|
|
|
|
+ return regexps;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
async _setIsV5CompatibleTrue() {
|
|
async _setIsV5CompatibleTrue() {
|
|
|
try {
|
|
try {
|
|
|
await this.crowi.configManager.updateConfigsInTheSameNamespace('crowi', {
|
|
await this.crowi.configManager.updateConfigsInTheSameNamespace('crowi', {
|
|
@@ -823,21 +866,33 @@ class PageService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// TODO: use websocket to show progress
|
|
// TODO: use websocket to show progress
|
|
|
- async _v5RecursiveMigration(grant, rootPath) {
|
|
|
|
|
|
|
+ async _v5RecursiveMigration(grant, regexps) {
|
|
|
const BATCH_SIZE = 100;
|
|
const BATCH_SIZE = 100;
|
|
|
const PAGES_LIMIT = 1000;
|
|
const PAGES_LIMIT = 1000;
|
|
|
const Page = this.crowi.model('Page');
|
|
const Page = this.crowi.model('Page');
|
|
|
const { PageQueryBuilder } = Page;
|
|
const { PageQueryBuilder } = Page;
|
|
|
|
|
|
|
|
- const total = await Page.countDocuments({ grant, parent: null });
|
|
|
|
|
|
|
+ // generate filter
|
|
|
|
|
+ let filter = {
|
|
|
|
|
+ grant,
|
|
|
|
|
+ parent: null,
|
|
|
|
|
+ path: { $ne: '/' },
|
|
|
|
|
+ };
|
|
|
|
|
+ if (regexps != null && regexps.length !== 0) {
|
|
|
|
|
+ filter = {
|
|
|
|
|
+ ...filter,
|
|
|
|
|
+ path: {
|
|
|
|
|
+ $in: regexps,
|
|
|
|
|
+ },
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const total = await Page.countDocuments(filter);
|
|
|
|
|
|
|
|
let baseAggregation = Page
|
|
let baseAggregation = Page
|
|
|
.aggregate([
|
|
.aggregate([
|
|
|
{
|
|
{
|
|
|
- $match: {
|
|
|
|
|
- grant,
|
|
|
|
|
- parent: null,
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ $match: filter,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
$project: { // minimize data to fetch
|
|
$project: { // minimize data to fetch
|
|
@@ -921,8 +976,8 @@ class PageService {
|
|
|
|
|
|
|
|
await streamToPromise(migratePagesStream);
|
|
await streamToPromise(migratePagesStream);
|
|
|
|
|
|
|
|
- if (await Page.exists({ grant, parent: null, path: { $ne: '/' } })) {
|
|
|
|
|
- return this._v5RecursiveMigration(grant, rootPath);
|
|
|
|
|
|
|
+ if (await Page.exists(filter)) {
|
|
|
|
|
+ return this._v5RecursiveMigration(grant, regexps);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|