Sanic: No non-blocking way to start the server in the same thread/loop

Created on 7 Jan 2017  路  14Comments  路  Source: sanic-org/sanic

Currently, there is no non-blocking way to start the server in the same thread/loop. This could possibly be achieved by having Sanic.run and subsequent funtions as a coroutine. Or having another function for running with async (e.g. Sanic.run_async)

idea discussion

Most helpful comment

@seemethere In my application, there are two listening coroutines, one for Telegram and one for Sanic. Having Sanic do anything but run in the current event loop makes it very difficult to manage the async flow of the program.

Ideally, there may be many listening coroutines, all using the same loop and sharing information and if any one of them has priority or more 'centric'-ness than the other it is likely to cause problems. E.g., what if another library decided to operate the same way as Sanic. That would mean somehow chaining them together in a way that's (hopefully) mutually compatible, possibly breaking one or the other, etc.. If Sanic works like other async libraries (e.g. coroutines throughout the whole library, not assuming sole ownership of the loop, etc.) then these problems are avoided.

However, if the aim of Sanic is to be a web server first, with features added to Sanic only (rather than adding Sanic as a feature to other applications), this should be reflected in documentation. This is a possible solution, although it would be a shame not to be able to use this library since it fulfils so many of the other criteria for my project.

All 14 comments

What's the use-case?

In my case, there is a telegram bot (https://telegram.org/) running asynchronously, and it would be helpful for the api to have access to the current state of the bot. At the moment, I run sanic in a different process which makes passing variables tricky (when it needn't be if it were running in the same asyncio/uvloop loop as the telegram bot).

I couldn't agree more. Currently we have non-blocking adapter bodged together using internal sanic functions. It works, but it would be nice to have native support.

Alright I'll look into this for the next release 馃憤

@JendaPlhak Do you possibly have those internal sanic functions to hand? If so, it would be good to use as a stopgap until the next release.

@nasfarley88 Here is our solution working with version 0.1.7. It doesn't work with later releases.

async def run_web_app(app, port, *, loop, logger, request_timeout=20):
    connections = {}
    signal = sanic.server.Signal()
    handler_factory = lambda: HttpProtocol(
        loop = loop,
        connections = connections,
        signal = signal,
        request_handler = app.handle_request,
        request_timeout = request_timeout,
        request_max_size = 1024*1024
    )

    server = await loop.create_server(handler_factory, None, port)
    for sock in server.sockets:
        sockname = sock.getsockname()
        logger.info("Listening on %s:%d", sockname[0], sockname[1])

    try:
        await asyncio.Future(loop = loop)
    finally:
        server.close()
        await server.wait_closed()

        # Complete all tasks on the loop
        signal.stopped = True
        for connection in connections.keys():
            connection.close_if_idle()
        while connections:
            await asyncio.sleep(0.1, loop = loop)

I too would love to find this coroutine in sanic! This is actually the last thing I need in order to switch from aiohttp to sanic.

This is addressed by #348. See the example here: https://github.com/channelcat/sanic/pull/348/files#diff-7f0b2849596f21c41bbf61f1904cc707.

Reopening this issue, having a non-blocking way of running the server seems to be more trouble than it's worth.

If anyone can make a compelling argument by February 3, 2017 we will keep an async_run in but if not we'll go ahead and remove it because it seems to be causing problems in a lot of different places.

Apart from Sanic being at least a little compatible with aiohttp's aiohttp.web.Application, I can't really imagine how would I do graceful Sanic stop when signal is caught. In my usecase I need to wait for couple of seconds and perform other actions when signal is caught. These I need to do with active event loop.

And as I mentioned elsewhere, forcing users to rely on Sanic to implicitly create event loop and then start their own tasks using Sanics after_start etc. is just wrong, not elegant and extremely Sanic-centric.

@JendaPlhak How is it wrong? If you're writing a Sanic application I'd at least expect it to be a bit Sanic-centric.

@seemethere In my application, there are two listening coroutines, one for Telegram and one for Sanic. Having Sanic do anything but run in the current event loop makes it very difficult to manage the async flow of the program.

Ideally, there may be many listening coroutines, all using the same loop and sharing information and if any one of them has priority or more 'centric'-ness than the other it is likely to cause problems. E.g., what if another library decided to operate the same way as Sanic. That would mean somehow chaining them together in a way that's (hopefully) mutually compatible, possibly breaking one or the other, etc.. If Sanic works like other async libraries (e.g. coroutines throughout the whole library, not assuming sole ownership of the loop, etc.) then these problems are avoided.

However, if the aim of Sanic is to be a web server first, with features added to Sanic only (rather than adding Sanic as a feature to other applications), this should be reflected in documentation. This is a possible solution, although it would be a shame not to be able to use this library since it fulfils so many of the other criteria for my project.

All of this can be simplified if Sanic removes the dependency on uvloop and just throws a warning when it isn't used. People can then use it however they want without before_start, run_async, etc.

This discussion died out 15 months ago. Closing for now. We can renew the discussion in a new issue and reference this if folks still have an interest.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

woutor picture woutor  路  3Comments

ubergarm picture ubergarm  路  4Comments

jasonab picture jasonab  路  3Comments

litelife picture litelife  路  3Comments

geekpy picture geekpy  路  4Comments