Skip to content

Instantly share code, notes, and snippets.

@hyzyla
Last active September 29, 2020 12:50
Show Gist options
  • Save hyzyla/fb77c13d2e147262f1a217c3a74c1e6f to your computer and use it in GitHub Desktop.
Save hyzyla/fb77c13d2e147262f1a217c3a74c1e6f to your computer and use it in GitHub Desktop.
aiohttp + tartiflette + aiodataloader ( DOESN'T WORKS!)
from aiohttp import web
import tartiflette
from tartiflette_aiohttp import register_graphql_handlers
import loader
sdl = """
type Query {
books: [Book]
}
type Book {
id: String
title: String
author: Author
}
type Author {
id: String
name: String
}
"""
ctx = {
'user_service': 1
}
@tartiflette.Resolver("Query.books")
async def resolver_books(parent, args, ctx, info):
return [
{'id': "1", 'title': 'The Great Gatsby'},
{'id': "2", 'title': 'The Great Gatsby'},
{'id': "3", 'title': 'The Great Gatsby'},
{'id': "4", 'title': 'The Great Gatsby'},
{'id': "5", 'title': 'The Great Gatsby'},
{'id': "3", 'title': 'The Great Gatsby'},
]
async def batch_resolve_authors(ids):
return [{'id': id_, 'name': f'A{id_}'} for id_ in ids]
@tartiflette.Resolver("Book.author")
async def resolver_books(parent, args, ctx, info):
key = parent["id"]
return await loader.load_key(batch_resolve_authors, key)
web.run_app(
register_graphql_handlers(
app=web.Application(),
engine_sdl=sdl,
engine_schema_name="default",
executor_context=ctx,
executor_http_endpoint='/graphql',
executor_http_methods=['POST', 'GET'],
context_factory=loader.context
)
)
from __future__ import annotations
from contextlib import asynccontextmanager
from contextvars import ContextVar
from typing import Any, AsyncIterator, Awaitable, List
from aiodataloader import DataLoader
context_loaders = ContextVar('loaders')
def load_key(resolver, key: Any) -> Awaitable[Any]:
# For null key return nullable awaitable
if key is None:
async def _nothing(*args: Any, **kwargs: Any) -> None:
return None
return _nothing()
# Try to select loader from dict of loaders
# of the current execution context
loaders = context_loaders.get()
loader = loaders.get(resolver)
# If loader not exist in current context, create new one
if not loader:
async def _resolver(ids: List[Any]) -> List[Any]:
return await resolver(ids)
loader = DataLoader(batch_load_fn=_resolver)
loaders[resolver] = loader
context_loaders.set(loaders)
return loader.load(key)
@asynccontextmanager
async def context(*args, **kwargs) -> AsyncIterator[None]:
token = context_loaders.set({})
try:
yield
finally:
context_loaders.reset(token)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment