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
| 18 | 18 | import csv | |
| 19 | 19 | from pathlib import Path | |
| 20 | 20 | ||
| 21 | 21 | import psycopg2 | |
| 22 | 22 | ||
| 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) |