Spaces:
Running
Running
Update app/db_sync.py
Browse files- app/db_sync.py +38 -0
app/db_sync.py
CHANGED
|
@@ -294,6 +294,44 @@ def is_ready() -> bool:
|
|
| 294 |
return _initialized and _db_path is not None
|
| 295 |
|
| 296 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 297 |
# =============================================================================
|
| 298 |
# Direct execution guard
|
| 299 |
# =============================================================================
|
|
|
|
| 294 |
return _initialized and _db_path is not None
|
| 295 |
|
| 296 |
|
| 297 |
+
# =============================================================================
|
| 298 |
+
# SECTION 6 — PostgreSQL Bridge (Guardian-injected, optional)
|
| 299 |
+
# =============================================================================
|
| 300 |
+
_psql_writer = None
|
| 301 |
+
|
| 302 |
+
|
| 303 |
+
def set_psql_writer(writer_fn) -> None:
|
| 304 |
+
"""
|
| 305 |
+
Receives execute_secured_query callable from Guardian via app.py.
|
| 306 |
+
Called once in start_application() if db_service is available.
|
| 307 |
+
app/* never imports postgresql.py directly — this is the only bridge.
|
| 308 |
+
"""
|
| 309 |
+
global _psql_writer
|
| 310 |
+
_psql_writer = writer_fn
|
| 311 |
+
logger.info("PostgreSQL writer registered.")
|
| 312 |
+
|
| 313 |
+
|
| 314 |
+
async def persist(table: str, data: dict) -> None:
|
| 315 |
+
"""
|
| 316 |
+
Write data from app/* to PostgreSQL via Guardian-injected writer.
|
| 317 |
+
Called by tools.py for provider_type = 'persist'.
|
| 318 |
+
Graceful degradation: raises RuntimeError if no DB configured.
|
| 319 |
+
|
| 320 |
+
Args:
|
| 321 |
+
table: Target PostgreSQL table name.
|
| 322 |
+
data: Dict to persist — stored as JSONB column 'payload'.
|
| 323 |
+
"""
|
| 324 |
+
if not _psql_writer:
|
| 325 |
+
raise RuntimeError("No PostgreSQL writer — DATABASE_URL not configured.")
|
| 326 |
+
|
| 327 |
+
from datetime import datetime, timezone
|
| 328 |
+
now = datetime.now(timezone.utc).isoformat()
|
| 329 |
+
|
| 330 |
+
sql = f"INSERT INTO {table} (payload, created_at) VALUES ($1::jsonb, $2)"
|
| 331 |
+
await _psql_writer(sql, json.dumps(data), now, fetch_method="execute")
|
| 332 |
+
logger.info(f"Persisted to PostgreSQL table '{table}'.")
|
| 333 |
+
|
| 334 |
+
|
| 335 |
# =============================================================================
|
| 336 |
# Direct execution guard
|
| 337 |
# =============================================================================
|