Closed allen-munsch closed 3 years ago
Thank you for reporting the issue, the only reason I can see here is that the thread executor to fetch all data when the iterator is call didn't wait to create the iterator. does this happen all the time ?
I couldn't reproduce with my tests but looking at the call stack and the routing I don't see a typical django app. can you tell me more about your use case ? it seems you're using starlette for routing do you have any idea how is working with django and the async world ?
What I can do to protect the code, is to try to block the async call, because in this specific use case I'm using threads to create the iterator.
def __aiter__(self):
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
executor.submit(self._fetch_all)
return AsyncIter(self._result_cache)
Also, if you try to print(data)
before iterating, it will fetch data because it's already blocking.
The code is using something like this:
Not entirely sure why, but nesting the function, or creating a closure around it seemed to work.
@app.get("/buildings", response_model=List[BuildingSummary])
async def get_buildings(limit: conint(le=500), skip: conint(le=500)) -> List[BuildingSummary]:
"""
Building List
"""
# this is a custom thing
async def get_data():
data = await Building.objects.async_all()
result = []
for building in data:
print(data, dir(data))
print(building.__dict__)
result.append({"id": building.id, "number": building.number})
return result
data = await get_data()
return data
closing this issue, since something else is going on.
Cheers. Thanks for sharing the code.
that's interesting, but still an issue I think would you try to patch the code locally and test ? I don't think people would make a closure as a workaround.
Also I would be interested to know the performance difference between the workaround and the blocking one.
Thanks for your help.
diff --git a/django_async_orm/query.py b/django_async_orm/query.py
index 5df0118..90f12d3 100644
--- a/django_async_orm/query.py
+++ b/django_async_orm/query.py
@@ -66,7 +66,8 @@ class QuerySetAsync(QuerySet):
def __aiter__(self):
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
- executor.submit(self._fetch_all)
+ f = executor.submit(self._fetch_all)
+ f.result()
return AsyncIter(self._result_cache)
Thanks for sharing this library. Very interesting!
Any suggestions on why
NoneType
would be returned from async_all?py3.8.10 django3.2