Research-Stack/4-Infrastructure/shim/rrc_bosonic_db_buffer.py
allaun 1f7ec15f12 feat(lean): add logarithmic viscosity coordinates to NKHodgeFAMM
Adds logViscosityRatio, log_viscosity_monotone, and ν_eff_monotone
to Semantics/NKHodgeFAMM.lean section 6b. The adaptive viscosity law
ν_eff = ν₀*(1+μ) is multiplicative in ν₀ and additive in scar density μ;
taking λ = log(ν_eff/ν₀) = log(1+μ) turns the multiplicative feedback into
an additive coordinate. This gives nlinarith a direct handle on viscosity
monotonicity and connects the module to Kritchevsky's "Everything Is
Logarithms" framing (SilverSight CITATION.cff).

Also marks a few pre-existing unused variables with underscores to silence
the linter.

Build: 8316 jobs, 0 errors (lake build Semantics.NKHodgeFAMM)
2026-06-22 01:21:58 -05:00

433 lines
17 KiB
Python

#!/usr/bin/env python3
# INFRA:DEAD rds -- AWS RDS is gone. Any file referencing rds_connect.py or this hostname is stale and must be ported.
"""
rrc_bosonic_db_buffer.py — Asynchronous buffering database ingestion program.
Queues RRC simulation receipts and writes them in buffered batches to the PostgreSQL database.
Uses asyncio for scheduling and delegates synchronous database operations to a thread pool.
"""
from __future__ import annotations
import argparse
import asyncio
import hashlib
import json
import logging
import os
import sys
import time
import uuid
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple
# Enable importing sibling modules
sys.path.insert(0, str(Path(__file__).parent))
try:
import psycopg2
import psycopg2.extras
from rds_connect import connect_rds
except ImportError:
# Fallback/Mock for local testing when psycopg2 is missing
psycopg2 = None
connect_rds = None
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s [%(name)s] %(message)s",
)
log = logging.getLogger("db_buffer")
def get_insert_query(table: str, keys: List[str]) -> str:
"""Generates parameterized INSERT queries with appropriate conflict resolution."""
fields = ", ".join(keys)
placeholders = ", ".join([f"%({k})s" for k in keys])
if table == "ene.packages":
return f"""
INSERT INTO {table} ({fields})
VALUES ({placeholders})
ON CONFLICT (pkg) DO UPDATE SET
title = EXCLUDED.title,
content = EXCLUDED.content,
content_hash = EXCLUDED.content_hash,
updated_at = EXCLUDED.updated_at,
verification_status = EXCLUDED.verification_status,
promotion_state = EXCLUDED.promotion_state
"""
elif table == "ene.receipts":
return f"""
INSERT INTO {table} ({fields})
VALUES ({placeholders})
ON CONFLICT (id) DO NOTHING
"""
elif table == "ene.crossing_weights":
return f"""
INSERT INTO {table} ({fields})
VALUES ({placeholders})
ON CONFLICT (recipe_id, row_index, col_index) DO UPDATE SET
weight_raw = EXCLUDED.weight_raw,
contractive_factor = EXCLUDED.contractive_factor
"""
elif table == "ene.eigensolid_snapshots":
return f"""
INSERT INTO {table} ({fields})
VALUES ({placeholders})
ON CONFLICT (id) DO NOTHING
"""
elif table == "ene.braid_strands":
return f"""
INSERT INTO {table} ({fields})
VALUES ({placeholders})
ON CONFLICT (snapshot_id, strand_index) DO UPDATE SET
phase_x = EXCLUDED.phase_x,
phase_y = EXCLUDED.phase_y
"""
else:
# Default fallback
return f"INSERT INTO {table} ({fields}) VALUES ({placeholders}) ON CONFLICT DO NOTHING"
class AsyncDatabaseBuffer:
"""Asynchronously buffers and writes database records in thread-safe batches."""
def __init__(
self,
batch_size: int = 10,
flush_interval: float = 2.0,
max_retries: int = 5,
retry_delay_base: float = 1.0,
dry_run: bool = False,
):
self.batch_size = batch_size
self.flush_interval = flush_interval
self.max_retries = max_retries
self.retry_delay_base = retry_delay_base
self.dry_run = dry_run
self.queue: asyncio.Queue[Tuple[str, Dict[str, Any]]] = asyncio.Queue()
self.conn: Optional[Any] = None
self.worker_task: Optional[asyncio.Task] = None
self.running = False
self._last_flush_time = time.time()
async def start(self):
"""Starts the background worker task."""
self.running = True
self.worker_task = asyncio.create_task(self._worker_loop())
log.info("Async database buffer coordinator started.")
async def stop(self):
"""Stops the worker and flushes any remaining items."""
self.running = False
if self.worker_task:
# Let the worker finish processing what's in the queue
self.worker_task.cancel()
try:
await self.worker_task
except asyncio.CancelledError:
pass
# Flush anything left over
await self._flush_remaining()
# Close connection
if self.conn:
try:
await asyncio.to_thread(self.conn.close)
log.info("Closed database connection.")
except Exception as e:
log.error(f"Error closing database connection: {e}")
self.conn = None
async def enqueue(self, table_name: str, row_data: Dict[str, Any]):
"""Puts an item to be inserted into the queue."""
await self.queue.put((table_name, row_data))
async def _worker_loop(self):
"""Main loop that gathers items and triggers flushes."""
batch: List[Tuple[str, Dict[str, Any]]] = []
while self.running:
try:
# Wait for an item, or timeout to trigger periodic flush
timeout = max(0.1, self.flush_interval - (time.time() - self._last_flush_time))
try:
item = await asyncio.wait_for(self.queue.get(), timeout=timeout)
batch.append(item)
self.queue.task_done()
except asyncio.TimeoutError:
# Flush interval reached
pass
# Flush conditions
if len(batch) >= self.batch_size or (batch and (time.time() - self._last_flush_time >= self.flush_interval)):
await self._flush_batch_with_retry(batch)
batch = []
self._last_flush_time = time.time()
except asyncio.CancelledError:
break
except Exception as e:
log.error(f"Error in worker loop: {e}", exc_info=True)
await asyncio.sleep(1.0)
# Catch remaining items
if batch:
await self._flush_batch_with_retry(batch)
async def _flush_remaining(self):
"""Drains the queue and flushes all items."""
batch = []
while not self.queue.empty():
item = self.queue.get_nowait()
batch.append(item)
self.queue.task_done()
if batch:
await self._flush_batch_with_retry(batch)
async def _flush_batch_with_retry(self, batch: List[Tuple[str, Dict[str, Any]]]):
"""Retries batch flushing with exponential backoff on database failure."""
if not batch:
return
log.info(f"Flushing batch of {len(batch)} records...")
if self.dry_run:
log.info(f"[DRY-RUN] Would have written {len(batch)} records.")
for table, data in batch:
log.debug(f"[DRY-RUN] Table: {table}, Keys: {list(data.keys())}")
return
for attempt in range(1, self.max_retries + 1):
try:
await asyncio.to_thread(self._flush_batch_sync, batch)
log.info("Batch flush successful.")
return
except Exception as e:
delay = self.retry_delay_base * (2 ** (attempt - 1))
log.warning(f"Database write attempt {attempt}/{self.max_retries} failed: {e}. Retrying in {delay:.1f}s...")
# Reset connection on failure so it attempts to reconnect
if self.conn:
try:
self.conn.close()
except Exception:
pass
self.conn = None
await asyncio.sleep(delay)
log.error(f"Failed to write batch of {len(batch)} records after {self.max_retries} attempts.")
# Optionally dump to a local fallback log file so we don't lose data
fallback_file = Path("shared-data/db_buffer_fallback.jsonl")
try:
fallback_file.parent.mkdir(parents=True, exist_ok=True)
with open(fallback_file, "a") as f:
for table, data in batch:
f.write(json.dumps({"table": table, "data": data, "failed_at": datetime.now(timezone.utc).isoformat()}) + "\n")
log.error(f"Dumped failed batch to fallback log: {fallback_file}")
except Exception as fe:
log.critical(f"Could not write to fallback log: {fe}")
def _flush_batch_sync(self, batch: List[Tuple[str, Dict[str, Any]]]):
"""Synchronous flush implementation. Executed inside a thread pool."""
if psycopg2 is None or connect_rds is None:
raise RuntimeError("psycopg2 is not installed or rds_connect is missing.")
if not self.conn:
log.info("Establishing database connection...")
self.conn = connect_rds(connect_timeout=5)
cur = self.conn.cursor()
try:
# Group entries by table name to optimize execution
grouped: Dict[str, List[Dict[str, Any]]] = {}
for table, data in batch:
grouped.setdefault(table, []).append(data)
for table, rows in grouped.items():
if not rows:
continue
# Extract keys from the first row (assuming all rows in the group have identical keys)
keys = list(rows[0].keys())
query = get_insert_query(table, keys)
log.debug(f"Executing batch insert on {table} for {len(rows)} rows.")
psycopg2.extras.execute_batch(cur, query, rows)
self.conn.commit()
except Exception as e:
self.conn.rollback()
# Catch duplicate content hash violations and skip them cleanly as successful dedups
if e.__class__.__name__ == "UniqueViolation" and "ene_pkg_hash_idx" in str(e):
log.info("Deduplication filter triggered: record with identical content_hash already exists. Skipping.")
return
raise e
finally:
cur.close()
# ── Helper to convert simulation receipts into database rows ─────────────────
def receipt_to_db_rows(receipt: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
"""Converts a standard RRC simulation receipt into ene.packages and ene.receipts rows."""
rows = []
# 1. Package Row
pkg_id = f"pkg_bosonic_tn_N{receipt['hardware_details']['N']}_{str(uuid.uuid4())[:8]}"
content = json.dumps(receipt, sort_keys=True)
content_hash = hashlib.sha256(content.encode("utf-8")).hexdigest()
pkg_row = {
"pkg": pkg_id,
"package_type": "bosonic_tensor_network",
"title": f"Bosonic Tensor Network Centrality (N = {receipt['hardware_details']['N']})",
"content": content,
"content_hash": content_hash,
"element": "METAL",
"tags": json.dumps(["bosonic_tensor", "centrality", f"N_{receipt['hardware_details']['N']}"]),
"source": "rrc_bosonic_tensor_gpu.py",
"created_at": receipt.get("computed_at", datetime.now(timezone.utc).isoformat()),
"updated_at": datetime.now(timezone.utc).isoformat(),
"verification_status": "verified",
"promotion_state": "held",
"domain": "RRC",
"archetype": "receipt",
}
rows.append(("ene.packages", pkg_row))
# 2. Receipt Row
rec_id = f"rec_bosonic_tn_N{receipt['hardware_details']['N']}_{str(uuid.uuid4())[:8]}"
# Derive input hash (from hardware details) and output hash (from receipt sha256)
input_preimage = json.dumps(receipt["hardware_details"], sort_keys=True)
input_hash = hashlib.sha256(input_preimage.encode("utf-8")).hexdigest()
rec_row = {
"id": rec_id,
"package_id": pkg_id,
"receipt_type": receipt.get("schema", "rrc_bosonic_tensor_gpu_receipt_v1"),
"receipt_hash": receipt.get("receipt_sha256", content_hash),
"input_hash": input_hash,
"output_hash": receipt.get("receipt_sha256", content_hash),
"toolchain": "wgpu-vulkan-rk4",
"verifier": "RTX 4070 SUPER",
"status": "verified",
"residual": json.dumps(receipt.get("entropies", [])),
"created_at": receipt.get("computed_at", datetime.now(timezone.utc).isoformat()),
}
rows.append(("ene.receipts", rec_row))
return rows
# ── CLI & Main Entry ──────────────────────────────────────────────────────────
async def async_main(args) -> int:
# Initialize the buffer coordinator
buffer = AsyncDatabaseBuffer(
batch_size=args.batch_size,
flush_interval=args.flush_interval,
max_retries=args.max_retries,
dry_run=args.dry_run,
)
await buffer.start()
try:
# Check if we are reading a specific receipt file
if args.file:
path = Path(args.file)
if not path.exists():
log.error(f"Input file does not exist: {path}")
return 1
with open(path, "r") as f:
receipt = json.load(f)
rows = receipt_to_db_rows(receipt)
for table, row in rows:
await buffer.enqueue(table, row)
log.info(f"Queued receipt from file: {path}")
# Check if we are reading from stdin (interactive/piped stream)
elif args.stdin:
log.info("Reading JSON/JSONL records from standard input (Ctrl+D to finish)...")
loop = asyncio.get_running_loop()
# Read line-by-line asynchronously
reader = asyncio.StreamReader()
protocol = asyncio.StreamReaderProtocol(reader)
await loop.connect_read_pipe(lambda: protocol, sys.stdin)
while True:
line_bytes = await reader.readline()
if not line_bytes:
break
line = line_bytes.decode("utf-8").strip()
if not line:
continue
try:
payload = json.loads(line)
# Support both raw table rows or formatted receipts
if "schema" in payload and "hardware_details" in payload:
rows = receipt_to_db_rows(payload)
for table, row in rows:
await buffer.enqueue(table, row)
elif "table" in payload and "data" in payload:
await buffer.enqueue(payload["table"], payload["data"])
else:
# Direct dictionary input -> treat as a general package
pkg_id = f"pkg_stream_{str(uuid.uuid4())[:8]}"
pkg_row = {
"pkg": pkg_id,
"package_type": "stream_item",
"title": "Streamed Database Payload",
"content": json.dumps(payload),
"content_hash": hashlib.sha256(json.dumps(payload).encode("utf-8")).hexdigest(),
"element": "GROUND",
"created_at": datetime.now(timezone.utc).isoformat(),
"updated_at": datetime.now(timezone.utc).isoformat(),
}
await buffer.enqueue("ene.packages", pkg_row)
except Exception as e:
log.error(f"Failed to parse stdin payload: {e}")
finally:
# Stop will flush all queued items
log.info("Stopping coordinator and flushing remaining items...")
await buffer.stop()
return 0
def main():
parser = argparse.ArgumentParser(description="Async Database Ingestion Buffer Shim")
parser.add_argument("--batch-size", type=int, default=10, help="Batch size for writing to DB (default: 10)")
parser.add_argument("--flush-interval", type=float, default=2.0, help="Interval in seconds for periodic flush (default: 2.0)")
parser.add_argument("--max-retries", type=int, default=5, help="Max database reconnection/write retries (default: 5)")
parser.add_argument("--dry-run", action="store_true", help="Run without writing to database (dry run)")
parser.add_argument("--file", type=str, help="Ingest a specific JSON receipt file")
parser.add_argument("--stdin", action="store_true", help="Stream payloads line-by-line from standard input")
args = parser.parse_args()
# If neither file nor stdin is provided, default to stdin if not a tty, otherwise print help
if not args.file and not args.stdin:
if not sys.stdin.isatty():
args.stdin = True
else:
parser.print_help()
sys.exit(1)
try:
sys.exit(asyncio.run(async_main(args)))
except KeyboardInterrupt:
log.info("Buffer program terminated by user.")
sys.exit(130)
if __name__ == "__main__":
main()