~caneypuggies/reformedchurcheslocator/couchapp-backbone

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);
                    }
                }
            }
        });
    });
})