allow some operations to proceed in parallel

some code chunks previously used `async.parallel` but if you
use `await` that forces them to be run serially.  Instead,
you can initiate the operation (getting a Promise) and then
_later_ `await` the result of that Promise.
This commit is contained in:
Ray Bellis 2019-02-01 09:57:50 +00:00
parent e7c2fad7b0
commit 769933786c
3 changed files with 37 additions and 21 deletions

View file

@ -169,9 +169,8 @@ Pad.prototype.getInternalRevisionAText = async function getInternalRevisionAText
// get all needed data out of the database // get all needed data out of the database
// get the atext of the key revision // start to get the atext of the key revision
let _atext = await db.getSub("pad:" + this.id + ":revs:" + keyRev, ["meta", "atext"]); let p_atext = db.getSub("pad:" + this.id + ":revs:" + keyRev, ["meta", "atext"]);
let atext = Changeset.cloneAText(_atext);
// get all needed changesets // get all needed changesets
let changesets = []; let changesets = [];
@ -181,6 +180,10 @@ Pad.prototype.getInternalRevisionAText = async function getInternalRevisionAText
}); });
})); }));
// we should have the atext by now
let atext = await p_atext;
atext = Changeset.cloneAText(atext);
// apply all changesets to the key changeset // apply all changesets to the key changeset
let apool = this.apool(); let apool = this.apool();
for (let curRev = keyRev; curRev < targetRev; ) { for (let curRev = keyRev; curRev < targetRev; ) {
@ -455,7 +458,10 @@ Pad.prototype.remove = async function remove() {
// kick everyone from this pad // kick everyone from this pad
padMessageHandler.kickSessionsFromPad(padID); padMessageHandler.kickSessionsFromPad(padID);
// delete all relations // delete all relations - the original code used async.parallel but
// none of the operations except getting the group depended on callbacks
// so the database operations here are just started and then left to
// run to completion
// is it a group pad? -> delete the entry of this pad in the group // is it a group pad? -> delete the entry of this pad in the group
if (padID.indexOf("$") >= 0) { if (padID.indexOf("$") >= 0) {

View file

@ -49,11 +49,11 @@ exports.checkAccess = async function(padID, sessionCookie, token, password)
return deny; return deny;
} }
// get author for this token // start to get author for this token
let tokenAuthor = await authorManager.getAuthor4Token(token); let p_tokenAuthor = authorManager.getAuthor4Token(token);
// check if pad exists // start to check if pad exists
let padExists = await padManager.doesPadExist(padID); let p_padExists = padManager.doesPadExist(padID);
if (settings.requireSession) { if (settings.requireSession) {
// a valid session is required (api-only mode) // a valid session is required (api-only mode)
@ -67,11 +67,14 @@ exports.checkAccess = async function(padID, sessionCookie, token, password)
// it's not a group pad, means we can grant access // it's not a group pad, means we can grant access
// assume user has access // assume user has access
let statusObject = { accessStatus: "grant", authorID: tokenAuthor }; let authorID = await p_tokenAuthor;
let statusObject = { accessStatus: "grant", authorID };
if (settings.editOnly) { if (settings.editOnly) {
// user can't create pads // user can't create pads
let padExists = await p_padExists;
if (!padExists) { if (!padExists) {
// pad doesn't exist - user can't have access // pad doesn't exist - user can't have access
statusObject.accessStatus = "deny"; statusObject.accessStatus = "deny";
@ -96,10 +99,13 @@ exports.checkAccess = async function(padID, sessionCookie, token, password)
let sessionIDs = sessionCookie.split(','); let sessionIDs = sessionCookie.split(',');
// was previously iterated in parallel using async.forEach // was previously iterated in parallel using async.forEach
for (let sessionID of sessionIDs) { let sessionInfos = await Promise.all(sessionIDs.map(sessionID => {
try { return sessionManager.getSessionInfo(sessionID);
let sessionInfo = await sessionManager.getSessionInfo(sessionID); }));
// seperated out the iteration of sessioninfos from the (parallel) fetches from the DB
for (let sessionInfo of sessionInfos) {
try {
// is it for this group? // is it for this group?
if (sessionInfo.groupID != groupID) { if (sessionInfo.groupID != groupID) {
authLogger.debug("Auth failed: wrong group"); authLogger.debug("Auth failed: wrong group");
@ -128,6 +134,8 @@ exports.checkAccess = async function(padID, sessionCookie, token, password)
} }
} }
let padExists = await p_padExists;
if (padExists) { if (padExists) {
let pad = await padManager.getPad(padID); let pad = await padManager.getPad(padID);
@ -205,7 +213,7 @@ exports.checkAccess = async function(padID, sessionCookie, token, password)
if (!validSession && padExists) { if (!validSession && padExists) {
// there is no valid session avaiable AND pad exists // there is no valid session avaiable AND pad exists
let authorID = tokenAuthor; let authorID = await p_tokenAuthor;
let grant = Object.freeze({ accessStatus: "grant", authorID }); let grant = Object.freeze({ accessStatus: "grant", authorID });
if (isPublic && !isPasswordProtected) { if (isPublic && !isPasswordProtected) {

View file

@ -890,8 +890,6 @@ async function handleClientReady(client, message)
return; return;
} }
var historicalAuthorData = {};
hooks.callAll("clientReady", message); hooks.callAll("clientReady", message);
// Get ro/rw id:s // Get ro/rw id:s
@ -915,12 +913,12 @@ async function handleClientReady(client, message)
let author = statusObject.authorID; let author = statusObject.authorID;
// get all authordata of this new user, and load the pad-object from the database // get all authordata of this new user
let value = await authorManager.getAuthor(author); let value = await authorManager.getAuthor(author);
let authorColorId = value.colorId; let authorColorId = value.colorId;
let authorName = value.name; let authorName = value.name;
// get pad // load the pad-object from the database
let pad = await padManager.getPad(padIds.padId); let pad = await padManager.getPad(padIds.padId);
// these db requests all need the pad object (timestamp of latest revision, author data) // these db requests all need the pad object (timestamp of latest revision, author data)
@ -930,6 +928,7 @@ async function handleClientReady(client, message)
let currentTime = await pad.getRevisionDate(pad.getHeadRevisionNumber()); let currentTime = await pad.getRevisionDate(pad.getHeadRevisionNumber());
// get all author data out of the database (in parallel) // get all author data out of the database (in parallel)
let historicalAuthorData = {};
await Promise.all(authors.map(authorId => { await Promise.all(authors.map(authorId => {
return authorManager.getAuthor(authorId).then(author => { return authorManager.getAuthor(authorId).then(author => {
if (!author) { if (!author) {
@ -1010,12 +1009,15 @@ async function handleClientReady(client, message)
changesets[r] = {}; changesets[r] = {};
} }
// get changesets, author and timestamp needed for pending revisions // get changesets, author and timestamp needed for pending revisions (in parallel)
let promises = [];
for (let revNum of revisionsNeeded) { for (let revNum of revisionsNeeded) {
changesets[revNum]['changeset'] = await pad.getRevisionChangeset(revNum); let cs = changesets[revNum];
changesets[revNum]['author'] = await pad.getRevisionAuthor(revNum); promises.push( pad.getRevisionChangeset(revNum).then(result => cs.changeset = result ));
changesets[revNum]['timestamp'] = await pad.getRevisionDate(revNum); promises.push( pad.getRevisionAuthor(revNum).then(result => cs.author = result ));
promises.push( pad.getRevisionDate(revNum).then(result => cs.timestamp = result ));
} }
await Promise.all(promises);
// return pending changesets // return pending changesets
for (let r of revisionsNeeded) { for (let r of revisionsNeeded) {