diff --git a/app.js b/app.js index ba0b67d..ee82fab 100644 --- a/app.js +++ b/app.js @@ -26,7 +26,6 @@ var validator = require('validator'); var config = require("./lib/config.js"); var logger = require("./lib/logger.js"); var auth = require("./lib/auth.js"); -var history = require("./lib/history.js"); var response = require("./lib/response.js"); var models = require("./lib/models"); @@ -443,6 +442,7 @@ app.get('/logout', function (req, res) { req.logout(); res.redirect(config.serverurl + '/'); }); +var history = require("./lib/history.js"); //get history app.get('/history', history.historyGet); //post history @@ -608,7 +608,7 @@ function startListen() { // sync db then start listen models.sequelize.sync().then(function () { // check if realtime is ready - if (history.isReady() && realtime.isReady()) { + if (realtime.isReady()) { models.Revision.checkAllNotesRevision(function (err, notes) { if (err) throw new Error(err); if (!notes || notes.length <= 0) return startListen(); @@ -639,7 +639,7 @@ function handleTermSignals() { }, 0); }); var checkCleanTimer = setInterval(function () { - if (history.isReady() && realtime.isReady()) { + if (realtime.isReady()) { models.Revision.checkAllNotesRevision(function (err, notes) { if (err) return logger.error(err); if (!notes || notes.length <= 0) { diff --git a/lib/history.js b/lib/history.js index 2723422..e7fb308 100644 --- a/lib/history.js +++ b/lib/history.js @@ -1,7 +1,6 @@ //history //external modules var async = require('async'); -var moment = require('moment'); //core var config = require("./config.js"); @@ -14,45 +13,32 @@ var History = { historyGet: historyGet, historyPost: historyPost, historyDelete: historyDelete, - isReady: isReady, updateHistory: updateHistory }; -var caches = {}; -//update when the history is dirty -var updater = setInterval(function () { - var deleted = []; - async.each(Object.keys(caches), function (key, callback) { - var cache = caches[key]; - if (cache.isDirty) { - if (config.debug) logger.info("history updater found dirty history: " + key); - var history = parseHistoryToArray(cache.history); - cache.isDirty = false; - finishUpdateHistory(key, history, function (err, count) { - if (err) return callback(err, null); - if (!count) return callback(null, null); - cache.updateAt = Date.now(); - return callback(null, null); - }); - } else { - if (moment().isAfter(moment(cache.updateAt).add(5, 'minutes'))) { - deleted.push(key); - } - return callback(null, null); +function getHistory(userid, callback) { + models.User.findOne({ + where: { + id: userid } - }, function (err) { - if (err) return logger.error('history updater error', err); + }).then(function (user) { + if (!user) + return callback(null, null); + var history = {}; + if (user.history) + history = parseHistoryToObject(JSON.parse(user.history)); + if (config.debug) + logger.info('read history success: ' + user.id); + return callback(null, history); + }).catch(function (err) { + logger.error('read history failed: ' + err); + return callback(err, null); }); - // delete specified caches - for (var i = 0, l = deleted.length; i < l; i++) { - caches[deleted[i]].history = {}; - delete caches[deleted[i]]; - } -}, 1000); +} -function finishUpdateHistory(userid, history, callback) { +function setHistory(userid, history, callback) { models.User.update({ - history: JSON.stringify(history) + history: JSON.stringify(parseHistoryToArray(history)) }, { where: { id: userid @@ -60,72 +46,27 @@ function finishUpdateHistory(userid, history, callback) { }).then(function (count) { return callback(null, count); }).catch(function (err) { + logger.error('set history failed: ' + err); return callback(err, null); }); } -function isReady() { - var dirtyCount = 0; - async.each(Object.keys(caches), function (key, callback) { - if (caches[key].isDirty) dirtyCount++; - return callback(null, null); - }, function (err) { - if (err) return logger.error('history ready check error', err); - }); - return dirtyCount > 0 ? false : true; -} - -function getHistory(userid, callback) { - if (caches[userid]) { - return callback(null, caches[userid].history); - } else { - models.User.findOne({ - where: { - id: userid - } - }).then(function (user) { - if (!user) - return callback(null, null); - var history = []; - if (user.history) - history = JSON.parse(user.history); - if (config.debug) - logger.info('read history success: ' + user.id); - setHistory(userid, history); - return callback(null, history); - }).catch(function (err) { - logger.error('read history failed: ' + err); - return callback(err, null); - }); - } -} - -function setHistory(userid, history) { - if (Array.isArray(history)) history = parseHistoryToObject(history); - if (!caches[userid]) { - caches[userid] = { - history: {}, - isDirty: false, - updateAt: Date.now() - }; - } - caches[userid].history = history; -} - -function updateHistory(userid, noteId, document) { +function updateHistory(userid, noteId, document, time) { if (userid && noteId && typeof document !== 'undefined') { getHistory(userid, function (err, history) { if (err || !history) return; - if (!caches[userid].history[noteId]) { - caches[userid].history[noteId] = {}; + if (!history[noteId]) { + history[noteId] = {}; } - var noteHistory = caches[userid].history[noteId]; + var noteHistory = history[noteId]; var noteInfo = models.Note.parseNoteInfo(document); noteHistory.id = noteId; noteHistory.text = noteInfo.title; - noteHistory.time = moment().valueOf(); + noteHistory.time = time || Date.now(); noteHistory.tags = noteInfo.tags; - caches[userid].isDirty = true; + setHistory(userid, history, function (err, count) { + return; + }); }); } } @@ -175,9 +116,10 @@ function historyPost(req, res) { return response.errorBadRequest(res); } if (Array.isArray(history)) { - setHistory(req.user.id, history); - caches[req.user.id].isDirty = true; - res.end(); + setHistory(req.user.id, history, function (err, count) { + if (err) return response.errorInternalError(res); + res.end(); + }); } else { return response.errorBadRequest(res); } @@ -186,11 +128,13 @@ function historyPost(req, res) { getHistory(req.user.id, function (err, history) { if (err) return response.errorInternalError(res); if (!history) return response.errorNotFound(res); - if (!caches[req.user.id].history[noteId]) return response.errorNotFound(res); + if (!history[noteId]) return response.errorNotFound(res); if (req.body.pinned === 'true' || req.body.pinned === 'false') { - caches[req.user.id].history[noteId].pinned = (req.body.pinned === 'true'); - caches[req.user.id].isDirty = true; - res.end(); + history[noteId].pinned = (req.body.pinned === 'true'); + setHistory(req.user.id, history, function (err, count) { + if (err) return response.errorInternalError(res); + res.end(); + }); } else { return response.errorBadRequest(res); } @@ -205,16 +149,19 @@ function historyDelete(req, res) { if (req.isAuthenticated()) { var noteId = req.params.noteId; if (!noteId) { - setHistory(req.user.id, []); - caches[req.user.id].isDirty = true; - res.end(); + setHistory(req.user.id, [], function (err, count) { + if (err) return response.errorInternalError(res); + res.end(); + }); } else { getHistory(req.user.id, function (err, history) { if (err) return response.errorInternalError(res); if (!history) return response.errorNotFound(res); - delete caches[req.user.id].history[noteId]; - caches[req.user.id].isDirty = true; - res.end(); + delete history[noteId]; + setHistory(req.user.id, history, function (err, count) { + if (err) return response.errorInternalError(res); + res.end(); + }); }); } } else { diff --git a/lib/realtime.js b/lib/realtime.js index fadea4f..def8f21 100644 --- a/lib/realtime.js +++ b/lib/realtime.js @@ -122,6 +122,12 @@ function updateNote(note, callback) { } }).then(function (_note) { if (!_note) return callback(null, null); + // update user note history + var tempUsers = Object.assign({}, note.tempUsers); + note.tempUsers = {}; + Object.keys(tempUsers).forEach(function (key) { + updateHistory(key, note, tempUsers[key]); + }); if (note.lastchangeuser) { if (_note.lastchangeuserId != note.lastchangeuser) { models.User.findOne({ @@ -405,10 +411,7 @@ function finishConnection(socket, note, user) { note.server.setColor(socket, user.color); // update user note history - setTimeout(function () { - var noteId = note.alias ? note.alias : LZString.compressToBase64(note.id); - if (note.server) history.updateHistory(user.userid, noteId, note.server.document); - }, 0); + updateHistory(user.userid, note); emitOnlineUsers(socket); emitRefresh(socket); @@ -497,6 +500,7 @@ function startConnection(socket) { lastchangeuserprofile: lastchangeuserprofile, socks: [], users: {}, + tempUsers: {}, createtime: moment(createtime).valueOf(), updatetime: moment(updatetime).valueOf(), server: server, @@ -687,15 +691,14 @@ function operationCallback(socket, operation) { return logger.error('operation callback failed: ' + err); }); } - // update user note history - setTimeout(function() { - var noteId = note.alias ? note.alias : LZString.compressToBase64(note.id); - if (note.server) history.updateHistory(userId, noteId, note.server.document); - }, 0); - + note.tempUsers[userId] = Date.now(); } // save authorship note.authorship = models.Note.updateAuthorshipByOperation(operation, userId, note.authorship); + +function updateHistory(userId, note, time) { + var noteId = note.alias ? note.alias : LZString.compressToBase64(note.id); + if (note.server) history.updateHistory(userId, noteId, note.server.document, time); } function connection(socket) { @@ -925,4 +928,4 @@ function connection(socket) { }); } -module.exports = realtime; +module.exports = realtime; \ No newline at end of file