Skip to content

Commit 629822e

Browse files
authored
Use exists_ok in error handling instead of pre-condition (#44)
Fixes exception raised in `CouchDB.create()` even with exists_ok This can happen in a race condition case.
1 parent 8ab0f62 commit 629822e

File tree

3 files changed

+40
-8
lines changed

3 files changed

+40
-8
lines changed

aiocouch/couchdb.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,13 @@ async def create(
9191
9292
"""
9393
db = Database(self, id)
94-
if not await db._exists():
94+
try:
9595
await db._put(**kwargs)
96-
return db
97-
elif exists_ok:
98-
return db
99-
else:
100-
raise PreconditionFailedError(f"The database '{id}' does already exist.")
96+
except PreconditionFailedError as e:
97+
if not exists_ok:
98+
raise e
99+
100+
return db
101101

102102
async def __getitem__(self, id: str) -> "Database":
103103
"""Returns a representation for the given database identifier

tests/conftest.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,15 @@ async def couchdb_with_user_access(
7979

8080

8181
@pytest.fixture
82-
async def database(couchdb: CouchDB) -> AsyncGenerator[Database, None]:
83-
database = await couchdb.create("aiocouch_test_fixture_database")
82+
def database_id() -> str:
83+
return "aiocouch_test_fixture_database"
84+
85+
86+
@pytest.fixture
87+
async def database(
88+
couchdb: CouchDB, database_id: str
89+
) -> AsyncGenerator[Database, None]:
90+
database = await couchdb.create(database_id)
8491

8592
yield database
8693

tests/test_server.py

+25
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import asyncio
2+
13
import pytest
24

35
from aiocouch import CouchDB, Database
@@ -35,6 +37,29 @@ async def test_create_for_existing(couchdb: CouchDB, database: Database) -> None
3537
await couchdb.create(database.id)
3638

3739

40+
async def test_create_for_existing_but_mismatching_params(
41+
couchdb: CouchDB, database: Database
42+
) -> None:
43+
from aiocouch import PreconditionFailedError
44+
45+
with pytest.raises(PreconditionFailedError):
46+
await couchdb.create(database.id, partitioned=True)
47+
48+
49+
async def test_create_for_existing_ok_with_race(
50+
couchdb: CouchDB, database_id: str
51+
) -> None:
52+
try:
53+
# try to trigger a race-condition during the creation of the database
54+
await asyncio.gather(
55+
*[couchdb.create(database_id, exists_ok=True) for _ in range(5)]
56+
)
57+
finally:
58+
# for this specific test, we need to do a manual cleanup
59+
db = await couchdb.create(database_id, exists_ok=True)
60+
await db.delete()
61+
62+
3863
async def test_create_for_existing_ok(couchdb: CouchDB, database: Database) -> None:
3964
await couchdb.create(database.id, exists_ok=True)
4065

0 commit comments

Comments
 (0)