-
Notifications
You must be signed in to change notification settings - Fork 3
/
watcher.js
130 lines (101 loc) · 4.05 KB
/
watcher.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
'use strict';
var fs = require('fs');
var Client = require('node-rest-client').Client;
var client = new Client();
var dbFile = 'watcherDb.json';
// Functions for persistence
var watcherDatabase = {
read: function(dbFilePath) {
try {
var stringContent = fs.readFileSync(dbFilePath);
var watcherState = JSON.parse(stringContent);
return watcherState;
} catch (e) {
console.log('No db found, initializing to empty state');
return {};
}
},
save: function(watcherState, dbFilePath) {
console.log('Saving watchers to db');
var stringContent = JSON.stringify(watcherState);
fs.writeFileSync(dbFilePath, stringContent);
}
}
// Keys are stringified userId-questionId pairs
// Values are the last activity time
var watcher = watcherDatabase.read(dbFile);
// Save the watcher state on exit/interrups
process.on('SIGINT', function () { console.log('SIGINT'); process.exit(); });
process.on('SIGTERM', function () { console.log('SIGTERM'); process.exit(); });
process.on('exit', function() { watcherDatabase.save(watcher, dbFile) });
var url = 'https://api.stackexchange.com/2.2/';
var questionAnswerUrlAppend = '?site=stackoverflow';
// This is the frequency at which we check for updates on the watcher
var updateIntervalInMilliseconds = 300000;
function getLastActivityTime(questionId) {
var questionUrl = url + '/questions/' + questionId + questionAnswerUrlAppend;
console.log(questionUrl);
var lastActivityDate = 0;
// TODO: This call is not blocking!
// We need to use either futures/promises
client.get(questionUrl, function (data, response) {
if (!(data.items == null)) {
lastActivityDate = data.items[0].last_activity_date;
console.log("Last Activity Date - " + lastActivityDate);
}
else {
console.log("Unable to retrieve last activity date details for " + questionId);
}
});
return lastActivityDate;
}
function checkForUpdates(callback) {
console.log("Checking for updates");
console.log(watcher);
for(var toWatchObj in watcher) {
var currentTime = watcher[toWatchObj];
console.log(toWatchObj);
var questionId = toWatchObj.split(",")[1];
var userId = toWatchObj.split(",")[0];
console.log("Question id: " + questionId);
var newTime = getLastActivityTime(questionId);
console.log("Current known last activity time: " + currentTime);
if (newTime > currentTime){
console.log("There has been new activity on question " + questionId);
// We call callback first because we want the user to be notified first
// If we update the watcher, but the notification fails, the user will never know
// that the question was updated!
callback(userId, questionId);
watcher[questionId] = newTime;
}
}
}
module.exports = {
// For a given userId, get a list of all the questionIds that he/she is watching
getWatchList: function(userId){
console.log("Inside getWatchList");
var watchedQuestions = [];
for(var toWatchObj in watcher) {
console.log(toWatchObj);
var questionId = toWatchObj.split(",")[1];
var watchingUserId = toWatchObj.split(",")[0];
if (watchingUserId === userId){
watchedQuestions.push(questionId);
}
}
return watchedQuestions;
},
// Add a question id to the watchlist of a particular user
addWatcher: function(userId, questionId) {
console.log("Now watching for userId = " + userId + ", questionId = " + questionId);
watcher[[userId, questionId]] = getLastActivityTime(questionId);
},
// Start the watcher thread
// Intermittently check for updates on all watched questions
startWatcher: function (callback) {
console.log("Starting watcher");
setInterval(function() {
checkForUpdates(callback);
}, updateIntervalInMilliseconds);
}
};