Files
topoteretes--cognee/cognee/tests/unit/modules/data/test_create_dataset_concurrency.py
wehub-resource-sync c889a57b6b
Test Suites / Build CI Environment (push) Has been cancelled
Test Suites / Basic Tests (push) Has been cancelled
Test Suites / End-to-End Tests (push) Has been cancelled
Test Suites / CLI Tests (push) Has been cancelled
Test Suites / Slow End-to-End Tests (push) Has been cancelled
Test Suites / Graph Database Tests (push) Has been cancelled
Test Suites / Vector DB Tests (push) Has been cancelled
Test Suites / Temporal Graph Test (push) Has been cancelled
Test Suites / Search Test on Different DBs (push) Has been cancelled
Test Suites / Example Tests (push) Has been cancelled
Test Suites / Notebook Tests (push) Has been cancelled
Test Suites / OS and Python Tests Ubuntu (push) Has been cancelled
Test Suites / OS and Python Tests Extended (push) Has been cancelled
Test Suites / LLM Test Suite (push) Has been cancelled
Test Suites / S3 File Storage Test (push) Has been cancelled
Test Suites / Run Integration Tests (push) Has been cancelled
Test Suites / MCP Tests (push) Has been cancelled
Test Suites / Docker Compose Test (push) Has been cancelled
Test Suites / Docker CI test (push) Has been cancelled
Test Suites / Relational DB Migration Tests (push) Has been cancelled
Test Suites / Distributed Cognee Test (push) Has been cancelled
Test Suites / DB Examples Tests (push) Has been cancelled
Test Suites / Test Completion Status (push) Has been cancelled
Test Suites / Claude Code Review (push) Has been cancelled
Test Suites / basic checks (push) Has been cancelled
build | Build and Push Cognee MCP Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
build | Build and Push Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.11) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.12) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (kuzu, kuzu) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (neo4j, neo4j) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Examples (push) Has been cancelled
Weighted Edges Tests / Code Quality for Weighted Edges (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:02:24 +08:00

139 lines
4.8 KiB
Python

"""Tests for ``create_dataset`` concurrent-creation safety.
Concurrent calls for the same dataset name race between the existence SELECT
and the INSERT and, because the dataset id is deterministic, collide on the
primary key. ``create_dataset`` must tolerate losing that race (catch the
IntegrityError and return the winner's committed row) without weakening
isolation: the recovered row must satisfy the same name/owner/tenant-scoped
query as the original lookup, so an id collision with any other row —
another owner's or tenant's dataset — stays an error.
"""
import asyncio
import sys
from types import SimpleNamespace
from uuid import NAMESPACE_OID, uuid4, uuid5
import pytest
from sqlalchemy.exc import IntegrityError
from cognee.modules.data.methods import create_dataset
# The package __init__ rebinds the ``create_dataset`` attribute to the
# function, so the module itself must come from sys.modules.
create_dataset_module = sys.modules["cognee.modules.data.methods.create_dataset"]
class _FakeScalarResult:
def __init__(self, value):
self._value = value
def first(self):
return self._value
def _matches(row, statement):
"""Evaluate a select statement's WHERE criteria against a row."""
whereclause = statement.whereclause
for clause in getattr(whereclause, "clauses", [whereclause]):
column_name = clause.left.name
expected = getattr(clause.right, "value", None) # IS NULL has no value
if getattr(row, column_name) != expected:
return False
return True
class _FakeSession:
"""Emulates the SELECT -> INSERT window against a shared rows-by-id store.
Every await yields control so concurrent tasks interleave exactly like
real DB round-trips. SELECTs honor the statement's WHERE criteria, and
commit enforces the primary-key unique constraint the way the real
database does: inserting a duplicate id raises IntegrityError.
"""
def __init__(self, rows_by_id):
self._rows_by_id = rows_by_id
self._pending_add = None
async def scalars(self, statement):
await asyncio.sleep(0)
return _FakeScalarResult(
next((row for row in self._rows_by_id.values() if _matches(row, statement)), None)
)
def add(self, dataset):
self._pending_add = dataset
async def commit(self):
await asyncio.sleep(0)
if self._pending_add is not None:
row, self._pending_add = self._pending_add, None
if row.id in self._rows_by_id:
raise IntegrityError("duplicate key value", None, Exception())
self._rows_by_id[row.id] = row
async def rollback(self):
await asyncio.sleep(0)
self._pending_add = None
class _CollideAndVanishSession(_FakeSession):
"""Insert collides, but the winner's row is gone by the re-select."""
async def scalars(self, _statement):
await asyncio.sleep(0)
return _FakeScalarResult(None)
async def commit(self):
await asyncio.sleep(0)
raise IntegrityError("duplicate key value", None, Exception())
def _install_deterministic_dataset_id(monkeypatch):
async def fake_get_unique_dataset_id(dataset_name, user):
return uuid5(NAMESPACE_OID, f"{dataset_name}{user.id}")
monkeypatch.setattr(create_dataset_module, "get_unique_dataset_id", fake_get_unique_dataset_id)
@pytest.mark.asyncio
async def test_concurrent_same_dataset_creation_does_not_raise(monkeypatch):
user = SimpleNamespace(id=uuid4(), tenant_id=None)
_install_deterministic_dataset_id(monkeypatch)
rows_by_id = {}
datasets = await asyncio.gather(
*[create_dataset("race_dataset", user, session=_FakeSession(rows_by_id)) for _ in range(10)]
)
assert len(rows_by_id) == 1
assert len({dataset.id for dataset in datasets}) == 1
@pytest.mark.asyncio
async def test_colliding_foreign_dataset_is_not_returned(monkeypatch):
"""An id collision with another owner's dataset must error, never leak the row."""
user = SimpleNamespace(id=uuid4(), tenant_id=None)
_install_deterministic_dataset_id(monkeypatch)
dataset_id = uuid5(NAMESPACE_OID, f"race_dataset{user.id}")
foreign_dataset = SimpleNamespace(
id=dataset_id, name="foreign_dataset", owner_id=uuid4(), tenant_id=uuid4()
)
rows_by_id = {dataset_id: foreign_dataset}
with pytest.raises(IntegrityError):
await create_dataset("race_dataset", user, session=_FakeSession(rows_by_id))
assert rows_by_id == {dataset_id: foreign_dataset}
@pytest.mark.asyncio
async def test_vanished_winner_row_reraises_integrity_error(monkeypatch):
user = SimpleNamespace(id=uuid4(), tenant_id=None)
_install_deterministic_dataset_id(monkeypatch)
with pytest.raises(IntegrityError):
await create_dataset("race_dataset", user, session=_CollideAndVanishSession({}))