## The Asynchronous Plumber Wes Mason [@1stvamp](http://twitter.com/1stvamp) [www.serverdensity.com](http://www.serverdensity.com/)
## Who? - @1stvamp (twitter/github) - Product Engineer at ServerDensity - I like Python and evented code
## The web is our API - Everything does HTTP - REST is *great* - let's do more of this - Almost everything can do HTTP *asynchronously*
## Our Internal Services - RESTful - Stateless - Mostly thinlayers - Common documented API - Callable from frontend
## Brave New (Async) World - Longpolling, WebSockets and Server Sent Events - UIs are **responsive** or GTFO - Libraries like socket.io make this pretty easy for devs
## Come Back To Me - Jobs running in parallel using task systems - **What we want**: async responses to the browser - **What happens**: Jobs complete and...die. \**sniff*\*
## Come Back To Me (cont.) - HTTP or WebSocket request kicks off a task - Task runs asynchronous to requests - Task completed and returns data... - ...how?
## Segway to Celery - **Great**: Takes care of distributing tasks to clusters - **Not so great**: can't do multiple pubsub
## Publish and subscribe - Need results back from Celery by account ID - Pubsub is ideal for this - Each account has multiple users - **What we want**: one task per account, same result to each user
## Many to many with pubsub - Redis let's you do this (but we don't know Redis) - In theory AMQP let's you do M2M pubsub (and Celery does AMQP by default)
## ...well, kind of >>> result = task.delay(foo) AsyncResult(id="some-unique-id") >>> result.get() ...
## Cue the haxx - Threads (urgh) - Polling MongoDB (we **do** know Mongo) - Using MongoDB as Celery backend and keeping results (hello race conditions!)
## You Had Me Hooked - The stack's just web APIs.. ..why not just use webhooks to return data? - They're async, just like handling our frontend requests - They can be tested the same way as our other APIs
## The Webhook Registry - Register/unregister callbacks by a given key (e.g. an account ID) - Web handler accepts data payloads via HTTP POST - Webhook URI persisted somewhere (e.g. MongoDB)
## Skyhoooks to reach the Tornado - Open source library with registry for Tornado - soon Gevent and Twisted. - Registers callbacks and handling of multiple instance URIs - Available now: [github.com/serverdensity/skyhooks](https://github.com/serverdensity/skyhooks)
## Meanwhile, back on the [server] farm - Tasks running somewhere, somehow - Data returning from one or more tasks - One or more `INSERT_SERVER_HERE` (e.g. Tornado) instances at one or more URIs awaiting data
## # import requests, import pymongo # setup collection etc. etc. hooks = webhook_collection.find({"account_id": id}) if data and len(data) > 0: for hook in hooks: requests.post(hook["url"], data) - **N.B.** `skyhooks` does this for you
## Is this the only way? - ZeroMQ? - Crossroads.io has bi-di-pubsub - MongoDB trailing cursors - Do you need it?
## sys.exit(0) - Code: [github.com/serverdensity](https://github.com/serverdensity) - Slides: [github.com/1stvamp/pycon-2012-talk](https://github.com/1stvamp/pycon-2012-talk) - Jonathan "Joff" Oliver: [about.me/joffie](http://about.me/joffie) - Grab me and say hi `:-)`