diff --git a/lib/hk-util.js b/lib/hk-util.js index 93c3f9c0e..372c9b290 100644 --- a/lib/hk-util.js +++ b/lib/hk-util.js @@ -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)) { diff --git a/lib/workers/db-worker.js b/lib/workers/db-worker.js index 398260d61..4bfae8d55 100644 --- a/lib/workers/db-worker.js +++ b/lib/workers/db-worker.js @@ -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; diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index 569db9bff..e9eb8226a 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -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, diff --git a/www/common/sframe-common-history.js b/www/common/sframe-common-history.js index 943e3f225..55bf2126c 100644 --- a/www/common/sframe-common-history.js +++ b/www/common/sframe-common-history.js @@ -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) { diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index b4031d155..097bb403b 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -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) {