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

Merge pull request #3278 from weseek/refactor-remove-attachment

imprv: Bulk to reduce attachments deletion action.
itizawa 5 лет назад
Родитель
Сommit
dd866b284f

+ 1 - 11
src/server/routes/attachment.js

@@ -244,16 +244,6 @@ module.exports = function(crowi, app) {
     }
   }
 
-  async function removeAttachment(attachmentId) {
-    const { fileUploadService } = crowi;
-
-    // retrieve data from DB to get a completely populated instance
-    const attachment = await Attachment.findById(attachmentId);
-
-    await fileUploadService.deleteFile(attachment);
-
-    return attachment.remove();
-  }
 
   const actions = {};
   const api = {};
@@ -637,7 +627,7 @@ module.exports = function(crowi, app) {
     }
 
     try {
-      await removeAttachment(attachment);
+      await attachmentService.removeAttachment(attachment);
     }
     catch (err) {
       logger.error(err);

+ 25 - 6
src/server/service/attachment.js

@@ -1,5 +1,5 @@
 const logger = require('@alias/logger')('growi:service:AttachmentService'); // eslint-disable-line no-unused-vars
-
+const mongoose = require('mongoose');
 const fs = require('fs');
 
 
@@ -43,13 +43,32 @@ class AttachmentService {
     return attachment;
   }
 
-  async removeAttachment(attachments) {
+  async removeAllAttachments(attachments) {
     const { fileUploadService } = this.crowi;
+    const attachmentsCollection = mongoose.connection.collection('attachments');
+    const unorderAttachmentsBulkOp = attachmentsCollection.initializeUnorderedBulkOp();
 
-    return attachments.forEach((attachment) => {
-      fileUploadService.deleteFile(attachment);
-      attachment.remove();
-    });
+    if (attachments.length > 0) {
+      fileUploadService.deleteFiles(attachments);
+
+      attachments.forEach((attachment) => {
+        unorderAttachmentsBulkOp.find({ _id: attachment._id }).remove();
+      });
+      await unorderAttachmentsBulkOp.execute();
+    }
+
+    return;
+  }
+
+  async removeAttachment(attachmentId) {
+    const Attachment = this.crowi.model('Attachment');
+    const { fileUploadService } = this.crowi;
+    const attachment = await Attachment.findById(attachmentId);
+
+    await fileUploadService.deleteFile(attachment);
+    await attachment.remove();
+
+    return;
   }
 
 }

+ 6 - 0
src/server/service/file-uploader/aws.js

@@ -115,6 +115,12 @@ module.exports = function(crowi) {
     return lib.deleteFileByFilePath(filePath);
   };
 
+  lib.deleteFiles = async function(attachments) {
+    attachments.map((attachment) => {
+      return this.deleteFile(attachment);
+    });
+  };
+
   lib.deleteFileByFilePath = async function(filePath) {
     if (!this.getIsUploadable()) {
       throw new Error('AWS is not configured.');

+ 6 - 0
src/server/service/file-uploader/gcs.js

@@ -92,6 +92,12 @@ module.exports = function(crowi) {
     return lib.deleteFileByFilePath(filePath);
   };
 
+  lib.deleteFiles = async function(attachments) {
+    attachments.map((attachment) => {
+      return this.deleteFile(attachment);
+    });
+  };
+
   lib.deleteFileByFilePath = async function(filePath) {
     if (!this.getIsUploadable()) {
       throw new Error('GCS is not configured.');

+ 6 - 0
src/server/service/file-uploader/gridfs.js

@@ -43,6 +43,12 @@ module.exports = function(crowi) {
     return AttachmentFile.promisifiedUnlink({ _id: attachmentFile._id });
   };
 
+  lib.deleteFiles = async function(attachments) {
+    attachments.map(async(attachment) => {
+      return lib.deleteFile(attachment);
+    });
+  };
+
   /**
    * get size of data uploaded files using (Promise wrapper)
    */

+ 6 - 0
src/server/service/file-uploader/local.js

@@ -35,6 +35,12 @@ module.exports = function(crowi) {
     return lib.deleteFileByFilePath(filePath);
   };
 
+  lib.deleteFiles = async function(attachments) {
+    attachments.map((attachment) => {
+      return this.deleteFile(attachment);
+    });
+  };
+
   lib.deleteFileByFilePath = async function(filePath) {
     // check file exists
     try {

+ 5 - 0
src/server/service/file-uploader/none.js

@@ -14,6 +14,11 @@ module.exports = function(crowi) {
     throw new Error('not implemented');
   };
 
+  lib.deleteFiles = function(filePath) {
+    debug(`File deletion: ${filePath}`);
+    throw new Error('not implemented');
+  };
+
   lib.uploadFile = function(filePath, contentType, fileStream, options) {
     debug(`File uploading: ${filePath}`);
     throw new Error('not implemented');

+ 4 - 0
src/server/service/file-uploader/uploader.js

@@ -29,6 +29,10 @@ class Uploader {
     return !!this.configManager.getConfig('crowi', 'app:fileUpload');
   }
 
+  deleteFiles() {
+    throw new Error('Implemnt this');
+  }
+
   /**
    * Check files size limits for all uploaders
    *

+ 5 - 9
src/server/service/page.js

@@ -23,6 +23,10 @@ class PageService {
     const PageTagRelation = this.crowi.model('PageTagRelation');
     const ShareLink = this.crowi.model('ShareLink');
     const Revision = this.crowi.model('Revision');
+    const Attachment = this.crowi.model('Attachment');
+
+    const { attachmentService } = this.crowi;
+    const attachments = await Attachment.find({ page: { $in: pageIds } });
 
     return Promise.all([
       Bookmark.find({ page: { $in: pageIds } }).remove({}),
@@ -32,18 +36,10 @@ class PageService {
       Revision.find({ path: { $in: pagePaths } }).remove({}),
       Page.find({ _id: { $in: pageIds } }).remove({}),
       Page.find({ path: { $in: pagePaths } }).remove({}),
-      this.removeAllAttachments(pageIds),
+      attachmentService.removeAllAttachments(attachments),
     ]);
   }
 
-  async removeAllAttachments(pageIds) {
-    const Attachment = this.crowi.model('Attachment');
-    const { attachmentService } = this.crowi;
-    const attachments = await Attachment.find({ page: { $in: pageIds } });
-
-    return attachmentService.removeAttachment(attachments);
-  }
-
   async duplicate(page, newPagePath, user, isRecursively) {
     const Page = this.crowi.model('Page');
     const PageTagRelation = mongoose.model('PageTagRelation');