Skip to content

Cannot perform operation: another operation is in progress #728

Open

Description

@erhosen
  • GINO version: 1.0.1
  • Python version: 3.8
  • asyncpg version: 0.21.0
  • aiocontextvars version: 0.2.2
  • PostgreSQL version: 10.14

Description

My task is create some database record (via GINO Model.create()) before running test (typical pytest.fixture usage), and drop everything after.

What I Did

conftest.py

import pytest
from fastapi.testclient import TestClient

from alembic.config import main as alembic_main

from settings import settings
settings.DATABASE_NAME = 'test_db_name'
from main import app_init

@pytest.fixture
def client():
    alembic_main(["--raiseerr", "upgrade", "head"])

    with TestClient(app_init()) as client:
        yield client

    alembic_main(["--raiseerr", "downgrade", "base"])

test.py

import pytest
from models import SpecialModel

@pytest.fixture
async def special_model():
    special_model = await SpecialModel.create(
        internal_name='internal_name',
        comment='comment',
        is_active=True,
        title="Title",
        text="Text"
    )
    yield special_model

def test_get_all_special_models(client, special_model):
    response = client.get("api/get_all_models")
    data = response.json()
    assert data["success"] is True
    assert len(data["result"]) == 1

What I got:

test setup failed
@pytest.fixture
    async def special_model():
>      special_model = await SpecialModel.create(
            internal_name='internal_name',
            comment='comment',
            is_active=True,
            title="Title",
            text="Text"
        )

tests/test.py:8: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/gino/crud.py:444: in _create_without_instance
    return await cls(**values)._create(bind=bind, timeout=timeout)
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/gino/crud.py:477: in _create
    row = await bind.first(q)
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/gino/engine.py:748: in first
    return await conn.first(clause, *multiparams, **params)
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/gino/engine.py:147: in __aexit__
    await conn.release()
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/gino/engine.py:279: in release
    await dbapi_conn.release(True)
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/gino/engine.py:47: in release
    return await self._release()
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/gino/engine.py:83: in _release
    await self._pool.release(conn)
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/gino/dialects/asyncpg.py:232: in release
    await self._pool.release(conn)
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/asyncpg/pool.py:654: in release
    return await asyncio.shield(ch.release(timeout))
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/asyncpg/pool.py:216: in release
    raise ex
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/asyncpg/pool.py:206: in release
    await self._con.reset(timeout=budget)
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/asyncpg/connection.py:1137: in reset
    await self.execute(reset_query, timeout=timeout)
../../.virtualenvs/deeplink-offer-service/lib/python3.8/site-packages/asyncpg/connection.py:295: in execute
    return await self._protocol.query(query, timeout)
asyncpg/protocol/protocol.pyx:301: in query
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   asyncpg.exceptions._base.InterfaceError: cannot perform operation: another operation is in progress

Activity

  1. uriyyo commented on Nov 5, 2020

    @uriyyo
    Contributor

    @erhosen I faced the same problem, solution was to use a separate db connection:

    @pytest.fixture
    async def special_model():
        async with db.acquire():  # use seperate db connection
            special_model = await SpecialModel.create(
                internal_name='internal_name',
                comment='comment',
                is_active=True,
                title="Title",
                text="Text"
            )
    
        yield special_model

    This isn't an issue with gino it's an asyncpg issue. Basically, asyncpg can't make two concurrent queries using the same db connection.

  2. fantix commented on Dec 7, 2020

    @fantix
    Member

    Thanks! This deserves a page in the docs.

  3. kgantsov commented on Nov 18, 2021

    @kgantsov

    I have the same exception asyncpg.exceptions._base.InterfaceError: cannot perform operation: another operation is in progress when I run pytest.

    Any idea what I did wrong? I would appreciate any help. Thanks in advance.

    requirements.txt

    fastapi==0.70.0
    gino==1.0.1
    pytest==6.2.5
    pytest-asyncio==0.16.0
    requests==2.26.0
    

    test_code.py

    import os
    from typing import List
    import pytest
    
    from gino import Gino
    from fastapi import APIRouter
    from pydantic import BaseModel
    from fastapi import FastAPI
    from starlette.testclient import TestClient
    
    router = APIRouter()
    
    db = Gino()
    
    
    async def init_db():
        await db.set_bind(os.environ['DATABASE_URL'])
        await db.gino.create_all()
    
    
    class UserModel(db.Model):
        __tablename__ = 'user'
    
        id = db.Column(db.Integer(), primary_key=True)
        name = db.Column(db.Unicode())
        email = db.Column(db.Unicode(), unique=True, index=True)
        password_hash = db.Column(db.Unicode())
    
    
    class UserSchema(BaseModel):
        id: int = 0
        name: str
        email: str
        password: str
    
    
    class UserListSchema(BaseModel):
        objects: List[UserSchema]
    
    
    @router.get("/users/", response_model=UserListSchema)
    async def get_users():
        async with db.acquire():
            users = await UserModel.query.limit(200).gino.all()
    
        return UserListSchema.parse_obj({
            'objects': [x.to_dict() for x in users]
        })
    
    
    def get_app():
        print('INIT APP')
        app = FastAPI(title="GINO FastAPI Demo")
    
        app.include_router(router, prefix='/API/v1')
    
        @app.on_event("startup")
        async def startup_event():
            print('Initialising DB')
            await init_db()
            print('DB was initialised')
    
        return app
    
    
    @pytest.fixture
    def client():
    
        with TestClient(get_app()) as client:
            yield client
    
    
    @pytest.fixture
    @pytest.mark.anyio
    async def user(client):
    
        print('[-------->')
        # await init_db()
    
        # async with db.acquire():
        user = await UserModel.create(email='test@gmail.com')
    
        # async with db.acquire():
        users = await UserModel.query.limit(200).gino.all()
        print('.....=', user)
        print('....._', users)
    
        yield user
    
    
    def test_users(user, client):
        response = client.get(
            "/API/v1/users",
            headers={},
        )
        print('=====', user, response.text)
    
        assert response.status_code == 200
        assert response.json() == {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions