Files
brain-of-reese/app/rag/sources_meta.py
T

54 lines
1.9 KiB
Python

"""Sources-version counter (phase 53, task 01).
The single-row ``sources_meta`` table (migration 0010, the
``kb_overview`` id=1 precedent) records **which generation of the
knowledge base** is current. ``version`` is bumped exactly once per
sync that actually changed the KB (task 02 — change-gated on
``added + updated + pruned > 0``; a failed sync never bumps), so it
doubles as the invalidation marker for saved chats: the chats API
stamps each saved row with the current version at save time (task 03)
and flags rows stamped with an older generation *stale* — their
answers predate the current index and may be Regenerated against it
(task 05).
Session convention (phase 53): :func:`bump_sources_version` only
*flushes* — the **caller** commits. The two sync paths (the admin Sync
button, ``scripts/import_docs``) each own their session, and the bump
must land in the same transaction as the KB changes it records.
"""
from __future__ import annotations
from sqlalchemy.orm import Session
from app.models import SourcesMeta
def current_sources_version(db: Session) -> int:
"""The current KB generation (one PK read of the seeded row).
Returns ``0`` when the row is absent — defensive, never raises
(the migration seeds the row, so absence only happens if someone
deleted it out-of-band).
"""
row = db.get(SourcesMeta, 1)
if row is None:
return 0
return row.version
def bump_sources_version(db: Session) -> int:
"""Advance the KB generation by one; return the new version.
Upserts the single row (creating it if it was ever deleted),
increments ``version`` by one, and ``flush``es — the **caller**
commits, because each of the two sync paths owns its session and
the bump must commit together with the KB changes it witnessed.
"""
row = db.get(SourcesMeta, 1)
if row is None:
row = SourcesMeta(id=1, version=0)
db.add(row)
row.version += 1
db.flush()
return row.version