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
|
// Use cradle to watch the database's changes and stream them in
// TODO: Could we use jquery.couch.js here instead of cradle, in order to use our
// CouchAppObject model here?
var child_process = require('./node_modules/child_process.js'),
util = require('util'),
vm = require('vm'),
fs = require('fs'),
config = require('./config'),
db = config.db,
changes_listeners_filename = '../changes_listeners_temp.js',
log = require('./lib').log;
//$ = require('jquery');
if (config.debug)
var longjohn = require('longjohn') // for printing long stacktraces
function write_new_changes_listener_file(doc){
// Write changes listeners to the temp file if it doesn't exist yet
if (fs.existsSync(changes_listeners_filename)){
var fs_copy = fs.readFileSync(changes_listeners_filename, 'utf8');
// Only write the new file to the filesystem if it is not the same as what is in the database
if (fs_copy != doc){
fs.writeFileSync(changes_listeners_filename, doc);
}
}else{
fs.writeFileSync(changes_listeners_filename, doc);
}
}
function start_child_process(){
db.get('_design/rcl', function(err, doc){
write_new_changes_listener_file(doc.changes_listeners);
});
// Spawn changes listener process
//var mode = 'spawn';
var mode = 'fork';
if (mode=='spawn'){
p = child_process.spawn(process.execPath, [changes_listeners_filename]);
// Log errors to stderr of this process (not the child process)
p.stderr.on("data", function (chunk) {util.error(chunk.toString());});
}else if (mode=='fork'){
p = child_process.fork(changes_listeners_filename);
}
p.on('error',function(err){
// TODO: Replace this with the domain example at http://nodejs.org/api/domain.html
console.log(err)
console.log(err.stack)
console.log('Killing child process')
p.kill()
// TODO: Could this cause a memory leak?
delete p;
p = start_child_process()
console.log('Killing child process')
})
return p;
}
// TODO: When the child process is started the first time, the CPU goes to 100%. When I save a file
// and the changes listener below restarts the child process, then the CPU goes back to normal usage.
p = start_child_process();
console.log('starting child process')
var it = 0;
// Only get changes after "update_seq"
db.get('', function(err,doc){
db.changes({since:doc.update_seq}).on('change', function (change) {
it++;
db.get(change.id, change.changes[0].rev, function(err, doc){
if (change.id && change.id.slice(0, '_design/'.length) === '_design/') {
// This is a change to the design document
// If the rcl design document changed, then reload the changes listeners.
// Get the new design doc
if (doc.changes) {
// take down the process with the old design doc
p.kill();
fs.unlinkSync(changes_listeners_filename);
// start up the process with the new design doc
write_new_changes_listener_file(doc.changes_listeners);
p = start_child_process();
}
} else {
// This is a change to a data document
// Feed the new doc into the changes listeners
if (doc) { // Don't handle docs that have been deleted
if (p.connected){
p.send(doc);
}
}
}
});
});
})
|