Call/CC: async with synchronous semantics
Created
March 11, 2011 19:13
-
-
Save weaver/866406 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.packages | |
*.pyc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Express = require('express'), | |
PG = require('pg'), | |
app = Express.createServer(); | |
app.get('/favicon.ico', function(req, res) { | |
res.send(404); | |
}); | |
app.get('/:message?', function(req, res) { | |
var message = req.param('message'), | |
client; | |
PG.connect('tcp://root:@localhost/callcc', function(err, _client) { | |
if (err) | |
fail(err); | |
else { | |
client = _client.on('error', fail); | |
if (!message) | |
showLog(); | |
else | |
client | |
.query('INSERT INTO log (message) VALUES ($1)', [message]) | |
.on('end', showLog); | |
} | |
}); | |
function fail(err) { | |
res.send((err.stack || err).toString(), 500); | |
} | |
function showLog() { | |
var results = []; | |
client | |
.query('SELECT stamp, message FROM log ORDER BY stamp DESC LIMIT 100') | |
.on('row', function(row) { | |
results.push('[' + row.stamp + '] ' + row.message); | |
}) | |
.on('end', function() { | |
res.end("<pre>" + results.join("\n") + "</pre>"); | |
}); | |
} | |
}); | |
app.listen(3000); | |
console.log('Listening on port 3000.'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import web, psycopg2 | |
## Routes ## | |
urls = ( | |
'/favicon.ico', 'favicon', | |
'/(.*)', 'log' | |
) | |
class log: | |
def GET(self, message): | |
conn = psycopg2.connect("dbname=callcc user=root") | |
cur = conn.cursor() | |
if message: | |
cur.execute("INSERT INTO log (message) VALUES (%s)", [message]) | |
conn.commit() | |
cur.execute("SELECT stamp, message FROM log ORDER BY stamp DESC LIMIT 100") | |
result = "<pre>%s</pre>" % "\n".join('[%s] %s' % r for r in cur) | |
cur.close() | |
conn.close() | |
return result | |
class favicon: | |
def GET(self): | |
raise web.NotFound() | |
## Server | |
app = web.application(urls, globals()) | |
if __name__ == '__main__': | |
app.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/csi -script | |
;; ## Main Program ## | |
(define (main message) | |
(let ((client #f)) | |
(define (fail err) | |
(error err)) | |
(define (connected conn) | |
(set! client conn) | |
(insert conn message showLog)) | |
(define (showLog err) | |
(if err | |
(fail err) | |
(select-all | |
client | |
(lambda (err all) | |
(if err | |
(fail err) | |
(for-each (lambda (entry) | |
(display entry) | |
(newline)) | |
all)))))) | |
(open-database | |
(lambda (err conn) | |
(if err | |
(fail err) | |
(connected conn)))) | |
)) | |
;; Fake Database | |
(define (open-database next) | |
(next #f (cons 'database (list "alpha" "beta")))) | |
(define (insert db entry next) | |
(set-cdr! db (append (cdr db) (list entry))) | |
(next #f)) | |
(define (select-all db next) | |
(next #f (cdr db))) | |
;; Run it | |
(apply main (cdddr (argv))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/csi -script | |
;; ## Main Program ## | |
(define (main message) | |
(let ((client (open-database))) | |
(insert client message) | |
(for-each | |
(lambda (entry) | |
(display entry) | |
(newline)) | |
(select-all client)))) | |
;; Async Interface | |
(define (open-database) | |
(capture | |
(lambda (next) | |
(%open-database next)))) | |
(define (insert db entry) | |
(capture | |
(lambda (next) | |
(%insert db entry next)))) | |
(define (select-all db) | |
(capture | |
(lambda (next) | |
(%select-all db next)))) | |
(define (capture with-next) | |
(call/cc | |
(lambda (next) | |
(with-next (maybe next))))) | |
(define (maybe k) | |
(lambda (err . success) | |
(if err | |
(error err) | |
(apply k success)))) | |
;; Fake Database | |
(define (%open-database next) | |
(next #f (cons 'database (list "alpha" "beta")))) | |
(define (%insert db entry next) | |
(set-cdr! db (append (cdr db) (list entry))) | |
(next #f #:void)) | |
(define (%select-all db next) | |
(next #f (cdr db))) | |
;; Run it | |
(apply main (cdddr (argv))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "demo", | |
"version": "0.1.0", | |
"dependencies": { | |
"express": "1.0.7", | |
"connect": "0.5.7" | |
}, | |
"mappings": { | |
"pg": "https://github.com/brianc/node-postgres/zipball/v0.2.5" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment