Skip to content

Async usage with new websockets and http async transports using asyncio #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 51 commits into from
May 15, 2020
Merged

Async usage with new websockets and http async transports using asyncio #70

merged 51 commits into from
May 15, 2020

Conversation

leszekhanusz
Copy link
Collaborator

@leszekhanusz leszekhanusz commented Mar 25, 2020

Necessitate Python 3.6 and asyncio

New Client

  • can be used as before synchronously
client.execute(query)
  • but can also be used asynchronously
async with Client(...) as session:
    await session.execute(query)
  • supports existing sync http transport (requests) (only synchronously)
  • supports also new async transports (websockets and aiohttp)
  • Supports subscriptions with the websockets transport
  • synchronously with an infinite python generator
for result in client.subscribe(query):
    ... result is a dict here
  • OR asynchronously with an async generator.
async with Client(...) as session:
    async for result in session.subscribe(query):
        ... result is a dict here
  • for async transports, fetching schema from transport is done when executing the first query

New Websockets async transport

Allows a connection to an Apollo GraphQL websocket endpoint using the apollo subscriptions-transport-ws protocol

Require the great websockets library

Supports:

  • queries, mutations AND subscriptions
  • SSL encryption
  • multiple queries using the same connection
  • multiple subscription in parallel on the same connection using asyncio tasks

New HTTP async transport

Supports thanks to the aiohttp library:

  • http headers
  • http cookies
  • Basic auth
  • SSL

gql-cli

  • Added gql-cli script to execute graphql queries from the command line to an http or websocket endpoint.

Necessitate Python 3.6

Allows a connection to an Apollo GraphQL websocket endpoint

Supports fetching schema from transport using the introspection query
Supports queries, mutations AND subscriptions
Supports connection using a client ssl certificate

Only one request per connection for now
@coveralls
Copy link

coveralls commented Mar 25, 2020

Coverage Status

Coverage decreased (-98.8%) to 0.0% when pulling e8c46b1 on leszekhanusz:master into d49bd63 on graphql-python:master.

It is now possible to execute multiple queries in parallel using the same websocket connection
@yiblet
Copy link

yiblet commented Apr 1, 2020

thanks for doing this work, I was looking exactly for these features!

@KingDarBoja
Copy link
Contributor

Been busy due to real-life stuff but will look into this PR as soon as possible.

Adding fixtures to create a websocket server for the tests
Allow ssl=False argument in transport
Adding exceptions:
- TransportProtocolError
- TransportQueryError
- TransportServerError
- TransportClosed

Now 100% code coverage for transport/websockets.py
Improvement of 'server' test fixture to simplify tests (list only answers)
@KingDarBoja
Copy link
Contributor

KingDarBoja commented Apr 13, 2020

This is looking great, of course requires several reviews from the graphql-python team but glad to see this effort 🚀

Also, I think its a good idea to link resources at the PR body, like apollo subscriptions-transport-ws as example.

Added _wait_closed event and wait_close coroutine to wait for the close
task to finish

Add exception 'TransportAlreadyConnected' used when trying to connect
to an already connected transport

Added new tests to test multiple connections in series or in parallel

Refactor:
- rename _close to _fail
- rename _answer_loop to _receive_data_loop
- rename listen_loop to receive_data_task
Testing validation using schema, type_def or introspection

Fixing some flake8/black styling issues in tests_py36
This allows us to keep the execute method sync in the AsyncClient class
Rename client to session in all tests

It is now possible to execute GraphQL queries synchronously on asynchronous transports

Returning ExecutionResult.data instead of ExecutionResult in AsyncClient
(This corresponds to the previous usage of the library)
Now client.execute will use the existing asyncio loop if using an async
transport.
Rename AsyncClient to Client in all tests
Put back the LocalSchemaTransport in the AsyncClient class
All the old tests are passing with the AsyncClient as the Client in python > 3.6
retries on the client is now removed
…n server url

Adding yarl dependency (already in aiohttp...)
Fix AIOHTTPTransport exceptions

Adding asserts to ensure client.execute and client.subscribe
are not called with a running asyncio event loop
Removing pytest_aiohttp dependency (copy only the fixture we need)
Fixing import order with isort
Modify isort config to be compatible with black
Now isort will fail if invalid import order is found

isort upgraded to version 4.2.8 to fix bug
PyCQA/isort#537

Fix posargs in tox.ini to allow to run tox for specific tests
Add -s to pytest to have better logs in tox
Add -vb (verbose) to isort to have better logs in tox
For some reason on pypy3 with the version on travis (3.6.1),
it takes 10 seconds to leave the async generator...
So we increase the default timeout for a sync execute
Add execute_timeout to AsyncClient
Add connect_timeout, ack_timeout and close_timeout to websockets transport

Fix asyncio bugs of pypy3 v3.6.1 by adding await generator.aclose() in async for
@leszekhanusz leszekhanusz changed the title Implementation of a websockets transport using asyncio Async usage with new websockets and http async transports using asyncio May 13, 2020
@leszekhanusz leszekhanusz mentioned this pull request May 14, 2020
@Cito Cito added this to the Version 3 milestone May 15, 2020
@Cito Cito merged commit 6d961b7 into graphql-python:master May 15, 2020
@Cito
Copy link
Member

Cito commented May 15, 2020

Thanks again for this contribution. After creating a v2.x branch for the legacy support, and declaring the master to be the modern v3 branch, I merged this into master, and after fixing a small merge problem, tests are green. I will do some clean-up and modernization work in the master branch now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants