I'm writing a batch process to read an RSS feed, and store the contents in MongoDB via Mongoose. I would run the script, and it would process the contents just fine... but the script wouldn't return to the console. My hypothesis was that my database connection was still open, and that's why I it wasn't returning.
I couldn't just track when my parsing was complete, because I still might have some mongoose save operations going on.
So, I wrote a function to track my open database connections, and the status of my RSS parsing. But my code ended up being heinously verbose. I'm wondering if there is a better model/pattern for doing something like this.
var FeedParser = require('feedparser')
, mongoose = require('mongoose');
var TEST_RSS_URL = "./test/data/20120303-seattle.rss";
var OPEN_DB_CONNECTIONS = 0;
var PARSING_DONE = false;
/*
* Keeps track of open database connections, and closes the connection when done
*/
function track_and_close_database(mode) {
switch(mode)
{
case 'open':
OPEN_DB_CONNECTIONS++;
break;
case 'close':
OPEN_DB_CONNECTIONS--;
if (0 == OPEN_DB_CONNECTIONS && PARSING_DONE) conn.close();
break;
case 'parseStart':
PARSING_DONE = false;
break;
case 'parseEnd':
PARSING_DONE = true;
if (0 == OPEN_DB_CONNECTIONS && PARSING_DONE) conn.close();
break;
}
}
function parse_stuff(stuff) {
// do some stuff
setTimeout(console.log("parsed some stuff",20));
}
function main() {
parser = new FeedParser();
parser.on('article', function(article) {
track_and_close_database('open');
// check to see if we already have this listing
stuff_model = conn.model('stuff');
stuff = stuff_model.findOne({'href': article.link}, function (error, doc) {
if (error) {
track_and_close_database('close');
return;
}
// this one doesn't exist yet, parse and save
if (null == doc) {
listing = parse_stuff(article);
// if listing is valid, save it!
if (null != listing) {
listing.save(function (error) { track_and_close_database('close') });
}
// parsing failed
else track_and_close_database('close');
}
// nothing to do, already in the database
else track_and_close_database('close');
});
});
// Completed parsing the RSS file
parser.on('end', function(article) {
track_and_close_database('parseEnd');
});
track_and_close_database('parseStart')
parser.parseFile(TEST_RSS_URL);
}
// run this thing
main();