Persistence Layer¶
The persistence package provides the SQLite-backed implementation of GraphRepository. The core engine never imports from this package — it depends only on the abstract GraphRepository interface defined in core.engine.
Design Decisions¶
| Decision | Rationale |
|---|---|
| SQLAlchemy 2.0 ORM | Well-supported, type-safe, works with SQLite and can be swapped for other DBs |
| JSON attribute blobs | Avoids schema migrations when AttributeFields are added to a GraphType |
| Upsert pattern | save_graph / save_node / save_edge all insert-or-update — no separate insert/update paths |
| Session-per-operation | Each call opens and closes a session; simple and safe for single-user desktop use |
| Cascade deletes | GraphRow has SQLAlchemy cascade="all, delete-orphan" so deleting a graph removes all its nodes and edges automatically |
Database Schema¶
erDiagram
workspaces {
string id PK
string name
datetime created_at
datetime updated_at
}
graphs {
string id PK
string workspace_id FK
string type_name
string name
int version
datetime created_at
datetime updated_at
}
nodes {
string id PK
string graph_id FK
string type_name
text attributes_json
int version
datetime created_at
datetime updated_at
}
edges {
string id PK
string graph_id FK
string source_id FK
string target_id FK
string type_name
text attributes_json
int version
datetime created_at
datetime updated_at
}
workspaces ||--o{ graphs : "owns"
graphs ||--o{ nodes : "contains"
graphs ||--o{ edges : "contains"
nodes ||--o{ edges : "source"
nodes ||--o{ edges : "target"
In-Memory Mode (Testing)¶
Pass ":memory:" to SqliteGraphRepository for a fully in-process database that is discarded when the object is garbage-collected:
from knowledge_platform.persistence.store import SqliteGraphRepository
repo = SqliteGraphRepository(":memory:")
# ... use repo ...
repo.close() # release connection pool
File-Based Mode (Production)¶
Pass a Path or string path to a .db file:
from pathlib import Path
repo = SqliteGraphRepository(Path.home() / ".knowledge_platform" / "my_workspace.db")
Resource Management¶
Always call repo.close() when you are done — typically in a finally block or via WorkspaceService.close(). Failing to do so causes ResourceWarning about unclosed database connections.
API Reference¶
See SqliteGraphRepository for the concrete repository API.