Skip to content

Commit 92ad67b

Browse files
committed
Update to remove history cache to lower application coupling
1 parent a261c8e commit 92ad67b

3 files changed

Lines changed: 64 additions & 114 deletions

File tree

app.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ var validator = require('validator');
2626
var config = require("./lib/config.js");
2727
var logger = require("./lib/logger.js");
2828
var auth = require("./lib/auth.js");
29-
var history = require("./lib/history.js");
3029
var response = require("./lib/response.js");
3130
var models = require("./lib/models");
3231

@@ -443,6 +442,7 @@ app.get('/logout', function (req, res) {
443442
req.logout();
444443
res.redirect(config.serverurl + '/');
445444
});
445+
var history = require("./lib/history.js");
446446
//get history
447447
app.get('/history', history.historyGet);
448448
//post history
@@ -608,7 +608,7 @@ function startListen() {
608608
// sync db then start listen
609609
models.sequelize.sync().then(function () {
610610
// check if realtime is ready
611-
if (history.isReady() && realtime.isReady()) {
611+
if (realtime.isReady()) {
612612
models.Revision.checkAllNotesRevision(function (err, notes) {
613613
if (err) throw new Error(err);
614614
if (!notes || notes.length <= 0) return startListen();
@@ -639,7 +639,7 @@ function handleTermSignals() {
639639
}, 0);
640640
});
641641
var checkCleanTimer = setInterval(function () {
642-
if (history.isReady() && realtime.isReady()) {
642+
if (realtime.isReady()) {
643643
models.Revision.checkAllNotesRevision(function (err, notes) {
644644
if (err) return logger.error(err);
645645
if (!notes || notes.length <= 0) {

lib/history.js

Lines changed: 47 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//history
22
//external modules
33
var async = require('async');
4-
var moment = require('moment');
54

65
//core
76
var config = require("./config.js");
@@ -14,118 +13,60 @@ var History = {
1413
historyGet: historyGet,
1514
historyPost: historyPost,
1615
historyDelete: historyDelete,
17-
isReady: isReady,
1816
updateHistory: updateHistory
1917
};
2018

21-
var caches = {};
22-
//update when the history is dirty
23-
var updater = setInterval(function () {
24-
var deleted = [];
25-
async.each(Object.keys(caches), function (key, callback) {
26-
var cache = caches[key];
27-
if (cache.isDirty) {
28-
if (config.debug) logger.info("history updater found dirty history: " + key);
29-
var history = parseHistoryToArray(cache.history);
30-
cache.isDirty = false;
31-
finishUpdateHistory(key, history, function (err, count) {
32-
if (err) return callback(err, null);
33-
if (!count) return callback(null, null);
34-
cache.updateAt = Date.now();
35-
return callback(null, null);
36-
});
37-
} else {
38-
if (moment().isAfter(moment(cache.updateAt).add(5, 'minutes'))) {
39-
deleted.push(key);
40-
}
41-
return callback(null, null);
19+
function getHistory(userid, callback) {
20+
models.User.findOne({
21+
where: {
22+
id: userid
4223
}
43-
}, function (err) {
44-
if (err) return logger.error('history updater error', err);
24+
}).then(function (user) {
25+
if (!user)
26+
return callback(null, null);
27+
var history = {};
28+
if (user.history)
29+
history = parseHistoryToObject(JSON.parse(user.history));
30+
if (config.debug)
31+
logger.info('read history success: ' + user.id);
32+
return callback(null, history);
33+
}).catch(function (err) {
34+
logger.error('read history failed: ' + err);
35+
return callback(err, null);
4536
});
46-
// delete specified caches
47-
for (var i = 0, l = deleted.length; i < l; i++) {
48-
caches[deleted[i]].history = {};
49-
delete caches[deleted[i]];
50-
}
51-
}, 1000);
37+
}
5238

53-
function finishUpdateHistory(userid, history, callback) {
39+
function setHistory(userid, history, callback) {
5440
models.User.update({
55-
history: JSON.stringify(history)
41+
history: JSON.stringify(parseHistoryToArray(history))
5642
}, {
5743
where: {
5844
id: userid
5945
}
6046
}).then(function (count) {
6147
return callback(null, count);
6248
}).catch(function (err) {
49+
logger.error('set history failed: ' + err);
6350
return callback(err, null);
6451
});
6552
}
6653

67-
function isReady() {
68-
var dirtyCount = 0;
69-
async.each(Object.keys(caches), function (key, callback) {
70-
if (caches[key].isDirty) dirtyCount++;
71-
return callback(null, null);
72-
}, function (err) {
73-
if (err) return logger.error('history ready check error', err);
74-
});
75-
return dirtyCount > 0 ? false : true;
76-
}
77-
78-
function getHistory(userid, callback) {
79-
if (caches[userid]) {
80-
return callback(null, caches[userid].history);
81-
} else {
82-
models.User.findOne({
83-
where: {
84-
id: userid
85-
}
86-
}).then(function (user) {
87-
if (!user)
88-
return callback(null, null);
89-
var history = [];
90-
if (user.history)
91-
history = JSON.parse(user.history);
92-
if (config.debug)
93-
logger.info('read history success: ' + user.id);
94-
setHistory(userid, history);
95-
return callback(null, history);
96-
}).catch(function (err) {
97-
logger.error('read history failed: ' + err);
98-
return callback(err, null);
99-
});
100-
}
101-
}
102-
103-
function setHistory(userid, history) {
104-
if (Array.isArray(history)) history = parseHistoryToObject(history);
105-
if (!caches[userid]) {
106-
caches[userid] = {
107-
history: {},
108-
isDirty: false,
109-
updateAt: Date.now()
110-
};
111-
}
112-
caches[userid].history = history;
113-
}
114-
115-
function updateHistory(userid, noteId, document) {
54+
function updateHistory(userid, noteId, document, time) {
11655
if (userid && noteId && typeof document !== 'undefined') {
11756
getHistory(userid, function (err, history) {
11857
if (err || !history) return;
119-
if (!caches[userid].history[noteId]) {
120-
caches[userid].history[noteId] = {};
58+
if (!history[noteId]) {
59+
history[noteId] = {};
12160
}
122-
var noteHistory = caches[userid].history[noteId];
61+
var noteHistory = history[noteId];
12362
var noteInfo = models.Note.parseNoteInfo(document);
12463
noteHistory.id = noteId;
12564
noteHistory.text = noteInfo.title;
126-
noteHistory.time = moment().valueOf();
65+
noteHistory.time = time || Date.now();
12766
noteHistory.tags = noteInfo.tags;
128-
caches[userid].isDirty = true;
67+
setHistory(userid, history, function (err, count) {
68+
return;
69+
});
12970
});
13071
}
13172
}
@@ -175,9 +116,10 @@ function historyPost(req, res) {
175116
return response.errorBadRequest(res);
176117
}
177118
if (Array.isArray(history)) {
178-
setHistory(req.user.id, history);
179-
caches[req.user.id].isDirty = true;
180-
res.end();
119+
setHistory(req.user.id, history, function (err, count) {
120+
if (err) return response.errorInternalError(res);
121+
res.end();
122+
});
181123
} else {
182124
return response.errorBadRequest(res);
183125
}
@@ -186,11 +128,13 @@ function historyPost(req, res) {
186128
getHistory(req.user.id, function (err, history) {
187129
if (err) return response.errorInternalError(res);
188130
if (!history) return response.errorNotFound(res);
189-
if (!caches[req.user.id].history[noteId]) return response.errorNotFound(res);
131+
if (!history[noteId]) return response.errorNotFound(res);
190132
if (req.body.pinned === 'true' || req.body.pinned === 'false') {
191-
caches[req.user.id].history[noteId].pinned = (req.body.pinned === 'true');
192-
caches[req.user.id].isDirty = true;
193-
res.end();
133+
history[noteId].pinned = (req.body.pinned === 'true');
134+
setHistory(req.user.id, history, function (err, count) {
135+
if (err) return response.errorInternalError(res);
136+
res.end();
137+
});
194138
} else {
195139
return response.errorBadRequest(res);
196140
}
@@ -205,16 +149,19 @@ function historyDelete(req, res) {
205149
if (req.isAuthenticated()) {
206150
var noteId = req.params.noteId;
207151
if (!noteId) {
208-
setHistory(req.user.id, []);
209-
caches[req.user.id].isDirty = true;
210-
res.end();
152+
setHistory(req.user.id, [], function (err, count) {
153+
if (err) return response.errorInternalError(res);
154+
res.end();
155+
});
211156
} else {
212157
getHistory(req.user.id, function (err, history) {
213158
if (err) return response.errorInternalError(res);
214159
if (!history) return response.errorNotFound(res);
215-
delete caches[req.user.id].history[noteId];
216-
caches[req.user.id].isDirty = true;
217-
res.end();
160+
delete history[noteId];
161+
setHistory(req.user.id, history, function (err, count) {
162+
if (err) return response.errorInternalError(res);
163+
res.end();
164+
});
218165
});
219166
}
220167
} else {

lib/realtime.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ function updateNote(note, callback) {
122122
}
123123
}).then(function (_note) {
124124
if (!_note) return callback(null, null);
125+
// update user note history
126+
var tempUsers = Object.assign({}, note.tempUsers);
127+
note.tempUsers = {};
128+
Object.keys(tempUsers).forEach(function (key) {
129+
updateHistory(key, note, tempUsers[key]);
130+
});
125131
if (note.lastchangeuser) {
126132
if (_note.lastchangeuserId != note.lastchangeuser) {
127133
models.User.findOne({
@@ -405,10 +411,7 @@ function finishConnection(socket, note, user) {
405411
note.server.setColor(socket, user.color);
406412

407413
// update user note history
408-
setTimeout(function () {
409-
var noteId = note.alias ? note.alias : LZString.compressToBase64(note.id);
410-
if (note.server) history.updateHistory(user.userid, noteId, note.server.document);
411-
}, 0);
414+
updateHistory(user.userid, note);
412415

413416
emitOnlineUsers(socket);
414417
emitRefresh(socket);
@@ -497,6 +500,7 @@ function startConnection(socket) {
497500
lastchangeuserprofile: lastchangeuserprofile,
498501
socks: [],
499502
users: {},
503+
tempUsers: {},
500504
createtime: moment(createtime).valueOf(),
501505
updatetime: moment(updatetime).valueOf(),
502506
server: server,
@@ -687,15 +691,14 @@ function operationCallback(socket, operation) {
687691
return logger.error('operation callback failed: ' + err);
688692
});
689693
}
690-
// update user note history
691-
setTimeout(function() {
692-
var noteId = note.alias ? note.alias : LZString.compressToBase64(note.id);
693-
if (note.server) history.updateHistory(userId, noteId, note.server.document);
694-
}, 0);
695-
694+
note.tempUsers[userId] = Date.now();
696695
}
697696
// save authorship
698697
note.authorship = models.Note.updateAuthorshipByOperation(operation, userId, note.authorship);
698+
699+
function updateHistory(userId, note, time) {
700+
var noteId = note.alias ? note.alias : LZString.compressToBase64(note.id);
701+
if (note.server) history.updateHistory(userId, noteId, note.server.document, time);
699702
}
700703

701704
function connection(socket) {
@@ -925,4 +928,4 @@ function connection(socket) {
925928
});
926929
}
927930

928-
module.exports = realtime;
931+
module.exports = realtime;

0 commit comments

Comments
 (0)