New events and service calls now use a shared thread pool

This commit is contained in:
Paulus Schoutsen 2014-01-26 18:44:36 -08:00
parent 70d2506e01
commit 2758d81525
2 changed files with 151 additions and 57 deletions

View file

@ -1,5 +1,6 @@
""" Helper methods for various modules. """
import threading
import Queue
import datetime
import re
@ -53,3 +54,56 @@ def filter_entity_ids(entity_ids, domain_filter=None, strip_domain=False):
for entity_id in entity_ids if
not domain_filter or entity_id.startswith(domain_filter)
]
def repr_helper(inp):
""" Helps creating a more readable string representation of objects. """
if isinstance(inp, dict):
return ", ".join(
repr_helper(key)+"="+repr_helper(item) for key, item in inp.items()
)
elif isinstance(inp, list):
return '[' + ', '.join(inp) + ']'
elif isinstance(inp, datetime.datetime):
return datetime_to_str(inp)
else:
return str(inp)
# Reason why I decided to roll my own ThreadPool instead of using
# multiprocessing.dummy.pool or even better, use multiprocessing.pool and
# not be hurt by the GIL in the cpython interpreter:
# 1. The built in threadpool does not allow me to create custom workers and so
# I would have to wrap every listener that I passed into it with code to log
# the exceptions. Saving a reference to the logger in the worker seemed
# like a more sane thing to do.
# 2. Most event listeners are simple checks if attributes match. If the method
# that they will call takes a long time to complete it might be better to
# put that request in a seperate thread. This is for every component to
# decide on its own instead of enforcing it for everyone.
class ThreadPool(object):
""" A simple queue-based thread pool.
Will initiate it's workers using worker(queue).start() """
# pylint: disable=too-few-public-methods
def __init__(self, worker_count, job_handler):
queue = self.queue = Queue.Queue()
for _ in xrange(worker_count):
worker = threading.Thread(target=_threadpool_worker,
args=(queue, job_handler))
worker.daemon = True
worker.start()
def add_job(self, *args):
""" Add a job to be sent to the workers. """
self.queue.put(args)
def _threadpool_worker(queue, job_handler):
""" Provides the base functionality of a worker for the thread pool. """
while True:
job = queue.get()
job_handler(job)
queue.task_done()