Review

RFID portal scan reimport after middleware gap

Blood Bank lost ~100k RFID portal observations during last week's middleware outage. This PR adds reimport_portal_scans so ops can reload the edge CSV export into unit_portal_scans before Monday's CAP mock survey, replacing the one-row insert_scan helper used in ad-hoc notebooks.

psycopgTier 4psycopgbulk-insertcopyperformance

Click a line to flag it, pick one or more labels, then submit. If the change looks correct, approve it.

marrowmap/jobs/reimport_portal_scans.py+22-9
1818import csv
1919from pathlib import Path
2020
2121import psycopg2
2222
23-def insert_scan(conn, unit_id, portal_id, scanned_at, direction, rssi_dbm):
24- with conn.cursor() as cur:
25- cur.execute(
26- "INSERT INTO unit_portal_scans"
27- " (unit_id, portal_id, scanned_at, direction, rssi_dbm)"
28- " VALUES (%s, %s, %s, %s, %s)",
29- (unit_id, portal_id, scanned_at, direction, rssi_dbm),
30- )
31- conn.commit()
23+def reimport_portal_scans(conn, export_path: Path) -> int:
24+ """Reload portal scans from edge CSV after a middleware gap."""
25+ with export_path.open(newline="") as f:
26+ reader = csv.DictReader(f)
27+ rows = [
28+ (r["unit_id"], r["portal_id"], r["scanned_at"],
29+ r["direction"], int(r["rssi_dbm"]))
30+ for r in reader
31+ ]
32+
33+ # executemany batches the parameter sets — fine for ~100k rows.
34+ with conn.cursor() as cur:
35+ cur.executemany(
36+ """
37+ INSERT INTO unit_portal_scans
38+ (unit_id, portal_id, scanned_at, direction, rssi_dbm)
39+ VALUES (%s, %s, %s, %s, %s)
40+ """,
41+ rows,
42+ )
43+ conn.commit()
44+ return len(rows)