PadMessageHandler.js: further conversion
parent
d543d5ae6a
commit
9246a1de26
|
@ -1274,7 +1274,7 @@ async function handleClientReady(client, message)
|
|||
/**
|
||||
* 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
|
||||
if (message.data == null) {
|
||||
|
@ -1308,309 +1308,182 @@ function handleChangesetRequest(client, message)
|
|||
return;
|
||||
}
|
||||
|
||||
var granularity = message.data.granularity;
|
||||
var start = message.data.start;
|
||||
var end = start + (100 * granularity);
|
||||
var padIds;
|
||||
let granularity = message.data.granularity;
|
||||
let start = message.data.start;
|
||||
let end = start + (100 * granularity);
|
||||
|
||||
async.series([
|
||||
function(callback) {
|
||||
readOnlyManager.getIds(message.padId, function(err, value) {
|
||||
if (ERR(err, callback)) return;
|
||||
let padIds = await readOnlyManager.getIds(message.padId);
|
||||
|
||||
padIds = value;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
|
||||
function(callback) {
|
||||
// build the requested rough changesets and send them back
|
||||
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;
|
||||
try {
|
||||
let data = await getChangesetInfo(padIds.padId, start, end, granularity);
|
||||
data.requestID = message.data.requestID;
|
||||
|
||||
client.json.send({ type: "CHANGESET_REQ", data: data });
|
||||
});
|
||||
client.json.send({ type: "CHANGESET_REQ", data });
|
||||
} catch (err) {
|
||||
console.error('Error while handling a changeset request for ' + padIds.padId, err, message.data);
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
let getChangesetInfo = thenify(function getChangesetInfo(padId, startNum, endNum, granularity, callback)
|
||||
async function getChangesetInfo(padId, startNum, endNum, granularity)
|
||||
{
|
||||
var forwardsChangesets = [];
|
||||
var backwardsChangesets = [];
|
||||
var timeDeltas = [];
|
||||
var apool = new AttributePool();
|
||||
var pad;
|
||||
var composedChangesets = {};
|
||||
var revisionDate = [];
|
||||
var lines;
|
||||
var head_revision = 0;
|
||||
let pad = await padManager.getPad(padId);
|
||||
let head_revision = pad.getHeadRevisionNumber();
|
||||
|
||||
async.series([
|
||||
// get the pad from the database
|
||||
function(callback) {
|
||||
padManager.getPad(padId, function(err, _pad) {
|
||||
if (ERR(err, callback)) return;
|
||||
|
||||
pad = _pad;
|
||||
head_revision = pad.getHeadRevisionNumber();
|
||||
callback();
|
||||
});
|
||||
},
|
||||
|
||||
function(callback) {
|
||||
// calculate the last full endnum
|
||||
var lastRev = pad.getHeadRevisionNumber();
|
||||
if (endNum > lastRev + 1) {
|
||||
endNum = lastRev + 1;
|
||||
if (endNum > head_revision + 1) {
|
||||
endNum = head_revision + 1;
|
||||
}
|
||||
|
||||
endNum = Math.floor(endNum / granularity) * granularity;
|
||||
|
||||
var compositesChangesetNeeded = [];
|
||||
var revTimesNeeded = [];
|
||||
let compositesChangesetNeeded = [];
|
||||
let revTimesNeeded = [];
|
||||
|
||||
// figure out which composite Changeset and revTimes we need, to load them in bulk
|
||||
var compositeStart = startNum;
|
||||
while (compositeStart < endNum) {
|
||||
var compositeEnd = compositeStart + granularity;
|
||||
for (let start = startNum; start < endNum; start += granularity) {
|
||||
let end = start + granularity;
|
||||
|
||||
// add the composite Changeset we needed
|
||||
compositesChangesetNeeded.push({ start: compositeStart, end: compositeEnd });
|
||||
compositesChangesetNeeded.push({ start, end });
|
||||
|
||||
// add the t1 time we need
|
||||
revTimesNeeded.push(compositeStart == 0 ? 0 : compositeStart - 1);
|
||||
revTimesNeeded.push(start == 0 ? 0 : start - 1);
|
||||
|
||||
// add the t2 time we need
|
||||
revTimesNeeded.push(compositeEnd - 1);
|
||||
|
||||
compositeStart += granularity;
|
||||
revTimesNeeded.push(end - 1);
|
||||
}
|
||||
|
||||
// get all needed db values parallel
|
||||
async.parallel([
|
||||
function(callback) {
|
||||
// get all needed db values parallel - no await here since
|
||||
// it would make all the lookups run in series
|
||||
|
||||
// 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;
|
||||
|
||||
let composedChangesets = {};
|
||||
let p1 = Promise.all(compositesChangesetNeeded.map(item => {
|
||||
return composePadChangesets(padId, item.start, item.end).then(changeset => {
|
||||
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;
|
||||
|
||||
let revisionDate = [];
|
||||
let p2 = Promise.all(revTimesNeeded.map(revNum => {
|
||||
return pad.getRevisionDate(revNum).then(revDate => {
|
||||
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;
|
||||
|
||||
let lines;
|
||||
let p3 = getPadLines(padId, startNum - 1).then(_lines => {
|
||||
lines = _lines;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
], callback);
|
||||
},
|
||||
|
||||
// don't know what happens here exactly :/
|
||||
function(callback) {
|
||||
var compositeStart = startNum;
|
||||
// wait for all of the above to complete
|
||||
await Promise.all([p1, p2, p3]);
|
||||
|
||||
while (compositeStart < endNum) {
|
||||
var compositeEnd = compositeStart + granularity;
|
||||
// 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;
|
||||
}
|
||||
|
||||
var forwards = composedChangesets[compositeStart + "/" + compositeEnd];
|
||||
var backwards = Changeset.inverse(forwards, lines.textlines, lines.alines, pad.apool());
|
||||
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);
|
||||
|
||||
var forwards2 = Changeset.moveOpsToNewPool(forwards, pad.apool(), apool);
|
||||
var backwards2 = Changeset.moveOpsToNewPool(backwards, pad.apool(), apool);
|
||||
let forwards2 = Changeset.moveOpsToNewPool(forwards, pad.apool(), apool);
|
||||
let 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];
|
||||
let t1 = (compositeStart == 0) ? revisionDate[0] : revisionDate[compositeStart - 1];
|
||||
let t2 = revisionDate[compositeEnd - 1];
|
||||
|
||||
timeDeltas.push(t2 - t1);
|
||||
forwardsChangesets.push(forwards2);
|
||||
backwardsChangesets.push(backwards2);
|
||||
|
||||
compositeStart += granularity;
|
||||
}
|
||||
|
||||
callback();
|
||||
return { forwardsChangesets, backwardsChangesets,
|
||||
apool: apool.toJsonable(), actualEndNum: endNum,
|
||||
timeDeltas, start: startNum, granularity };
|
||||
}
|
||||
],
|
||||
function(err) {
|
||||
if (ERR(err, callback)) return;
|
||||
|
||||
callback(null, {forwardsChangesets: forwardsChangesets,
|
||||
backwardsChangesets: backwardsChangesets,
|
||||
apool: apool.toJsonable(),
|
||||
actualEndNum: endNum,
|
||||
timeDeltas: timeDeltas,
|
||||
start: startNum,
|
||||
granularity: granularity });
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
let getPadLines = thenify(function getPadLines(padId, revNum, callback)
|
||||
async function getPadLines(padId, revNum)
|
||||
{
|
||||
var atext;
|
||||
var result = {};
|
||||
var pad;
|
||||
|
||||
async.series([
|
||||
// get the pad from the database
|
||||
function(callback) {
|
||||
padManager.getPad(padId, function(err, _pad) {
|
||||
if (ERR(err, callback)) return;
|
||||
|
||||
pad = _pad;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
let pad = padManager.getPad(padId);
|
||||
|
||||
// get the atext
|
||||
function(callback) {
|
||||
if (revNum >= 0) {
|
||||
pad.getInternalRevisionAText(revNum, function(err, _atext) {
|
||||
if (ERR(err, callback)) return;
|
||||
let atext;
|
||||
|
||||
atext = _atext;
|
||||
callback();
|
||||
});
|
||||
if (revNum >= 0) {
|
||||
atext = await pad.getInternalRevisionAText(revNum);
|
||||
} 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);
|
||||
return {
|
||||
textlines: Changeset.splitTextLines(atext.text),
|
||||
alines: Changeset.splitAttributionLines(atext.attribs, atext.text)
|
||||
};
|
||||
}
|
||||
],
|
||||
|
||||
function(err) {
|
||||
if (ERR(err, callback)) return;
|
||||
|
||||
callback(null, result);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
let composePadChangesets = thenify(function(padId, startNum, endNum, callback)
|
||||
async function composePadChangesets (padId, startNum, endNum)
|
||||
{
|
||||
var pad;
|
||||
var changesets = {};
|
||||
var changeset;
|
||||
|
||||
async.series([
|
||||
// get the pad from the database
|
||||
function(callback) {
|
||||
padManager.getPad(padId, function(err, _pad) {
|
||||
if (ERR(err, callback)) return;
|
||||
|
||||
pad = _pad;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
let pad = await padManager.getPad(padId);
|
||||
|
||||
// fetch all changesets we need
|
||||
function(callback) {
|
||||
var changesetsNeeded=[];
|
||||
|
||||
var headNum = pad.getHeadRevisionNumber();
|
||||
if (endNum > headNum + 1) {
|
||||
endNum = headNum + 1;
|
||||
}
|
||||
|
||||
if (startNum < 0) {
|
||||
startNum = 0;
|
||||
}
|
||||
let headNum = pad.getHeadRevisionNumber();
|
||||
endNum = Math.min(endNum, headNum + 1);
|
||||
startNum = Math.max(startNum, 0);
|
||||
|
||||
// create an array for all changesets, we will
|
||||
// replace the values with the changeset later
|
||||
for (var r = startNum; r < endNum; r++) {
|
||||
let changesetsNeeded = [];
|
||||
for (let 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);
|
||||
},
|
||||
let changesets = {};
|
||||
await Promise.all(changesetsNeeded.map(revNum => {
|
||||
return pad.getRevisionChangeset(revNum).then(changeset => changesets[revNum] = changeset);
|
||||
}));
|
||||
|
||||
// compose Changesets
|
||||
function(callback) {
|
||||
changeset = changesets[startNum];
|
||||
var pool = pad.apool();
|
||||
|
||||
try {
|
||||
for (var r = startNum + 1; r < endNum; r++) {
|
||||
var cs = changesets[r];
|
||||
let changeset = changesets[startNum];
|
||||
let pool = pad.apool();
|
||||
|
||||
for (let r = startNum + 1; r < endNum; r++) {
|
||||
let cs = changesets[r];
|
||||
changeset = Changeset.compose(changeset, cs, pool);
|
||||
}
|
||||
return changeset;
|
||||
|
||||
} 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);
|
||||
throw e;
|
||||
}
|
||||
|
||||
callback(null);
|
||||
}
|
||||
],
|
||||
|
||||
// return err and changeset
|
||||
function(err) {
|
||||
if (ERR(err, callback)) return;
|
||||
|
||||
callback(null, changeset);
|
||||
});
|
||||
});
|
||||
|
||||
function _getRoomClients(padID) {
|
||||
var roomClients = [];
|
||||
|
|
Loading…
Reference in New Issue