One nice thing about Lua coroutines is that they are "stackful". You don't need to chain "yields" all the way up the call stack (like Python's "yield from") so its possible to create functions that work with both sync and async callbacks.
function mapList(xs, f)
local ys = {}
for i=1,#xs do
ys[i] = f(xs[i])
end
return ys
end
mapList({10, 20, 30}, function(x)
return db.fetch(x)
end)
In JS you can't use async functions inside of Array.prototype.map. You need to use a separate async-aware method from your favorite async library instead.I have used this idiom to great results in my project (https://github.com/raksoras/luaw). Basically, request:read() hooks up into libuv (node.js' excellent async IO library) event loop and then yields. Server is now free to run next coroutine. When socket underlying the first request is ready with data to read libuv event loop's callback gets fired and resumes original coroutine.
That's awesome. You've me hooked. For postgres database access, what library do you suggest? Also, I remember lua-nginx can also do non-blocking IO in blocking style code. (http://wiki.nginx.org/HttpLuaModule, http://openresty.org) How does luaw compared to that?
Right now it's just a HTTP server and REST framework. It's a very first release and I don't have any DB drivers for it yet- they would need to be non-blocking as you mentioned.
I have plans to write dbslayer like "access DB over REST" service as a companion to Luaw so that it can use any and all databases that have JDBC drivers available without having to write non-blocking driver specially for each new database. This kind of arrangement where DB connection pooling is abstracted out of application server itself has other advantages related to auto-scaling in cloud and red/black or "flip" code pushes at the cost of slightly more complex deployment.
All depends on how much spare time I actually get :(
With BabelJS, or the co modules (used with generators) you can get a very similar model...
app.use(function *(){
var db = yeild getDbConnection();
var data = db.query("procname", this.request.query.param);
this.body = JSON.stringify(data);
});
This of course assumes you have a db interface that uses Primises and are using koa for your web platform in a version of node that supports Generators, or are using something like BabelJS or traceur.
In db.fetch it uses the "yield" keyword that would tell Lua it is about to do an async operation it should wait till it finish before continue running Lua code, meanwhile run something else instead, making it non-blocking and you can run many of these Lua programs at once on a single thread, all of them concurrently.