Shun Miyazawa %!s(int64=2) %!d(string=hai) anos
pai
achega
90d8f75f2f

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

@@ -725,6 +725,7 @@ Crowi.prototype.setupPageService = async function() {
   // initialize after pageGrantService since pageService uses pageGrantService in constructor
   if (this.pageService == null) {
     this.pageService = new PageService(this);
+    await this.pageService.createTtlIndex();
   }
   if (this.pageOperationService == null) {
     this.pageOperationService = new PageOperationService(this);

+ 1 - 1
apps/app/src/server/models/page.ts

@@ -140,7 +140,7 @@ const schema = new Schema<PageDocument, PageModel>({
   commentCount: { type: Number, default: 0 },
   expandContentWidth: { type: Boolean },
   wip: { type: Boolean },
-  wipExpiredAt: { type: Date },
+  wipExpiredAt: { type: Date, index: true },
   updatedAt: { type: Date, default: Date.now }, // Do not use timetamps for updatedAt because it breaks 'updateMetadata: false' option
   deleteUser: { type: ObjectId, ref: 'User' },
   deletedAt: { type: Date },

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

@@ -4408,6 +4408,34 @@ class PageService implements IPageService {
     });
   }
 
+  async createTtlIndex(): Promise<void> {
+    const pageExpirationSeconds = 60; // TODO: Allow to retrieve from environment variables
+    const collection = mongoose.connection.collection('pages');
+
+    try {
+      const targetField = 'wipExpiredAt_1';
+
+      const indexes = await collection.indexes();
+      const foundTargetField = indexes.find(i => i.name === targetField);
+
+      const isNotSpec = foundTargetField?.expireAfterSeconds == null || foundTargetField?.expireAfterSeconds !== pageExpirationSeconds;
+      const shoudDropIndex = foundTargetField != null && isNotSpec;
+      const shoudCreateIndex = foundTargetField == null || shoudDropIndex;
+
+      if (shoudDropIndex) {
+        await collection.dropIndex(targetField);
+      }
+
+      if (shoudCreateIndex) {
+        await collection.createIndex({ wipExpiredAt: 1 }, { expireAfterSeconds: pageExpirationSeconds });
+      }
+    }
+    catch (err) {
+      logger.error('Failed to create TTL Index', err);
+      throw err;
+    }
+  }
+
 }
 
 export default PageService;