Skip to content

feat(scripts): add bidirectional incremental DB sync (local <-> prod) - #25

Merged
dipto0321 merged 2 commits into
mainfrom
feat/bidirectional-db-sync
Jul 21, 2026
Merged

dipto0321 merged 2 commits into
mainfrom
feat/bidirectional-db-sync

Conversation

@dipto0321

Copy link
Copy Markdown
Owner

Summary

Replaces the one-way sync-prod.sh with a bidirectional, watermark-based incremental sync between local and production Postgres.

  • scripts/sync_db.py — sync engine: per-table INSERT ... ON CONFLICT DO UPDATE upserts, latest-updated_at-wins conflict resolution, INSERT-only (deletes never propagated), idempotent watermark advance via new sync_state table
  • Safety: refuses to run if local/prod Alembic versions differ; pg_dumps both DBs before any mutation and auto-restores both on failure (fault-injection tested)
  • alembic/versions/87927e56a6f2 — migration adding the sync_state watermark table (applies to prod automatically on deploy via the Dockerfile's alembic upgrade head)
  • scripts/sync-db.sh — wrapper loading local creds from .env; PROD_URL is passed at runtime and never stored
  • Makefile — sync-db, sync-db-dry, sync-db-status, sync-db-reset, plus an isolated test harness (sync-db-test-*) on port 5433

Test plan

  • Migration applied cleanly on a fresh test DB (all 11 tables incl. sync_state)
  • Dry-run correctly reported 1,351 pending rows local → test prod
  • Real sync copied all 1,351 rows; re-run was a no-op (idempotent)
  • Fault injection mid-sync triggered restore of both DBs from dumps
  • Real local DB (port 5432) untouched by the test harness
  • After merge/deploy: dry-run against real prod, then first real sync with --keep-dump

🤖 Generated with Claude Code

- scripts/sync_db.py: watermark-based incremental sync engine with
  INSERT ... ON CONFLICT upserts, latest-updated_at-wins conflicts,
  INSERT-only (deletes never propagated)
- pre-sync pg_dump of both DBs; verified auto-restore on failure via
  pg_restore --clean --if-exists (fault-injection tested)
- fetch from the older of the two watermarks so a fresh prod target
  gets a full scan instead of silently receiving nothing
- alembic migration for the sync_state watermark table
- scripts/sync-db.sh wrapper reads local creds from .env; PROD_URL is
  runtime-only and never stored
- Makefile: sync-db / sync-db-dry / sync-db-status / sync-db-reset plus
  an isolated test harness on port 5433; replaces one-way sync-prod
- CLAUDE.md: document usage

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- keep main's Makefile improvements (.SHELLFLAGS, db-status, shellcheck
  lint, safer migrations/clean) while replacing sync-prod/push-prod
  targets with the bidirectional sync-db targets
- remove scripts/push-to-prod.sh and scripts/sync-prod.sh: both one-way
  flows are superseded by scripts/sync_db.py
- update README and CLAUDE.md sync docs accordingly

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dipto0321
dipto0321 temporarily deployed to feat/bidirectional-db-sync - spendrift-be PR #25 July 21, 2026 14:23 — with Render Destroyed
@dipto0321
dipto0321 merged commit bae7199 into main Jul 21, 2026
@cocogitto-bot

cocogitto-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown

❌ Found 1 compliant commit and 1 non-compliant commits in bb3dd11...50b1c9a.

Commit 50b1c9a by @dipto0321 is not conform to the conventional commit specification :

  • message: `merge: resolve conflicts with main (sync tooling superseded)

  • keep main's Makefile improvements (.SHELLFLAGS, db-status, shellcheck
    lint, safer migrations/clean) while replacing sync-prod/push-prod
    targets with the bidirectional sync-db targets

  • remove scripts/push-to-prod.sh and scripts/sync-prod.sh: both one-way
    flows are superseded by scripts/sync_db.py

  • update README and CLAUDE.md sync docs accordingly

Co-Authored-By: Claude Fable 5 noreply@anthropic.com`

  • cause:
    Errored commit: not committed <dipto0321>
    	Commit message:'merge: resolve conflicts with main (sync tooling superseded)'
    	Error:Commit type `merge` not allowed
    

@dipto0321
dipto0321 deleted the feat/bidirectional-db-sync branch July 21, 2026 14:23

This branch was successfully deployed

No deployments
feat/bidirectional-db-sync - spendrift-be PR #25 — 50b1c9ab Deployed Jul 21, 2026 by dipto0321
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant