asyncio.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import sys
  2. from apscheduler.executors.base import BaseExecutor, run_coroutine_job, run_job
  3. from apscheduler.util import iscoroutinefunction_partial
  4. class AsyncIOExecutor(BaseExecutor):
  5. """
  6. Runs jobs in the default executor of the event loop.
  7. If the job function is a native coroutine function, it is scheduled to be run directly in the
  8. event loop as soon as possible. All other functions are run in the event loop's default
  9. executor which is usually a thread pool.
  10. Plugin alias: ``asyncio``
  11. """
  12. def start(self, scheduler, alias):
  13. super().start(scheduler, alias)
  14. self._eventloop = scheduler._eventloop
  15. self._pending_futures = set()
  16. def shutdown(self, wait=True):
  17. # There is no way to honor wait=True without converting this method into a coroutine method
  18. for f in self._pending_futures:
  19. if not f.done():
  20. f.cancel()
  21. self._pending_futures.clear()
  22. def _do_submit_job(self, job, run_times):
  23. def callback(f):
  24. self._pending_futures.discard(f)
  25. try:
  26. events = f.result()
  27. except BaseException:
  28. self._run_job_error(job.id, *sys.exc_info()[1:])
  29. else:
  30. self._run_job_success(job.id, events)
  31. if iscoroutinefunction_partial(job.func):
  32. coro = run_coroutine_job(
  33. job, job._jobstore_alias, run_times, self._logger.name
  34. )
  35. f = self._eventloop.create_task(coro)
  36. else:
  37. f = self._eventloop.run_in_executor(
  38. None, run_job, job, job._jobstore_alias, run_times, self._logger.name
  39. )
  40. f.add_done_callback(callback)
  41. self._pending_futures.add(f)