Example #1
0
def loop(
    request,
    services,
    loop_debug,
    default_context,
    entrypoint_kwargs,
    thread_pool_size,
    thread_pool_executor,
    loop: asyncio.AbstractEventLoop,
    caplog: pytest.LogCaptureFixture,
):
    from aiomisc.context import get_context
    from aiomisc.entrypoint import entrypoint

    if LOG_LEVEL:
        LOG_LEVEL.set(logging.getLogger().getEffectiveLevel())

    pool = thread_pool_executor(thread_pool_size)
    loop.set_default_executor(pool)

    get_marker = request.node.get_closest_marker
    forbid_loop_getter_marker = get_marker("forbid_get_event_loop")
    catch_unhandled_marker = get_marker("catch_loop_exceptions")

    exceptions = list()
    if catch_unhandled_marker:
        loop.set_exception_handler(lambda l, c: exceptions.append(c))

    try:
        with entrypoint(*services, loop=loop, **entrypoint_kwargs):

            ctx = get_context(loop)

            for key, value in default_context.items():
                ctx[key] = value

            if forbid_loop_getter_marker:
                asyncio.get_event_loop.side_effect = partial(
                    pytest.fail,
                    "get_event_loop is forbidden",
                )

            yield loop

            if exceptions:
                logging.error(
                    "Unhandled exceptions found:\n\n\t%s",
                    "\n\t".join(("Message: {m}\n\t"
                                 "Future: {f}\n\t"
                                 "Exception: {e}").format(
                                     m=e["message"],
                                     f=repr(e.get("future")),
                                     e=repr(e.get("exception")),
                                 ) for e in exceptions),
                )
                pytest.fail("Unhandled exceptions found. See logs.")
    finally:
        asyncio.get_event_loop.side_effect = get_event_loop
        del loop
Example #2
0
async def executor(event_loop: asyncio.AbstractEventLoop):
    thread_pool = ThreadPoolExecutor(8, loop=event_loop)
    event_loop.set_default_executor(thread_pool)
    try:
        yield thread_pool
    finally:
        with suppress(Exception):
            thread_pool.shutdown(wait=True)

        event_loop.set_default_executor(None)
Example #3
0
def executor(loop: asyncio.AbstractEventLoop):
    thread_pool = aiomisc.ThreadPoolExecutor(8)
    loop.set_default_executor(thread_pool)
    try:
        yield thread_pool
    finally:
        with suppress(Exception):
            thread_pool.shutdown(wait=True)

        thread_pool.shutdown(wait=True)
Example #4
0
    def run(self, event_loop: AbstractEventLoop = None):
        # Configure the logging system
        if isinstance(self.logging_config, dict):
            logging.config.dictConfig(self.logging_config)
        elif self.logging_config:
            logging.basicConfig(level=logging.INFO)

        # Assign a new default executor with the given max worker thread limit
        event_loop = event_loop or asyncio.get_event_loop()
        event_loop.set_default_executor(ThreadPoolExecutor(self.max_threads))

        # Create the application context
        context = self.create_context()

        try:
            # Start all the components and run the loop until they've finished
            self.logger.info("Starting components")
            coroutines = (component.start(context) for component in self.components)
            coroutines = [coro for coro in coroutines if coro is not None]
            event_loop.run_until_complete(asyncio.gather(*coroutines))
            self.logger.info("All components started")

            # Run the application's custom startup code
            coro = self.start(context)
            if coro is not None:
                event_loop.run_until_complete(coro)

            # Run all the application context's start callbacks
            event_loop.run_until_complete(context.run_callbacks(ContextEventType.started))
            self.logger.info("Application started")
        except Exception as exc:
            self.logger.exception("Error during application startup")
            context.exception = exc
        else:
            # Finally, run the event loop until the process is terminated or Ctrl+C is pressed
            try:
                event_loop.run_forever()
            except (KeyboardInterrupt, SystemExit):
                pass

        event_loop.run_until_complete(context.run_callbacks(ContextEventType.finished))
        event_loop.close()
        self.logger.info("Application stopped")