mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
c44291830c
Signed-off-by: phernandez <paul@basicmachines.co> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
136 lines
5.1 KiB
Python
136 lines
5.1 KiB
Python
"""Tests for issue #187 - UNIQUE constraint violation on file_path during sync."""
|
|
|
|
import pytest
|
|
from datetime import datetime, timezone
|
|
|
|
from basic_memory.models.knowledge import Entity, Observation
|
|
from basic_memory.repository.entity_repository import EntityRepository
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_upsert_entity_with_observations_conflict(entity_repository: EntityRepository):
|
|
"""Test upserting an entity that already exists with observations.
|
|
|
|
This reproduces issue #187 where sync fails with UNIQUE constraint violations
|
|
when trying to update entities that already exist with observations.
|
|
"""
|
|
# Create initial entity with observations
|
|
entity1 = Entity(
|
|
project_id=entity_repository.project_id,
|
|
title="Original Title",
|
|
note_type="note",
|
|
permalink="debugging/backup-system/coderabbit-feedback-resolution",
|
|
file_path="debugging/backup-system/CodeRabbit Feedback Resolution - Backup System Issues.md",
|
|
content_type="text/markdown",
|
|
created_at=datetime.now(timezone.utc),
|
|
updated_at=datetime.now(timezone.utc),
|
|
)
|
|
|
|
# Add observations to the entity
|
|
obs1 = Observation(
|
|
project_id=entity_repository.project_id,
|
|
content="This is a test observation",
|
|
category="testing",
|
|
tags=["test"],
|
|
)
|
|
entity1.observations.append(obs1)
|
|
|
|
result1 = await entity_repository.upsert_entity(entity1)
|
|
original_id = result1.id
|
|
|
|
# Verify entity was created with observations
|
|
assert result1.id is not None
|
|
assert len(result1.observations) == 1
|
|
|
|
# Now try to upsert the same file_path with different content/observations
|
|
# This simulates a file being modified and re-synced
|
|
entity2 = Entity(
|
|
project_id=entity_repository.project_id,
|
|
title="Updated Title",
|
|
note_type="note",
|
|
permalink="debugging/backup-system/coderabbit-feedback-resolution", # Same permalink
|
|
file_path="debugging/backup-system/CodeRabbit Feedback Resolution - Backup System Issues.md", # Same file_path
|
|
content_type="text/markdown",
|
|
created_at=datetime.now(timezone.utc),
|
|
updated_at=datetime.now(timezone.utc),
|
|
)
|
|
|
|
# Add different observations
|
|
obs2 = Observation(
|
|
project_id=entity_repository.project_id,
|
|
content="This is an updated observation",
|
|
category="updated",
|
|
tags=["updated"],
|
|
)
|
|
obs3 = Observation(
|
|
project_id=entity_repository.project_id,
|
|
content="This is a second observation",
|
|
category="second",
|
|
tags=["second"],
|
|
)
|
|
entity2.observations.extend([obs2, obs3])
|
|
|
|
# This should UPDATE the existing entity, not fail with IntegrityError
|
|
result2 = await entity_repository.upsert_entity(entity2)
|
|
|
|
# Should update existing entity (same ID)
|
|
assert result2.id == original_id
|
|
assert result2.title == "Updated Title"
|
|
assert result2.file_path == entity1.file_path
|
|
assert result2.permalink == entity1.permalink
|
|
|
|
# Observations should be updated
|
|
assert len(result2.observations) == 2
|
|
assert result2.observations[0].content == "This is an updated observation"
|
|
assert result2.observations[1].content == "This is a second observation"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_upsert_entity_repeated_sync_same_file(entity_repository: EntityRepository):
|
|
"""Test that syncing the same file multiple times doesn't cause IntegrityError.
|
|
|
|
This tests the specific scenario from issue #187 where files are being
|
|
synced repeatedly and hitting UNIQUE constraint violations.
|
|
"""
|
|
file_path = "processes/Complete Process for Uploading New Training Videos.md"
|
|
permalink = "processes/complete-process-for-uploading-new-training-videos"
|
|
|
|
# Create initial entity
|
|
entity1 = Entity(
|
|
project_id=entity_repository.project_id,
|
|
title="Complete Process for Uploading New Training Videos",
|
|
note_type="note",
|
|
permalink=permalink,
|
|
file_path=file_path,
|
|
content_type="text/markdown",
|
|
checksum="abc123",
|
|
created_at=datetime.now(timezone.utc),
|
|
updated_at=datetime.now(timezone.utc),
|
|
)
|
|
|
|
result1 = await entity_repository.upsert_entity(entity1)
|
|
first_id = result1.id
|
|
|
|
# Simulate multiple sync attempts (like the infinite retry loop in the issue)
|
|
for i in range(5):
|
|
entity_new = Entity(
|
|
project_id=entity_repository.project_id,
|
|
title="Complete Process for Uploading New Training Videos",
|
|
note_type="note",
|
|
permalink=permalink,
|
|
file_path=file_path,
|
|
content_type="text/markdown",
|
|
checksum=f"def{456 + i}", # Different checksum each time
|
|
created_at=datetime.now(timezone.utc),
|
|
updated_at=datetime.now(timezone.utc),
|
|
)
|
|
|
|
# Each upsert should succeed and update the existing entity
|
|
result = await entity_repository.upsert_entity(entity_new)
|
|
|
|
# Should always return the same entity (updated)
|
|
assert result.id == first_id
|
|
assert result.checksum == entity_new.checksum
|
|
assert result.file_path == file_path
|
|
assert result.permalink == permalink
|