BeanieODM / beanie

Asynchronous Python ODM for MongoDB
http://beanie-odm.dev/
Apache License 2.0
2.07k stars 218 forks source link

[BUG] "RuntimeError: There is no current event loop in thread 'AnyIO worker thread'" when using inside FastAPI #390

Closed ccauet closed 2 years ago

ccauet commented 2 years ago

Describe the bug When trying to insert a new document into the MongoDB an error is thrown.

RuntimeError: There is no current event loop in thread 'AnyIO worker thread'

More Details

  ...
  File "/Users/ccauet/my_project/./mwe.py", line 25, in ingest_data
    data_dump.create()
  File "/Users/ccauet/my_project/.venv/lib/python3.10/site-packages/beanie/sync/odm/documents.py", line 241, in create
    return self.insert(session=session)
  File "/Users/ccauet/my_project/.venv/lib/python3.10/site-packages/beanie/sync/odm/actions.py", line 190, in wrapper
    ActionRegistry.run_actions(
  File "/Users/ccauet/my_project/.venv/lib/python3.10/site-packages/beanie/sync/odm/actions.py", line 111, in run_actions
    asyncio.gather(*coros)
  File "/Users/ccauet/.pyenv/versions/3.10.4/lib/python3.10/asyncio/tasks.py", line 715, in gather
    loop = events._get_event_loop()
  File "/Users/ccauet/.pyenv/versions/3.10.4/lib/python3.10/asyncio/events.py", line 656, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'AnyIO worker thread'.

To Reproduce

(Spin up a local test MongoDB with docker run -it -p "27017:27017" mongo)

This is a MWE

from beanie.sync import init_beanie, Document
from pymongo import MongoClient
from fastapi import FastAPI

class DataDump(Document):
    name: str
    upload_timestamp: str

    class Settings:
        name = "default"

def init_db():
    db_client = MongoClient(
        f"mongodb://localhost:27017",
    )

    init_beanie(database=db_client.pdharcs, document_models=[DataDump])

app = FastAPI()
init_db()

@app.post("/data/")
def ingest_data(data_dump: DataDump):
    print(data_dump)
    data_dump.create()

# poetry run uvicorn mwe:app --reload

Send some example data

import requests

def main():
    url = "http://localhost:8000/data"
    data = {
        "name": "john",
        "upload_timestamp": "2022-10-24T16:47+00:00",
    }
    response = requests.post(url, json=data)

    print(response.status_code)
    print(response.headers)

if __name__ == "__main__":
    main()

deps

anyio              3.6.2    
beanie             1.13.0   
fastapi            0.85.1   
pydantic           1.10.2   
pymongo            4.3.2    
starlette          0.20.4   
uvicorn            0.18.3   
uvloop             0.17.0   

Expected behavior I would except the document inserted and no problem due to async stuff.

Additional context I'm pretty sure it has something to do with FastAPI or even Starlette underneath, but it only starts happing after adding the .create() step. So, somehow I'm opening this issue to get some understanding what happens and maybe where to look next.

roman-right commented 2 years ago

Hi! This is a bug. I'll fix it today. Thank you for the catch!

ccauet commented 2 years ago

This is a bug. I'll fix it today.

😅

Thanks a lot

roman-right commented 2 years ago

@ccauet, it should be fixed in 1.13.1. Please, try

ccauet commented 2 years ago

Yes, I can confirm, it now works as expected. Thanks a lot! 👍

roman-right commented 2 years ago

Great! Thank you :)