This engine plugin allows you to run tasks in response to a request without tying up the request thread.
import Queue import threading class BackgroundTaskQueue(SimplePlugin): thread = None def __init__(self, bus, qsize=100, qwait=2, safe_stop=True): SimplePlugin.__init__(self, bus) self.q = Queue.Queue(qsize) self.qwait = qwait self.safe_stop = safe_stop def start(self): self.running = True if not self.thread: self.thread = threading.Thread(target=self.run) self.thread.start() def stop(self): if self.safe_stop: self.running = "draining" else: self.running = False if self.thread: self.thread.join() self.thread = None self.running = False def run(self): while self.running: try: try: func, args, kwargs = self.q.get(block=True, timeout=self.qwait) except Queue.Empty: if self.running == "draining": return continue else: func(*args, **kwargs) if hasattr(self.q, 'task_done'): self.q.task_done() except: self.bus.log("Error in BackgroundTaskQueue %r." % self, level=40, traceback=True) def put(self, func, *args, **kwargs): """Schedule the given func to be run.""" self.q.put((func, args, kwargs))
Use it like this:
import cherrypy from complicated_logging import log bgtask = BackgroundTaskQueue(cherrypy.engine) bgtask.subscribe() class Root(object): def index(self): bgtask.put(log, "index was called", ip=cherrypy.request.remote.ip)) return "Hello, world!" index.exposed = True
Another interesting feature for tasks: [IsClientConnected]

