Skip to content

Instantly share code, notes, and snippets.

@seanhess
Created March 16, 2011 00:08
Show Gist options
  • Save seanhess/871772 to your computer and use it in GitHub Desktop.
Save seanhess/871772 to your computer and use it in GitHub Desktop.
uses step
Showcard.prototype.ensureHasUrls = function(cb) {
// If they have urls in the corresponding meta record,
// then add them. Otherwise, grab them from google and save
// the meta object for later.
// For now, lazily aggregate the urls. Never do this automatically when finding a showcard
// it needs to be clear when you are joining/proxying data, and callers need control
// Ignore google API Abuse errors so it can still finish
// if Google limits us.
// We store them on meta.showcards because we don't want them to get wiped out
// between imports.
// EXPERIMENT: (sean) I'm experimenting with flow control here, using Step.
// it lets you describe what you're doing. With a sort of inline comment
// It automatically handles if (err) return cb(err), as well as flattens
// asynchronous stuff so you can lay it out in order.
// If an error occurs, it will tell you which step you were on.
// We could add a log that dumps out what step you're on too.
// Let me know what you think.
var self = this
var step = new Step(cb)
step('look in meta.showcards for the urls', function(done) {
meta.findOne({_id: self.showcardId()}, done)
})
step('if we dont find one then go get it', function(done, info) {
if (info) return done(null, info.wikipediaUrl, info.imdbUrl, false)
var step = new Step(done)
step('get wikipedia url', function(done, info) {
google.wikipediaUrl(self.title(), function(err, wikipediaUrl) {
if (err && !err.message.match(/Abuse/)) return done(err)
done(null, wikipediaUrl)
})
})
step('get imdb url', function(done, wikipediaUrl) {
google.imdbUrl(self.title(), function(err, imdbUrl) {
if (err && !err.message.match(/Abuse/)) return cb(err)
done(null, wikipediaUrl, imdbUrl)
})
})
step('cache the urls to meta.showcards', function(done, wikipediaUrl, imdbUrl) {
if (!wikipediaUrl || !imdbUrl) return done()
meta.save({_id: self.showcardId(), wikipediaUrl: wikipediaUrl, imdbUrl: imdbUrl}, function(err) {
done(err, wikipediaUrl, imdbUrl, true)
})
})
})
step('set urls on showcard and finish', function(done, wikipediaUrl, imdbUrl, wasGenerated) {
self.wikipediaUrl(wikipediaUrl)
self.imdbUrl(imdbUrl)
done(null, wasGenerated)
})
})
Showcard.prototype.ensureHasUrls = function(cb) {
// If they have urls in the corresponding meta record,
// then add them. Otherwise, grab them from google and save
// the meta object for later.
// For now, lazily aggregate the urls. Never do this automatically when finding a showcard
// it needs to be clear when you are joining/proxying data, and callers need control
// Ignore google API Abuse errors so it can still finish
// if Google limits us.
// We store them on meta.showcards because we don't want them to get wiped out
// between imports.
function setUrlsAndFinish(wikipediaUrl, imdbUrl, wasGenerated) {
self.wikipediaUrl(wikipediaUrl)
self.imdbUrl(imdbUrl)
cb(null, wasGenerated)
}
function saveUrls(wikipediaUrl, imdbUrl, innerCb) {
if (wikipediaUrl && imdbUrl) {
meta.save({_id: self.showcardId(), wikipediaUrl: wikipediaUrl, imdbUrl: imdbUrl}, function(err) {
innerCb(err)
})
}
else {
innerCb()
}
}
meta.findOne({_id: self.showcardId()}, function(err, info) {
if (err) return cb(err)
if (info) return setUrlsAndFinish(info.wikipediaUrl, info.imdbUrl, false)
google.wikipediaUrl(self.title(), function(err, wikipediaUrl) {
if (err && !err.message.match(/Abuse/)) return cb(err)
google.imdbUrl(self.title(), function(err, imdbUrl) {
if (err && !err.message.match(/Abuse/)) return cb(err)
saveUrls(wikipediaUrl, imdbUrl, function(err) {
if (err) return cb(err)
setUrlsAndFinish(wikipediaUrl, imdbUrl, true)
})
})
})
})
}
module.exports = function Step(cb) {
// generates a "step" function, which executes stuff in sequence
// see testStep. Used for flow control.
var actions = []
var action = null
function step(description, work) {
actions.push({description: description, work: work})
process.nextTick(function() {
start()
})
}
function start(args) {
if (action) return
action = actions.shift()
args = args || []
args = [done].concat(args)
action.work.apply(null, args)
}
function handleError(err) {
err.message = "Step '" + action.description + "': " + err.message
return cb(err)
}
function done(err) {
if (err) return handleError(err)
var args = Array.prototype.slice.call(arguments, 1)
if (actions.length == 0) return cb.apply(null, arguments)
action = null
start(args)
}
return step
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment