示例#1
0
    def worker(self, bus_client, after_shutdown: Callable = None):
        """


        A note about error handling in the worker thread:

        There are two scenarios in which the worker thread my encounter an error.

            1. The bus is being used as a client. A bus method is called by the client code,
               and this call raises an exception. This exception is propagated to the client
               code for it to deal with.1
            2. The bus is being used as a server and has various coroutines running at any one
               time. In this case, if a coroutine encounters an error then it should cause the
               lightbus server to exit.

        In response to either of these cases the bus needs to shut itself down. Therefore,
        the worker needs to keep on running for a while in order to handle the various shutdown tasks.

        In case 1 above, we assume the developer will take responsibility for closing the bus
        correctly when they are done with it.

        In case 2 above, the worker needs to signal the main lightbus run process to tell it to begin the
        shutdown procedure

        """
        logger.debug(f"Bus thread {self._thread.name} initialising")

        # Start a new event loop for this new thread
        asyncio.set_event_loop(asyncio.new_event_loop())

        self._call_queue = janus.Queue()
        self._worker_shutdown_queue = janus.Queue()

        async def worker_shutdown_monitor():
            await self._worker_shutdown_queue.async_q.get()
            asyncio.get_event_loop().stop()
            self._worker_shutdown_queue.async_q.task_done()

        shutdown_monitor_task = asyncio.ensure_future(worker_shutdown_monitor())
        shutdown_monitor_task.add_done_callback(make_exception_checker(bus_client, die=True))

        perform_calls_task = asyncio.ensure_future(self.perform_calls())
        perform_calls_task.add_done_callback(make_exception_checker(bus_client, die=True))

        self._ready.set()

        asyncio.get_event_loop().run_forever()

        logging.debug(f"Event loop stopped in bus worker thread {self._thread.name}. Closing down.")
        self._ready.clear()

        if after_shutdown:
            after_shutdown()

        logger.debug("Canceling worker tasks")
        block(cancel(perform_calls_task, shutdown_monitor_task))

        logger.debug("Closing the call queue")
        self._call_queue.close()
        block(self._call_queue.wait_closed())

        logger.debug("Closing the worker shutdown queue")
        self._worker_shutdown_queue.close()
        block(self._worker_shutdown_queue.wait_closed())

        logger.debug("Worker shutdown complete")
示例#2
0
 def close(self):
     logger.debug("Bus is closing")
     self._call_queue.sync_q.join()
     block(cancel(self._perform_calls_task))
示例#3
0
 def stop_server(self):
     block(cancel(self._shutdown_monitor_task))
     block(self._stop_server_inner())