PadMessageHandler.js: further conversion

This commit is contained in:
Ray Bellis 2019-01-30 13:55:49 +00:00
parent d543d5ae6a
commit 9246a1de26

View file

@ -1274,7 +1274,7 @@ async function handleClientReady(client, message)
/** /**
* Handles a request for a rough changeset, the timeslider client needs it * Handles a request for a rough changeset, the timeslider client needs it
*/ */
function handleChangesetRequest(client, message) async function handleChangesetRequest(client, message)
{ {
// check if all ok // check if all ok
if (message.data == null) { if (message.data == null) {
@ -1308,309 +1308,182 @@ function handleChangesetRequest(client, message)
return; return;
} }
var granularity = message.data.granularity; let granularity = message.data.granularity;
var start = message.data.start; let start = message.data.start;
var end = start + (100 * granularity); let end = start + (100 * granularity);
var padIds;
async.series([ let padIds = await readOnlyManager.getIds(message.padId);
function(callback) {
readOnlyManager.getIds(message.padId, function(err, value) {
if (ERR(err, callback)) return;
padIds = value; // build the requested rough changesets and send them back
callback(); try {
}); let data = await getChangesetInfo(padIds.padId, start, end, granularity);
}, data.requestID = message.data.requestID;
client.json.send({ type: "CHANGESET_REQ", data });
function(callback) { } catch (err) {
// build the requested rough changesets and send them back console.error('Error while handling a changeset request for ' + padIds.padId, err, message.data);
getChangesetInfo(padIds.padId, start, end, granularity, function(err, changesetInfo) { }
if (err) return console.error('Error while handling a changeset request for ' + padIds.padId, err, message.data);
var data = changesetInfo;
data.requestID = message.data.requestID;
client.json.send({ type: "CHANGESET_REQ", data: data });
});
}
]);
} }
/** /**
* Tries to rebuild the getChangestInfo function of the original Etherpad * Tries to rebuild the getChangestInfo function of the original Etherpad
* https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L144 * https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L144
*/ */
let getChangesetInfo = thenify(function getChangesetInfo(padId, startNum, endNum, granularity, callback) async function getChangesetInfo(padId, startNum, endNum, granularity)
{ {
var forwardsChangesets = []; let pad = await padManager.getPad(padId);
var backwardsChangesets = []; let head_revision = pad.getHeadRevisionNumber();
var timeDeltas = [];
var apool = new AttributePool();
var pad;
var composedChangesets = {};
var revisionDate = [];
var lines;
var head_revision = 0;
async.series([ // calculate the last full endnum
// get the pad from the database if (endNum > head_revision + 1) {
function(callback) { endNum = head_revision + 1;
padManager.getPad(padId, function(err, _pad) { }
if (ERR(err, callback)) return; endNum = Math.floor(endNum / granularity) * granularity;
pad = _pad; let compositesChangesetNeeded = [];
head_revision = pad.getHeadRevisionNumber(); let revTimesNeeded = [];
callback();
});
},
function(callback) { // figure out which composite Changeset and revTimes we need, to load them in bulk
// calculate the last full endnum for (let start = startNum; start < endNum; start += granularity) {
var lastRev = pad.getHeadRevisionNumber(); let end = start + granularity;
if (endNum > lastRev + 1) {
endNum = lastRev + 1;
}
endNum = Math.floor(endNum / granularity) * granularity; // add the composite Changeset we needed
compositesChangesetNeeded.push({ start, end });
var compositesChangesetNeeded = []; // add the t1 time we need
var revTimesNeeded = []; revTimesNeeded.push(start == 0 ? 0 : start - 1);
// figure out which composite Changeset and revTimes we need, to load them in bulk // add the t2 time we need
var compositeStart = startNum; revTimesNeeded.push(end - 1);
while (compositeStart < endNum) { }
var compositeEnd = compositeStart + granularity;
// add the composite Changeset we needed // get all needed db values parallel - no await here since
compositesChangesetNeeded.push({ start: compositeStart, end: compositeEnd }); // it would make all the lookups run in series
// add the t1 time we need // get all needed composite Changesets
revTimesNeeded.push(compositeStart == 0 ? 0 : compositeStart - 1); let composedChangesets = {};
let p1 = Promise.all(compositesChangesetNeeded.map(item => {
return composePadChangesets(padId, item.start, item.end).then(changeset => {
composedChangesets[item.start + "/" + item.end] = changeset;
});
}));
// add the t2 time we need // get all needed revision Dates
revTimesNeeded.push(compositeEnd - 1); let revisionDate = [];
let p2 = Promise.all(revTimesNeeded.map(revNum => {
return pad.getRevisionDate(revNum).then(revDate => {
revisionDate[revNum] = Math.floor(revDate / 1000);
});
}));
compositeStart += granularity; // get the lines
} let lines;
let p3 = getPadLines(padId, startNum - 1).then(_lines => {
// get all needed db values parallel lines = _lines;
async.parallel([
function(callback) {
// get all needed composite Changesets
async.forEach(compositesChangesetNeeded, function(item, callback) {
composePadChangesets(padId, item.start, item.end, function(err, changeset) {
if (ERR(err, callback)) return;
composedChangesets[item.start + "/" + item.end] = changeset;
callback();
});
}, callback);
},
function(callback) {
// get all needed revision Dates
async.forEach(revTimesNeeded, function(revNum, callback) {
pad.getRevisionDate(revNum, function(err, revDate) {
if (ERR(err, callback)) return;
revisionDate[revNum] = Math.floor(revDate/1000);
callback();
});
}, callback);
},
// get the lines
function(callback) {
getPadLines(padId, startNum-1, function(err, _lines) {
if (ERR(err, callback)) return;
lines = _lines;
callback();
});
}
], callback);
},
// don't know what happens here exactly :/
function(callback) {
var compositeStart = startNum;
while (compositeStart < endNum) {
var compositeEnd = compositeStart + granularity;
if (compositeEnd > endNum || compositeEnd > head_revision+1) {
break;
}
var forwards = composedChangesets[compositeStart + "/" + compositeEnd];
var backwards = Changeset.inverse(forwards, lines.textlines, lines.alines, pad.apool());
Changeset.mutateAttributionLines(forwards, lines.alines, pad.apool());
Changeset.mutateTextLines(forwards, lines.textlines);
var forwards2 = Changeset.moveOpsToNewPool(forwards, pad.apool(), apool);
var backwards2 = Changeset.moveOpsToNewPool(backwards, pad.apool(), apool);
var t1, t2;
if (compositeStart == 0) {
t1 = revisionDate[0];
} else {
t1 = revisionDate[compositeStart - 1];
}
t2 = revisionDate[compositeEnd - 1];
timeDeltas.push(t2 - t1);
forwardsChangesets.push(forwards2);
backwardsChangesets.push(backwards2);
compositeStart += granularity;
}
callback();
}
],
function(err) {
if (ERR(err, callback)) return;
callback(null, {forwardsChangesets: forwardsChangesets,
backwardsChangesets: backwardsChangesets,
apool: apool.toJsonable(),
actualEndNum: endNum,
timeDeltas: timeDeltas,
start: startNum,
granularity: granularity });
}); });
});
// wait for all of the above to complete
await Promise.all([p1, p2, p3]);
// doesn't know what happens here exactly :/
let timeDeltas = [];
let forwardsChangesets = [];
let backwardsChangesets = [];
let apool = new AttributePool();
for (let compositeStart = startNum; compositeStart < endNum; compositeStart += granularity) {
let compositeEnd = compositeStart + granularity;
if (compositeEnd > endNum || compositeEnd > head_revision + 1) {
break;
}
let forwards = composedChangesets[compositeStart + "/" + compositeEnd];
let backwards = Changeset.inverse(forwards, lines.textlines, lines.alines, pad.apool());
Changeset.mutateAttributionLines(forwards, lines.alines, pad.apool());
Changeset.mutateTextLines(forwards, lines.textlines);
let forwards2 = Changeset.moveOpsToNewPool(forwards, pad.apool(), apool);
let backwards2 = Changeset.moveOpsToNewPool(backwards, pad.apool(), apool);
let t1 = (compositeStart == 0) ? revisionDate[0] : revisionDate[compositeStart - 1];
let t2 = revisionDate[compositeEnd - 1];
timeDeltas.push(t2 - t1);
forwardsChangesets.push(forwards2);
backwardsChangesets.push(backwards2);
}
return { forwardsChangesets, backwardsChangesets,
apool: apool.toJsonable(), actualEndNum: endNum,
timeDeltas, start: startNum, granularity };
}
/** /**
* Tries to rebuild the getPadLines function of the original Etherpad * Tries to rebuild the getPadLines function of the original Etherpad
* https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L263 * https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L263
*/ */
let getPadLines = thenify(function getPadLines(padId, revNum, callback) async function getPadLines(padId, revNum)
{ {
var atext; let pad = padManager.getPad(padId);
var result = {};
var pad;
async.series([ // get the atext
// get the pad from the database let atext;
function(callback) {
padManager.getPad(padId, function(err, _pad) {
if (ERR(err, callback)) return;
pad = _pad; if (revNum >= 0) {
callback(); atext = await pad.getInternalRevisionAText(revNum);
}); } else {
}, atext = Changeset.makeAText("\n");
}
// get the atext return {
function(callback) { textlines: Changeset.splitTextLines(atext.text),
if (revNum >= 0) { alines: Changeset.splitAttributionLines(atext.attribs, atext.text)
pad.getInternalRevisionAText(revNum, function(err, _atext) { };
if (ERR(err, callback)) return; }
atext = _atext;
callback();
});
} else {
atext = Changeset.makeAText("\n");
callback(null);
}
},
function(callback) {
result.textlines = Changeset.splitTextLines(atext.text);
result.alines = Changeset.splitAttributionLines(atext.attribs, atext.text);
callback(null);
}
],
function(err) {
if (ERR(err, callback)) return;
callback(null, result);
});
});
/** /**
* Tries to rebuild the composePadChangeset function of the original Etherpad * Tries to rebuild the composePadChangeset function of the original Etherpad
* https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L241 * https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L241
*/ */
let composePadChangesets = thenify(function(padId, startNum, endNum, callback) async function composePadChangesets (padId, startNum, endNum)
{ {
var pad; let pad = await padManager.getPad(padId);
var changesets = {};
var changeset;
async.series([ // fetch all changesets we need
// get the pad from the database let headNum = pad.getHeadRevisionNumber();
function(callback) { endNum = Math.min(endNum, headNum + 1);
padManager.getPad(padId, function(err, _pad) { startNum = Math.max(startNum, 0);
if (ERR(err, callback)) return;
pad = _pad; // create an array for all changesets, we will
callback(); // replace the values with the changeset later
}); let changesetsNeeded = [];
}, for (let r = startNum ; r < endNum; r++) {
changesetsNeeded.push(r);
}
// fetch all changesets we need // get all changesets
function(callback) { let changesets = {};
var changesetsNeeded=[]; await Promise.all(changesetsNeeded.map(revNum => {
return pad.getRevisionChangeset(revNum).then(changeset => changesets[revNum] = changeset);
}));
var headNum = pad.getHeadRevisionNumber(); // compose Changesets
if (endNum > headNum + 1) { try {
endNum = headNum + 1; let changeset = changesets[startNum];
} let pool = pad.apool();
if (startNum < 0) { for (let r = startNum + 1; r < endNum; r++) {
startNum = 0; let cs = changesets[r];
} changeset = Changeset.compose(changeset, cs, pool);
// create an array for all changesets, we will
// replace the values with the changeset later
for (var r = startNum; r < endNum; r++) {
changesetsNeeded.push(r);
}
// get all changesets
async.forEach(changesetsNeeded, function(revNum,callback) {
pad.getRevisionChangeset(revNum, function(err, value) {
if (ERR(err, callback)) return;
changesets[revNum] = value;
callback();
});
},callback);
},
// compose Changesets
function(callback) {
changeset = changesets[startNum];
var pool = pad.apool();
try {
for (var r = startNum + 1; r < endNum; r++) {
var cs = changesets[r];
changeset = Changeset.compose(changeset, cs, pool);
}
} catch(e) {
// r-1 indicates the rev that was build starting with startNum, applying startNum+1, +2, +3
console.warn("failed to compose cs in pad:", padId, " startrev:", startNum, " current rev:", r);
return callback(e);
}
callback(null);
} }
], return changeset;
// return err and changeset } catch (e) {
function(err) { // r-1 indicates the rev that was build starting with startNum, applying startNum+1, +2, +3
if (ERR(err, callback)) return; console.warn("failed to compose cs in pad:", padId, " startrev:", startNum," current rev:", r);
throw e;
callback(null, changeset); }
}); }
});
function _getRoomClients(padID) { function _getRoomClients(padID) {
var roomClients = []; var roomClients = [];