hballard/graphql-python-subscriptions

Add additional executors, in addition to gevent (current)

Opened this issue · 7 comments

Abstract excector model similar to python graphql-python/graphql-core -- allowing different executors -- like threads, asyncio, etc.

Currently working on -- see pull request #19

Awesome work so far. I am going to take what you have done and see if I can get it working with sanic which uses asyncio with uvloop.

Thanks. I haven't had much time to play w/ this the last couple weeks. I just pushed a new commit that has an almost working version of asyncio. About 6 transport server tests still don't pass. I might have to change the executor model around to get those to pass...haven't had a chance to dive into it. Also, in the asyncio transport server tests...I do use Sanic for the integration server. Code looks like this below

def create_app(sub_mgr, schema, options, executor, sub_server):
    app = Sanic(__name__)

    app.add_route(GraphQLView.as_view(schema=schema, graphiql=True),
                  '/graphql')

    @app.route('/publish', methods=['POST'])
    async def sub_mgr_publish(request):
        await sub_mgr.publish(*request.json)
        return await response.json(request.json)

    async def websocket(websocket, path):
        if path == '/socket':
            subscription_server = sub_server(sub_mgr, websocket,
                                             executor, **options)
            await subscription_server.handle()

    ws_server = websockets.serve(websocket, 'localhost', TEST_PORT,
                                 subprotocols=[GRAPHQL_SUBSCRIPTIONS])

    app.add_task(ws_server)

    return app


def app_worker(app, port):
    app.run(host="0.0.0.0", port=port)

Now you shouldn't have to use the app.add_task method for the websocket server...I only did this because Sanic did not originally support websocket subprotocols. I opened a an issue an couple weeks ago and they fixed it...not sure if it got pushed to master yet or not...you'll have to check. This would allow you to utilize the regular Sanic websocket decorator in lieu of the app.add_task method. It's a little cleaner than what I did above.

Also, if you haven't yet...you might want to read the comments on this current pull request #19. Looks like graphene will soon include support for subscriptions as an observable versus using the pubsub implementation I've done here. I still think there will need to be some code written around integrating w/ the various python concurrency frameworks...not sure if that will be done w/ extensions or included organically in graphene. I believe the observable will only take care of resolving the subscription...not the specific concurrency model or the subscription protocol implementation. We'll have to wait to see when graphene 2.0 is released.

Awesome thanks. I put together something using the @app.websocket decorator, but was having trouble getting the subscriptions to completely work. Seeing your code now, I think I might be able to piece the two together and will report back if I come up with anything.

I did see the PR #19. And, I am definitely going to keep my eye on this area.

Definitely...happy to help and would love to hear any feedback. Ideally, when I get some time, I'd still like to make the asyncio piece fully work. If you have any insight...I'm happy to hear it. Even with graphene eventually providing an observable based implementation...there still might be some interest in having a pubsub based alternative.

In case it's not obvious from the above code...websockets is imported globally in the module.

I just checked and it appears websocket subprotocol support is included in the master branch of Sanic now. See here. The tests give an example of how to use it with the websocket decorator.