import asyncio
import configparser
+import inspect
import logging
import os
import pakfire
class Backend(object):
version = __version__
+ # A list of any background tasks
+ __tasks = set()
+
def __init__(self, config_file=None):
# Read configuration file.
self.config = self.read_config(config_file)
# Delete the configuration file
os.unlink(t)
+ # Functions to run something in background
+
+ def run_task(self, callback, *args):
+ """
+ Runs the given coroutine in the background
+ """
+ # Create a new task
+ task = asyncio.create_task(callback(*args))
+
+ # Keep a reference to the task and remove it when the task has finished
+ self.__tasks.add(task)
+ task.add_done_callback(self.__tasks.discard)
+
+ return task
+
+ def run_periodic_task(self, delay, callback, *args):
+ """
+ Calls the given callback periodically in the background
+ """
+ self.run_task(self._periodic_task, delay, callback, *args)
+
+ async def _periodic_task(self, delay, callback, *args):
+ """
+ Helper function for run_periodic_task() that will call the given
+ callback regulary after the timer has expired.
+ """
+ log.debug("Periodic callback %r started" % callback)
+
+ while True:
+ # Wait a little moment
+ await asyncio.sleep(delay)
+
+ try:
+ ret = callback(*args)
+
+ # Await ret if callback is a coroutine
+ if inspect.isawaitable(ret):
+ await ret
+
+ except Exception as e:
+ log.error("Exception in periodic callback %r" % callback, exc_info=True)
+
# Commands
async def command(self, *args, krb5_auth=False, **kwargs):
self.backend = Backend()
# Launch any background jobs
- self._run_task(queue.dispatch_jobs, 5)
+ self.backend.run_periodic_task(5, queue.dispatch_jobs, self.backend)
logging.info("Successfully initialied application")
# Perform some initial tasks
- self._run_task(self.backend.builders.sync)
- self._run_task(self.backend.builders.autoscale)
-
- def _run_task(self, callback, t=None):
- """
- Runs the callback every t seconds in the background or once if t is None
- """
- # Pass backend to the function
- callback = functools.partial(callback, self.backend)
-
- # Create a periodic callback object
- if t:
- task = tornado.ioloop.PeriodicCallback(callback, t * 1000)
- task.start()
-
- else:
- ioloop = tornado.ioloop.IOLoop.current()
- ioloop.add_callback(callback)
+ self.backend.run_task(self.backend.builders.sync)
+ self.backend.run_task(self.backend.builders.autoscale)