mirror of
https://github.com/cryptpad/cryptpad.git
synced 2026-09-12 19:49:59 +05:00
Prevent server OOM caused by document history
This commit is contained in:
parent
fe481eda29
commit
3b9b9ea30c
@ -773,6 +773,10 @@ const handleGetHistoryRange = function (Env, Server, seq, userId, parsed) {
|
||||
Env.getOlderHistory(channelName, oldestKnownHash, untilHash, desiredMessages, desiredCheckpoint, function (err, toSend) {
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
Env.Log.error("HK_GET_OLDER_HISTORY", err);
|
||||
Server.send(userId, [0, HISTORY_KEEPER_ID, 'MSG', userId,
|
||||
JSON.stringify(['HISTORY_RANGE_ERROR', txid, err])
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(toSend)) {
|
||||
|
||||
@ -33,6 +33,8 @@ Logger.levels.forEach(function (level) {
|
||||
};
|
||||
});
|
||||
|
||||
const HISTORY_SIZE_LIMIT = 1; // XXX 1GB
|
||||
|
||||
var DETAIL = 1000;
|
||||
var round = function (n) {
|
||||
return Math.floor(n * DETAIL) / DETAIL;
|
||||
@ -322,6 +324,31 @@ const computeMetadata = function (data, cb) {
|
||||
});
|
||||
};
|
||||
|
||||
const _getFileSize = function (channel, _cb) {
|
||||
var cb = Util.once(Util.mkAsync(_cb));
|
||||
if (!Core.isValidId(channel)) { return void cb('INVALID_CHAN'); }
|
||||
if (channel.length === HK.STANDARD_CHANNEL_LENGTH ||
|
||||
channel.length === HK.ADMIN_CHANNEL_LENGTH) {
|
||||
return void store.getChannelSize(channel, function (e, size) {
|
||||
if (e) {
|
||||
if (e.code === 'ENOENT') { return void cb(void 0, 0); }
|
||||
return void cb(e.code);
|
||||
}
|
||||
cb(void 0, size);
|
||||
});
|
||||
}
|
||||
|
||||
// 'channel' refers to a file, so you need another API
|
||||
blobStore.size(channel, function (e, size) {
|
||||
if (typeof(size) === 'undefined') { return void cb(e); }
|
||||
cb(void 0, size);
|
||||
});
|
||||
};
|
||||
|
||||
const getFileSize = function (data, cb) {
|
||||
_getFileSize(data.channel, cb);
|
||||
};
|
||||
|
||||
/* getOlderHistory
|
||||
* allows clients to query for all messages until a known hash is read
|
||||
* stores all messages in history as they are read
|
||||
@ -339,6 +366,7 @@ const getOlderHistory = function (data, cb) {
|
||||
const desiredMessages = data.desiredMessages;
|
||||
const desiredCheckpoint = data.desiredCheckpoint;
|
||||
|
||||
var next = () => {
|
||||
var messages = [];
|
||||
var found = false;
|
||||
store.getMessages(channelName, function (msgStr) {
|
||||
@ -384,6 +412,15 @@ const getOlderHistory = function (data, cb) {
|
||||
}
|
||||
cb(err, toSend);
|
||||
});
|
||||
};
|
||||
|
||||
_getFileSize(channelName, function (err, size) {
|
||||
if (err) { return void cb(err); }
|
||||
if (size > HISTORY_SIZE_LIMIT) {
|
||||
return void cb('HISTORY_TOO_LARGE');
|
||||
}
|
||||
next();
|
||||
});
|
||||
};
|
||||
|
||||
const getPinState = function (data, cb) {
|
||||
@ -401,31 +438,6 @@ const getPinState = function (data, cb) {
|
||||
});
|
||||
};
|
||||
|
||||
const _getFileSize = function (channel, _cb) {
|
||||
var cb = Util.once(Util.mkAsync(_cb));
|
||||
if (!Core.isValidId(channel)) { return void cb('INVALID_CHAN'); }
|
||||
if (channel.length === HK.STANDARD_CHANNEL_LENGTH ||
|
||||
channel.length === HK.ADMIN_CHANNEL_LENGTH) {
|
||||
return void store.getChannelSize(channel, function (e, size) {
|
||||
if (e) {
|
||||
if (e.code === 'ENOENT') { return void cb(void 0, 0); }
|
||||
return void cb(e.code);
|
||||
}
|
||||
cb(void 0, size);
|
||||
});
|
||||
}
|
||||
|
||||
// 'channel' refers to a file, so you need another API
|
||||
blobStore.size(channel, function (e, size) {
|
||||
if (typeof(size) === 'undefined') { return void cb(e); }
|
||||
cb(void 0, size);
|
||||
});
|
||||
};
|
||||
|
||||
const getFileSize = function (data, cb) {
|
||||
_getFileSize(data.channel, cb);
|
||||
};
|
||||
|
||||
const _iterateFiles = function (channels, handler, cb) {
|
||||
if (!Array.isArray(channels)) { return cb('INVALID_LIST'); }
|
||||
var L = channels.length;
|
||||
|
||||
@ -2343,6 +2343,12 @@ define([
|
||||
if (completed) { return; }
|
||||
var parsed = parse(msg);
|
||||
if (parsed[1] !== txid) { console.log('bad txid'); return; }
|
||||
if (parsed[0] === 'HISTORY_RANGE_ERROR') {
|
||||
cb({
|
||||
error: parsed[2]
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (parsed[0] === 'HISTORY_RANGE_END') {
|
||||
cb({
|
||||
messages: msgs,
|
||||
|
||||
@ -212,6 +212,9 @@ define([
|
||||
sharedFolder: config.sharedFolder
|
||||
}, function (err, data) {
|
||||
if (err) { return void console.error(err); }
|
||||
if (data && data.error) {
|
||||
return void cb(data.error);
|
||||
}
|
||||
if (!Array.isArray(data.messages)) { return void console.error('Not an array!'); }
|
||||
lastKnownHash = data.lastKnownHash;
|
||||
isComplete = data.isFull;
|
||||
@ -288,6 +291,14 @@ define([
|
||||
|
||||
UI.spinner($hist).get().show();
|
||||
|
||||
let closeAll = () => {
|
||||
History.state = false;
|
||||
$hist.hide()
|
||||
$bottom.show();
|
||||
$cke.show();
|
||||
$(window).trigger('resize');
|
||||
};
|
||||
|
||||
var update = function (newRt) {
|
||||
realtime = newRt;
|
||||
if (!realtime) { return []; }
|
||||
@ -567,11 +578,7 @@ define([
|
||||
|
||||
var onKeyDown, onKeyUp;
|
||||
var closeUI = function () {
|
||||
History.state = false;
|
||||
$hist.hide();
|
||||
$bottom.show();
|
||||
$cke.show();
|
||||
$(window).trigger('resize');
|
||||
closeAll();
|
||||
$(window).off('keydown', onKeyDown);
|
||||
$(window).off('keyup', onKeyUp);
|
||||
};
|
||||
@ -681,7 +688,12 @@ define([
|
||||
loadMoreHistory(config, common, function (err, newRt, isFull) {
|
||||
History.readOnly = common.getMetadataMgr().getPrivateData().readOnly;
|
||||
History.loading = false;
|
||||
if (err) { throw new Error(err); }
|
||||
if (err) {
|
||||
console.error(err);
|
||||
UI.warn(`${Messages.error}: ${err}`);
|
||||
closeAll();
|
||||
return;
|
||||
}
|
||||
update(newRt);
|
||||
display();
|
||||
if (isFull) {
|
||||
|
||||
@ -1322,6 +1322,9 @@ define([
|
||||
toHash: data.toHash,
|
||||
lastKnownHash: data.lastKnownHash
|
||||
}, function (data) {
|
||||
if (data && data.error) {
|
||||
return void cb(data);
|
||||
}
|
||||
cb({
|
||||
isFull: data.isFull,
|
||||
messages: data.messages.map(function (obj) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user