From 53003d4471e130199987bc4214d83a0727c9bc21 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 19 Dec 2019 17:14:00 +0100 Subject: [PATCH] pad.js: fix freeze on pad deletion when it has many revisions --- src/node/db/Pad.js | 13 +++++++------ src/node/utils/promises.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 src/node/utils/promises.js diff --git a/src/node/db/Pad.js b/src/node/db/Pad.js index cf016444..10f50ec2 100644 --- a/src/node/db/Pad.js +++ b/src/node/db/Pad.js @@ -16,6 +16,7 @@ var readOnlyManager = require("./ReadOnlyManager"); var crypto = require("crypto"); var randomString = require("../utils/randomstring"); var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); +var promises = require('../utils/promises') // serialization/deserialization attributes var attributeBlackList = ["id"]; @@ -482,14 +483,14 @@ Pad.prototype.remove = async function remove() { db.remove("readonly2pad:" + readonlyID); // delete all chat messages - for (let i = 0, n = this.chatHead; i <= n; ++i) { - db.remove("pad:" + padID + ":chat:" + i); - } + promises.timesLimit(this.chatHead + 1, 500, function (i) { + return db.remove("pad:" + padID + ":chat:" + i); + }) // delete all revisions - for (let i = 0, n = this.head; i <= n; ++i) { - db.remove("pad:" + padID + ":revs:" + i); - } + promises.timesLimit(this.head + 1, 500, function (i) { + return db.remove("pad:" + padID + ":revs:" + i); + }) // remove pad from all authors who contributed this.getAllAuthors().forEach(authorID => { diff --git a/src/node/utils/promises.js b/src/node/utils/promises.js new file mode 100644 index 00000000..4fb2e831 --- /dev/null +++ b/src/node/utils/promises.js @@ -0,0 +1,32 @@ +/** + * Helpers to manipulate promises (like async but for promises). + */ + +var timesLimit = function (ltMax, concurrency, promiseCreator) { + var done = 0 + var current = 0 + + function addAnother () { + function _internalRun () { + done++ + + if (done < ltMax) { + addAnother() + } + } + + promiseCreator(current) + .then(_internalRun) + .catch(_internalRun) + + current++ + } + + for (var i = 0; i < concurrency && i < ltMax; i++) { + addAnother() + } +} + +module.exports = { + timesLimit: timesLimit +}