diff --git a/lib/pins.js b/lib/pins.js index 4e0791d05..23b1364a3 100644 --- a/lib/pins.js +++ b/lib/pins.js @@ -2,20 +2,44 @@ var Pins = module.exports; -/* - takes contents of a pinFile (UTF8 string) - and the pin file's name - returns an array of of channel ids which are pinned - - throw errors on pin logs with invalid pin data +/* Accepts a reference to an object, and... + either a string describing which log is being processed (backwards compatibility), + or a function which will log the error with all relevant data */ -Pins.calculateFromLog = function (pinFile, fileName) { - var pins = {}; - pinFile.split('\n').filter((x)=>(x)).map((l) => JSON.parse(l)).forEach((l) => { +var createLineHandler = Pins.createLineHandler = function (ref, errorHandler) { + var fileName; + if (typeof(errorHandler) === 'string') { + fileName = errorHandler; + errorHandler = function (label, data) { + console.error(label, { + log: fileName, + data: data, + }); + }; + } + + // passing the reference to an object allows us to overwrite accumulated pins + // make sure to get ref.pins as the result + // it's a weird API but it's faster than unpinning manually + var pins = ref.pins = {}; + return function (line) { + if (!Boolean(line)) { return; } + + var l; + try { + l = JSON.parse(line); + } catch (e) { + return void errorHandler('PIN_LINE_PARSE_ERROR', line); + } + + if (!Array.isArray(l)) { + return void errorHandler('PIN_LINE_NOT_FORMAT_ERROR', l); + } + switch (l[0]) { case 'RESET': { - pins = {}; - if (l[1] && l[1].length) { l[1].forEach((x) => { pins[x] = 1; }); } + pins = ref.pins = {}; + if (l[1] && l[1].length) { l[1].forEach((x) => { ref.pins[x] = 1; }); } //jshint -W086 // fallthrough } @@ -28,16 +52,25 @@ Pins.calculateFromLog = function (pinFile, fileName) { break; } default: - // FIXME logging - // TODO write to the error log - /* Log.error('CORRUPTED_PIN_LOG', { - line: JSON.stringify(l), - fileName: fileName, - }); */ - console.error(new Error (JSON.stringify(l) + ' ' + fileName)); + errorHandler("PIN_LINE_UNSUPPORTED_COMMAND", l); } - }); - return Object.keys(pins); + }; +}; + +/* + takes contents of a pinFile (UTF8 string) + and the pin file's name + returns an array of of channel ids which are pinned + + throw errors on pin logs with invalid pin data +*/ +Pins.calculateFromLog = function (pinFile, fileName) { + var ref = {}; + var handler = createLineHandler(ref, fileName); + + pinFile.split('\n').forEach(handler); + return Object.keys(ref.pins); }; // TODO refactor to include a streaming version for use in rpc.js as well + diff --git a/rpc.js b/rpc.js index 9943b0334..13f08f4e3 100644 --- a/rpc.js +++ b/rpc.js @@ -16,7 +16,7 @@ const Pinned = require('./scripts/pinned'); const Saferphore = require("saferphore"); const nThen = require("nthen"); const getFolderSize = require("get-folder-size"); - +const Pins = require("./lib/pins"); var RPC = module.exports; @@ -237,52 +237,21 @@ var loadUserPins = function (Env, publicKey, cb) { return cb(session.channels); } - // if channels aren't in memory. load them from disk - var pins = {}; - - var pin = function (channel) { - pins[channel] = true; - }; - - var unpin = function (channel) { - // TODO delete? - pins[channel] = false; - }; + var ref = {}; + var lineHandler = Pins.createLineHandler(ref, function (label, data) { + Log.error(label, { + log: publicKey, + data: data, + }); + }); - Env.pinStore.getMessages(publicKey, function (msg) { - // handle messages... - var parsed; - try { - parsed = JSON.parse(msg); - session.hasPinned = true; - - switch (parsed[0]) { - case 'PIN': - parsed[1].forEach(pin); - break; - case 'UNPIN': - parsed[1].forEach(unpin); - break; - case 'RESET': - // TODO just wipe out the object? - Object.keys(pins).forEach(unpin); - - if (parsed[1] && parsed[1].length) { - parsed[1].forEach(pin); - } - break; - default: - Log.warn('INVALID_STORED_MESSAGE', msg); - } - } catch (e) { - Log.warn('STORED_PARSE_ERROR', e); - } - }, function () { + // if channels aren't in memory. load them from disk + Env.pinStore.getMessages(publicKey, lineHandler, function () { // no more messages // only put this into the cache if it completes - session.channels = pins; - cb(pins); + session.channels = ref.pins; + cb(ref.pins); }); };