tornado.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. from __future__ import absolute_import
  2. import sys
  3. from concurrent.futures import ThreadPoolExecutor
  4. from tornado.gen import convert_yielded
  5. from apscheduler.executors.base import BaseExecutor, run_job
  6. try:
  7. from apscheduler.executors.base_py3 import run_coroutine_job
  8. from apscheduler.util import iscoroutinefunction_partial
  9. except ImportError:
  10. def iscoroutinefunction_partial(func):
  11. return False
  12. class TornadoExecutor(BaseExecutor):
  13. """
  14. Runs jobs either in a thread pool or directly on the I/O loop.
  15. If the job function is a native coroutine function, it is scheduled to be run directly in the
  16. I/O loop as soon as possible. All other functions are run in a thread pool.
  17. Plugin alias: ``tornado``
  18. :param int max_workers: maximum number of worker threads in the thread pool
  19. """
  20. def __init__(self, max_workers=10):
  21. super(TornadoExecutor, self).__init__()
  22. self.executor = ThreadPoolExecutor(max_workers)
  23. def start(self, scheduler, alias):
  24. super(TornadoExecutor, self).start(scheduler, alias)
  25. self._ioloop = scheduler._ioloop
  26. def _do_submit_job(self, job, run_times):
  27. def callback(f):
  28. try:
  29. events = f.result()
  30. except BaseException:
  31. self._run_job_error(job.id, *sys.exc_info()[1:])
  32. else:
  33. self._run_job_success(job.id, events)
  34. if iscoroutinefunction_partial(job.func):
  35. f = run_coroutine_job(job, job._jobstore_alias, run_times, self._logger.name)
  36. else:
  37. f = self.executor.submit(run_job, job, job._jobstore_alias, run_times,
  38. self._logger.name)
  39. f = convert_yielded(f)
  40. f.add_done_callback(callback)