mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-22 08:26:16 -04:00
async-ify more functions, and await completion
Where feasible I put the await at the end of the function to minimize the impact on latency. My motivation for this change: Eliminate a race condition in tests I am writing.
This commit is contained in:
parent
45ec8326f0
commit
3365e944bf
8 changed files with 78 additions and 70 deletions
|
@ -110,8 +110,7 @@ async.series([
|
||||||
// Save the source pad
|
// Save the source pad
|
||||||
db.db.set("pad:"+newPadId, newPad, function(err) {
|
db.db.set("pad:"+newPadId, newPad, function(err) {
|
||||||
console.log("Created: Source Pad: pad:" + newPadId);
|
console.log("Created: Source Pad: pad:" + newPadId);
|
||||||
newPad.saveToDatabase();
|
newPad.saveToDatabase().then(() => callback(), callback);
|
||||||
callback();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
], function (err) {
|
], function (err) {
|
||||||
|
|
|
@ -203,11 +203,10 @@ exports.setText = async function(padID, text)
|
||||||
// get the pad
|
// get the pad
|
||||||
let pad = await getPadSafe(padID, true);
|
let pad = await getPadSafe(padID, true);
|
||||||
|
|
||||||
// set the text
|
await Promise.all([
|
||||||
pad.setText(text);
|
pad.setText(text),
|
||||||
|
padMessageHandler.updatePadClients(pad),
|
||||||
// update the clients on the pad
|
]);
|
||||||
padMessageHandler.updatePadClients(pad);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -226,12 +225,11 @@ exports.appendText = async function(padID, text)
|
||||||
throw new customError("text is not a string", "apierror");
|
throw new customError("text is not a string", "apierror");
|
||||||
}
|
}
|
||||||
|
|
||||||
// get and update the pad
|
|
||||||
let pad = await getPadSafe(padID, true);
|
let pad = await getPadSafe(padID, true);
|
||||||
pad.appendText(text);
|
await Promise.all([
|
||||||
|
pad.appendText(text),
|
||||||
// update the clients on the pad
|
padMessageHandler.updatePadClients(pad),
|
||||||
padMessageHandler.updatePadClients(pad);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -287,7 +285,7 @@ exports.setHTML = async function(padID, html)
|
||||||
|
|
||||||
// add a new changeset with the new html to the pad
|
// add a new changeset with the new html to the pad
|
||||||
try {
|
try {
|
||||||
importHtml.setPadHTML(pad, cleanText(html));
|
await importHtml.setPadHTML(pad, cleanText(html));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new customError("HTML is malformed", "apierror");
|
throw new customError("HTML is malformed", "apierror");
|
||||||
}
|
}
|
||||||
|
@ -373,7 +371,7 @@ exports.appendChatMessage = async function(padID, text, authorID, time)
|
||||||
// @TODO - missing getPadSafe() call ?
|
// @TODO - missing getPadSafe() call ?
|
||||||
|
|
||||||
// save chat message to database and send message to all connected clients
|
// save chat message to database and send message to all connected clients
|
||||||
padMessageHandler.sendChatMessageToPadClients(time, authorID, text, padID);
|
await padMessageHandler.sendChatMessageToPadClients(time, authorID, text, padID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************/
|
/*****************/
|
||||||
|
@ -454,7 +452,7 @@ exports.saveRevision = async function(padID, rev)
|
||||||
}
|
}
|
||||||
|
|
||||||
let author = await authorManager.createAuthor('API');
|
let author = await authorManager.createAuthor('API');
|
||||||
pad.addSavedRevision(rev, author.authorID, 'Saved through API call');
|
await pad.addSavedRevision(rev, author.authorID, 'Saved through API call');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -575,11 +573,10 @@ exports.restoreRevision = async function(padID, rev)
|
||||||
|
|
||||||
var changeset = builder.toString();
|
var changeset = builder.toString();
|
||||||
|
|
||||||
// append the changeset
|
await Promise.all([
|
||||||
pad.appendRevision(changeset);
|
pad.appendRevision(changeset),
|
||||||
|
padMessageHandler.updatePadClients(pad),
|
||||||
// update the clients on the pad
|
]);
|
||||||
padMessageHandler.updatePadClients(pad);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -688,7 +685,7 @@ exports.setPublicStatus = async function(padID, publicStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the password
|
// set the password
|
||||||
pad.setPublicStatus(publicStatus);
|
await pad.setPublicStatus(publicStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -726,7 +723,7 @@ exports.setPassword = async function(padID, password)
|
||||||
let pad = await getPadSafe(padID, true);
|
let pad = await getPadSafe(padID, true);
|
||||||
|
|
||||||
// set the password
|
// set the password
|
||||||
pad.setPassword(password == "" ? null : password);
|
await pad.setPassword(password === '' ? null : password);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -245,6 +245,6 @@ exports.removePad = async function(authorID, padID)
|
||||||
if (author.padIDs !== null) {
|
if (author.padIDs !== null) {
|
||||||
// remove pad from author
|
// remove pad from author
|
||||||
delete author.padIDs[padID];
|
delete author.padIDs[padID];
|
||||||
db.set("globalAuthor:" + authorID, author);
|
await db.set('globalAuthor:' + authorID, author);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ Pad.prototype.getPublicStatus = function getPublicStatus() {
|
||||||
return this.publicStatus;
|
return this.publicStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
Pad.prototype.appendRevision = function appendRevision(aChangeset, author) {
|
Pad.prototype.appendRevision = async function appendRevision(aChangeset, author) {
|
||||||
if (!author) {
|
if (!author) {
|
||||||
author = '';
|
author = '';
|
||||||
}
|
}
|
||||||
|
@ -97,12 +97,14 @@ Pad.prototype.appendRevision = function appendRevision(aChangeset, author) {
|
||||||
newRevData.meta.atext = this.atext;
|
newRevData.meta.atext = this.atext;
|
||||||
}
|
}
|
||||||
|
|
||||||
db.set("pad:" + this.id + ":revs:" + newRev, newRevData);
|
const p = [
|
||||||
this.saveToDatabase();
|
db.set('pad:' + this.id + ':revs:' + newRev, newRevData),
|
||||||
|
this.saveToDatabase(),
|
||||||
|
];
|
||||||
|
|
||||||
// set the author to pad
|
// set the author to pad
|
||||||
if (author) {
|
if (author) {
|
||||||
authorManager.addPad(author, this.id);
|
p.push(authorManager.addPad(author, this.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.head == 0) {
|
if (this.head == 0) {
|
||||||
|
@ -110,10 +112,12 @@ Pad.prototype.appendRevision = function appendRevision(aChangeset, author) {
|
||||||
} else {
|
} else {
|
||||||
hooks.callAll("padUpdate", {'pad':this, 'author': author});
|
hooks.callAll("padUpdate", {'pad':this, 'author': author});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await Promise.all(p);
|
||||||
};
|
};
|
||||||
|
|
||||||
// save all attributes to the database
|
// save all attributes to the database
|
||||||
Pad.prototype.saveToDatabase = function saveToDatabase() {
|
Pad.prototype.saveToDatabase = async function saveToDatabase() {
|
||||||
var dbObject = {};
|
var dbObject = {};
|
||||||
|
|
||||||
for (var attr in this) {
|
for (var attr in this) {
|
||||||
|
@ -127,7 +131,7 @@ Pad.prototype.saveToDatabase = function saveToDatabase() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.set("pad:" + this.id, dbObject);
|
await db.set('pad:' + this.id, dbObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get time of last edit (changeset application)
|
// get time of last edit (changeset application)
|
||||||
|
@ -244,7 +248,7 @@ Pad.prototype.text = function text() {
|
||||||
return this.atext.text;
|
return this.atext.text;
|
||||||
};
|
};
|
||||||
|
|
||||||
Pad.prototype.setText = function setText(newText) {
|
Pad.prototype.setText = async function setText(newText) {
|
||||||
// clean the new text
|
// clean the new text
|
||||||
newText = exports.cleanText(newText);
|
newText = exports.cleanText(newText);
|
||||||
|
|
||||||
|
@ -261,10 +265,10 @@ Pad.prototype.setText = function setText(newText) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// append the changeset
|
// append the changeset
|
||||||
this.appendRevision(changeset);
|
await this.appendRevision(changeset);
|
||||||
};
|
};
|
||||||
|
|
||||||
Pad.prototype.appendText = function appendText(newText) {
|
Pad.prototype.appendText = async function appendText(newText) {
|
||||||
// clean the new text
|
// clean the new text
|
||||||
newText = exports.cleanText(newText);
|
newText = exports.cleanText(newText);
|
||||||
|
|
||||||
|
@ -274,14 +278,16 @@ Pad.prototype.appendText = function appendText(newText) {
|
||||||
var changeset = Changeset.makeSplice(oldText, oldText.length, 0, newText);
|
var changeset = Changeset.makeSplice(oldText, oldText.length, 0, newText);
|
||||||
|
|
||||||
// append the changeset
|
// append the changeset
|
||||||
this.appendRevision(changeset);
|
await this.appendRevision(changeset);
|
||||||
};
|
};
|
||||||
|
|
||||||
Pad.prototype.appendChatMessage = function appendChatMessage(text, userId, time) {
|
Pad.prototype.appendChatMessage = async function appendChatMessage(text, userId, time) {
|
||||||
this.chatHead++;
|
this.chatHead++;
|
||||||
// save the chat entry in the database
|
// save the chat entry in the database
|
||||||
db.set("pad:" + this.id + ":chat:" + this.chatHead, { "text": text, "userId": userId, "time": time });
|
await Promise.all([
|
||||||
this.saveToDatabase();
|
db.set('pad:' + this.id + ':chat:' + this.chatHead, {text, userId, time}),
|
||||||
|
this.saveToDatabase(),
|
||||||
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Pad.prototype.getChatMessage = async function getChatMessage(entryNum) {
|
Pad.prototype.getChatMessage = async function getChatMessage(entryNum) {
|
||||||
|
@ -350,7 +356,7 @@ Pad.prototype.init = async function init(text) {
|
||||||
// this pad doesn't exist, so create it
|
// this pad doesn't exist, so create it
|
||||||
let firstChangeset = Changeset.makeSplice("\n", 0, 0, exports.cleanText(text));
|
let firstChangeset = Changeset.makeSplice("\n", 0, 0, exports.cleanText(text));
|
||||||
|
|
||||||
this.appendRevision(firstChangeset, '');
|
await this.appendRevision(firstChangeset, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks.callAll("padLoad", { 'pad': this });
|
hooks.callAll("padLoad", { 'pad': this });
|
||||||
|
@ -366,7 +372,7 @@ Pad.prototype.copy = async function copy(destinationID, force) {
|
||||||
// padMessageHandler.kickSessionsFromPad(sourceID);
|
// padMessageHandler.kickSessionsFromPad(sourceID);
|
||||||
|
|
||||||
// flush the source pad:
|
// flush the source pad:
|
||||||
this.saveToDatabase();
|
await this.saveToDatabase();
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -532,6 +538,7 @@ Pad.prototype.copyPadWithoutHistory = async function copyPadWithoutHistory(desti
|
||||||
|
|
||||||
Pad.prototype.remove = async function remove() {
|
Pad.prototype.remove = async function remove() {
|
||||||
var padID = this.id;
|
var padID = this.id;
|
||||||
|
const p = [];
|
||||||
|
|
||||||
// kick everyone from this pad
|
// kick everyone from this pad
|
||||||
padMessageHandler.kickSessionsFromPad(padID);
|
padMessageHandler.kickSessionsFromPad(padID);
|
||||||
|
@ -552,44 +559,45 @@ Pad.prototype.remove = async function remove() {
|
||||||
delete group.pads[padID];
|
delete group.pads[padID];
|
||||||
|
|
||||||
// set the new value
|
// set the new value
|
||||||
db.set("group:" + groupID, group);
|
p.push(db.set('group:' + groupID, group));
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the readonly entries
|
// remove the readonly entries
|
||||||
let readonlyID = readOnlyManager.getReadOnlyId(padID);
|
p.push(readOnlyManager.getReadOnlyId(padID).then(async (readonlyID) => {
|
||||||
|
await db.remove('readonly2pad:' + readonlyID);
|
||||||
db.remove("pad2readonly:" + padID);
|
}));
|
||||||
db.remove("readonly2pad:" + readonlyID);
|
p.push(db.remove('pad2readonly:' + padID));
|
||||||
|
|
||||||
// delete all chat messages
|
// delete all chat messages
|
||||||
promises.timesLimit(this.chatHead + 1, 500, function (i) {
|
p.push(promises.timesLimit(this.chatHead + 1, 500, async (i) => {
|
||||||
return db.remove("pad:" + padID + ":chat:" + i, null);
|
await db.remove('pad:' + padID + ':chat:' + i, null);
|
||||||
})
|
}));
|
||||||
|
|
||||||
// delete all revisions
|
// delete all revisions
|
||||||
promises.timesLimit(this.head + 1, 500, function (i) {
|
p.push(promises.timesLimit(this.head + 1, 500, async (i) => {
|
||||||
return db.remove("pad:" + padID + ":revs:" + i, null);
|
await db.remove('pad:' + padID + ':revs:' + i, null);
|
||||||
})
|
}));
|
||||||
|
|
||||||
// remove pad from all authors who contributed
|
// remove pad from all authors who contributed
|
||||||
this.getAllAuthors().forEach(authorID => {
|
this.getAllAuthors().forEach(authorID => {
|
||||||
authorManager.removePad(authorID, padID);
|
p.push(authorManager.removePad(authorID, padID));
|
||||||
});
|
});
|
||||||
|
|
||||||
// delete the pad entry and delete pad from padManager
|
// delete the pad entry and delete pad from padManager
|
||||||
padManager.removePad(padID);
|
p.push(padManager.removePad(padID));
|
||||||
hooks.callAll("padRemove", { padID });
|
hooks.callAll("padRemove", { padID });
|
||||||
|
await Promise.all(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set in db
|
// set in db
|
||||||
Pad.prototype.setPublicStatus = function setPublicStatus(publicStatus) {
|
Pad.prototype.setPublicStatus = async function setPublicStatus(publicStatus) {
|
||||||
this.publicStatus = publicStatus;
|
this.publicStatus = publicStatus;
|
||||||
this.saveToDatabase();
|
await this.saveToDatabase();
|
||||||
};
|
};
|
||||||
|
|
||||||
Pad.prototype.setPassword = function setPassword(password) {
|
Pad.prototype.setPassword = async function setPassword(password) {
|
||||||
this.passwordHash = password == null ? null : hash(password, generateSalt());
|
this.passwordHash = password == null ? null : hash(password, generateSalt());
|
||||||
this.saveToDatabase();
|
await this.saveToDatabase();
|
||||||
};
|
};
|
||||||
|
|
||||||
Pad.prototype.isCorrectPassword = function isCorrectPassword(password) {
|
Pad.prototype.isCorrectPassword = function isCorrectPassword(password) {
|
||||||
|
@ -600,7 +608,7 @@ Pad.prototype.isPasswordProtected = function isPasswordProtected() {
|
||||||
return this.passwordHash != null;
|
return this.passwordHash != null;
|
||||||
};
|
};
|
||||||
|
|
||||||
Pad.prototype.addSavedRevision = function addSavedRevision(revNum, savedById, label) {
|
Pad.prototype.addSavedRevision = async function addSavedRevision(revNum, savedById, label) {
|
||||||
// if this revision is already saved, return silently
|
// if this revision is already saved, return silently
|
||||||
for (var i in this.savedRevisions) {
|
for (var i in this.savedRevisions) {
|
||||||
if (this.savedRevisions[i] && this.savedRevisions[i].revNum === revNum) {
|
if (this.savedRevisions[i] && this.savedRevisions[i].revNum === revNum) {
|
||||||
|
@ -618,7 +626,7 @@ Pad.prototype.addSavedRevision = function addSavedRevision(revNum, savedById, la
|
||||||
|
|
||||||
// save this new saved revision
|
// save this new saved revision
|
||||||
this.savedRevisions.push(savedRevision);
|
this.savedRevisions.push(savedRevision);
|
||||||
this.saveToDatabase();
|
await this.saveToDatabase();
|
||||||
};
|
};
|
||||||
|
|
||||||
Pad.prototype.getSavedRevisions = function getSavedRevisions() {
|
Pad.prototype.getSavedRevisions = function getSavedRevisions() {
|
||||||
|
|
|
@ -200,10 +200,11 @@ exports.isValidPadId = function(padId)
|
||||||
/**
|
/**
|
||||||
* Removes the pad from database and unloads it.
|
* Removes the pad from database and unloads it.
|
||||||
*/
|
*/
|
||||||
exports.removePad = function(padId) {
|
exports.removePad = async (padId) => {
|
||||||
db.remove("pad:" + padId);
|
const p = db.remove('pad:' + padId);
|
||||||
exports.unloadPad(padId);
|
exports.unloadPad(padId);
|
||||||
padList.removePad(padId);
|
padList.removePad(padId);
|
||||||
|
await p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// removes a pad from the cache
|
// removes a pad from the cache
|
||||||
|
|
|
@ -226,12 +226,12 @@ async function doImport(req, res, padId)
|
||||||
if (!req.directDatabaseAccess) {
|
if (!req.directDatabaseAccess) {
|
||||||
if (importHandledByPlugin || useConvertor || fileIsHTML) {
|
if (importHandledByPlugin || useConvertor || fileIsHTML) {
|
||||||
try {
|
try {
|
||||||
importHtml.setPadHTML(pad, text);
|
await importHtml.setPadHTML(pad, text);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
apiLogger.warn("Error importing, possibly caused by malformed HTML");
|
apiLogger.warn("Error importing, possibly caused by malformed HTML");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pad.setText(text);
|
await pad.setText(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -294,7 +294,7 @@ async function handleSaveRevisionMessage(client, message)
|
||||||
var userId = sessioninfos[client.id].author;
|
var userId = sessioninfos[client.id].author;
|
||||||
|
|
||||||
let pad = await padManager.getPad(padId);
|
let pad = await padManager.getPad(padId);
|
||||||
pad.addSavedRevision(pad.head, userId);
|
await pad.addSavedRevision(pad.head, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -365,7 +365,7 @@ exports.sendChatMessageToPadClients = async function(time, userId, text, padId)
|
||||||
let userName = await authorManager.getAuthorName(userId);
|
let userName = await authorManager.getAuthorName(userId);
|
||||||
|
|
||||||
// save the chat message
|
// save the chat message
|
||||||
pad.appendChatMessage(text, userId, time);
|
const promise = pad.appendChatMessage(text, userId, time);
|
||||||
|
|
||||||
let msg = {
|
let msg = {
|
||||||
type: "COLLABROOM",
|
type: "COLLABROOM",
|
||||||
|
@ -374,6 +374,8 @@ exports.sendChatMessageToPadClients = async function(time, userId, text, padId)
|
||||||
|
|
||||||
// broadcast the chat message to everyone on the pad
|
// broadcast the chat message to everyone on the pad
|
||||||
socketio.sockets.in(padId).json.send(msg);
|
socketio.sockets.in(padId).json.send(msg);
|
||||||
|
|
||||||
|
await promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -664,7 +666,7 @@ async function handleUserChanges(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pad.appendRevision(changeset, thisSession.author);
|
await pad.appendRevision(changeset, thisSession.author);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
client.json.send({ disconnect: "badChangeset" });
|
client.json.send({ disconnect: "badChangeset" });
|
||||||
stats.meter('failedChangesets').mark();
|
stats.meter('failedChangesets').mark();
|
||||||
|
@ -673,13 +675,13 @@ async function handleUserChanges(data)
|
||||||
|
|
||||||
let correctionChangeset = _correctMarkersInPad(pad.atext, pad.pool);
|
let correctionChangeset = _correctMarkersInPad(pad.atext, pad.pool);
|
||||||
if (correctionChangeset) {
|
if (correctionChangeset) {
|
||||||
pad.appendRevision(correctionChangeset);
|
await pad.appendRevision(correctionChangeset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the pad always ends with an empty line.
|
// Make sure the pad always ends with an empty line.
|
||||||
if (pad.text().lastIndexOf("\n") !== pad.text().length-1) {
|
if (pad.text().lastIndexOf("\n") !== pad.text().length-1) {
|
||||||
var nlChangeset = Changeset.makeSplice(pad.text(), pad.text().length - 1, 0, "\n");
|
var nlChangeset = Changeset.makeSplice(pad.text(), pad.text().length - 1, 0, "\n");
|
||||||
pad.appendRevision(nlChangeset);
|
await pad.appendRevision(nlChangeset);
|
||||||
}
|
}
|
||||||
|
|
||||||
await exports.updatePadClients(pad);
|
await exports.updatePadClients(pad);
|
||||||
|
|
|
@ -22,8 +22,7 @@ const rehype = require("rehype")
|
||||||
const format = require("rehype-format")
|
const format = require("rehype-format")
|
||||||
|
|
||||||
|
|
||||||
exports.setPadHTML = function(pad, html)
|
exports.setPadHTML = async (pad, html) => {
|
||||||
{
|
|
||||||
var apiLogger = log4js.getLogger("ImportHtml");
|
var apiLogger = log4js.getLogger("ImportHtml");
|
||||||
|
|
||||||
var opts = {
|
var opts = {
|
||||||
|
@ -103,6 +102,8 @@ exports.setPadHTML = function(pad, html)
|
||||||
var theChangeset = builder.toString();
|
var theChangeset = builder.toString();
|
||||||
|
|
||||||
apiLogger.debug('The changeset: ' + theChangeset);
|
apiLogger.debug('The changeset: ' + theChangeset);
|
||||||
pad.setText("\n");
|
await Promise.all([
|
||||||
pad.appendRevision(theChangeset);
|
pad.setText('\n'),
|
||||||
|
pad.appendRevision(theChangeset),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue