feat(versions): rolling-cap prune ignores pinned versions
The DELETE inside create_version now filters pin_kind IS NULL so pinned rows (auto or manual) aren't counted toward MAX_VERSIONS=50 and aren't candidates for deletion. Pinned versions live indefinitely regardless of how heavy rolling autosave traffic gets on the same note.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
"""Tests for the prune logic — both rolling (pin_kind IS NULL) and the
|
||||
auto-pin bucket (pin_kind='auto').
|
||||
|
||||
Design: docs/superpowers/specs/2026-05-13-note-version-pinning-design.md
|
||||
"""
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
|
||||
async def test_create_version_prune_sql_filters_to_unpinned():
|
||||
"""The DELETE statement issued by create_version's prune step must
|
||||
include `pin_kind IS NULL` in the inner SELECT so pinned versions
|
||||
aren't counted toward MAX_VERSIONS and can't be pruned by it."""
|
||||
mock_session = AsyncMock()
|
||||
select_result = MagicMock()
|
||||
# No prior version → skips the throttle/dedupe early-return paths and
|
||||
# proceeds straight to insert + prune.
|
||||
select_result.scalars.return_value.first.return_value = None
|
||||
mock_session.add = MagicMock()
|
||||
mock_session.commit = AsyncMock()
|
||||
mock_session.refresh = AsyncMock()
|
||||
mock_session.__aenter__ = AsyncMock(return_value=mock_session)
|
||||
mock_session.__aexit__ = AsyncMock(return_value=False)
|
||||
|
||||
captured_sql: list[str] = []
|
||||
|
||||
async def execute_capture(stmt, *args, **kwargs):
|
||||
captured_sql.append(str(stmt))
|
||||
if len(captured_sql) == 1:
|
||||
return select_result
|
||||
return MagicMock()
|
||||
|
||||
mock_session.execute = AsyncMock(side_effect=execute_capture)
|
||||
|
||||
with patch(
|
||||
"fabledassistant.services.note_versions.async_session",
|
||||
return_value=mock_session,
|
||||
):
|
||||
from fabledassistant.services.note_versions import create_version
|
||||
await create_version(
|
||||
user_id=1, note_id=42, body="content", title="t", tags=["a"],
|
||||
)
|
||||
|
||||
assert any("pin_kind IS NULL" in s for s in captured_sql), (
|
||||
f"Expected prune SQL to filter pin_kind IS NULL; got: {captured_sql!r}"
|
||||
)
|
||||
Reference in New Issue
Block a user