feat: add real PDF ingestion workflow
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from functools import lru_cache
|
||||
|
||||
import psycopg
|
||||
from psycopg.types.json import Jsonb
|
||||
|
||||
from app.domain.models import ProjectSnapshot
|
||||
from app.repositories.memory import create_demo_project
|
||||
|
||||
|
||||
class PostgresProjectRepository:
|
||||
def __init__(self, database_url: str) -> None:
|
||||
self.database_url = database_url
|
||||
self.ensure_schema()
|
||||
if self.get("demo-apartment") is None:
|
||||
self.save(create_demo_project())
|
||||
|
||||
def _connect(self):
|
||||
return psycopg.connect(self.database_url)
|
||||
|
||||
def ensure_schema(self) -> None:
|
||||
with self._connect() as connection, connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS projects (
|
||||
project_id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
stage TEXT NOT NULL,
|
||||
revision INTEGER NOT NULL,
|
||||
snapshot JSONB NOT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
def get(self, project_id: str) -> ProjectSnapshot | None:
|
||||
with self._connect() as connection, connection.cursor() as cursor:
|
||||
cursor.execute("SELECT snapshot FROM projects WHERE project_id = %s", (project_id,))
|
||||
row = cursor.fetchone()
|
||||
if row is None:
|
||||
return None
|
||||
payload = json.loads(row[0]) if isinstance(row[0], str) else row[0]
|
||||
return ProjectSnapshot.model_validate(payload)
|
||||
|
||||
def list(self) -> list[ProjectSnapshot]:
|
||||
with self._connect() as connection, connection.cursor() as cursor:
|
||||
cursor.execute("SELECT snapshot FROM projects ORDER BY updated_at DESC")
|
||||
rows = cursor.fetchall()
|
||||
return [
|
||||
ProjectSnapshot.model_validate(json.loads(row[0]) if isinstance(row[0], str) else row[0])
|
||||
for row in rows
|
||||
]
|
||||
|
||||
def save(self, project: ProjectSnapshot) -> ProjectSnapshot:
|
||||
payload = project.model_dump(mode="json")
|
||||
with self._connect() as connection, connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT INTO projects (project_id, name, stage, revision, snapshot, updated_at)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)
|
||||
ON CONFLICT (project_id) DO UPDATE SET
|
||||
name = EXCLUDED.name,
|
||||
stage = EXCLUDED.stage,
|
||||
revision = EXCLUDED.revision,
|
||||
snapshot = EXCLUDED.snapshot,
|
||||
updated_at = EXCLUDED.updated_at
|
||||
""",
|
||||
(
|
||||
project.project_id,
|
||||
project.name,
|
||||
project.stage.value,
|
||||
project.revision,
|
||||
Jsonb(payload),
|
||||
project.updated_at,
|
||||
),
|
||||
)
|
||||
return project
|
||||
|
||||
|
||||
@lru_cache(maxsize=4)
|
||||
def postgres_repository(database_url: str) -> PostgresProjectRepository:
|
||||
return PostgresProjectRepository(database_url)
|
||||
Reference in New Issue
Block a user