BeanieODM / beanie

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

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

Closed ccauet closed 1 year ago

ccauet commented 1 year 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 1 year ago

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

ccauet commented 1 year ago

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

😅

Thanks a lot

roman-right commented 1 year ago

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

ccauet commented 1 year ago

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

roman-right commented 1 year ago

Great! Thank you :)