I've been using the "task"/"worker" a bit, and found that it's simple enough to put together, but the moving parts confuse me each time.
So here's a decorator class that allows you to decorate a handler method and "just do it".
This does assume that you have a worker attached to the application, and to a channel "worker" (or a custom name passed to the decorator). It's not obvious to me how to verify at decoration-time or execution-time that the task will actually be picked up by a worker. Any suggestions how to do that?
from functools import wraps
class async(object):
"""Decorator for an event handler, pushes this event execution into a worker pool"""
def __init__(self, *args, **kwargs):
self.pool = kwargs.get("pool", "worker")
if len(args) > 0:
raise Exception("Usage: @async() or @async(pool=<worker_channel_name>)")
def __call__(self, func):
"""Called at decoration time, with function"""
@wraps(func)
def decorated(itself, event, *args, **kwargs):
evt = task(func, itself, event, *args, **kwargs)
ret = yield itself.call(evt, self.pool)
result = ret.value
if isinstance(result, Exception):
raise result
yield result
return decorated