-
Notifications
You must be signed in to change notification settings - Fork 0
Codex/phase2 platform hardening #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7510dc7
95209c2
43995ce
8b146b8
17ee5b5
6de789d
aac2710
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| # Runbook: Postgres Backup and Restore | ||
|
|
||
| **Purpose:** Capture and restore both the write-model and read-model Postgres databases for local drills and operator validation. | ||
| **Service affected:** telemetry-service, saga-orchestrator, bff, read-model-builder, asset-registry | ||
|
|
||
| --- | ||
|
|
||
| ## Scope | ||
|
|
||
| This runbook matches the local Docker stack: | ||
|
|
||
| - write DB container: `grainguard-postgres` | ||
| - read DB container: `grainguard-postgres-read` | ||
| - scripts: | ||
| - [`backup-postgres.sh`](infra/scripts/backup-postgres.sh) | ||
| - [`restore-postgres.sh`](infra/scripts/restore-postgres.sh) | ||
|
|
||
| These scripts create custom-format dumps for: | ||
|
|
||
| - `grainguard` | ||
| - `grainguard_read` | ||
|
|
||
| --- | ||
|
|
||
| ## Backup | ||
|
|
||
| ```bash | ||
| ./infra/scripts/backup-postgres.sh | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| ``` | ||
|
|
||
| Optional custom target: | ||
|
|
||
| ```bash | ||
| BACKUP_ROOT=/tmp/grainguard-backups ./infra/scripts/backup-postgres.sh | ||
| ``` | ||
|
|
||
| Expected output: | ||
|
|
||
| - `infra/backups/postgres/<timestamp>/grainguard.dump` | ||
| - `infra/backups/postgres/<timestamp>/grainguard_read.dump` | ||
| - `infra/backups/postgres/<timestamp>/metadata.env` | ||
|
|
||
| --- | ||
|
|
||
| ## Verify backup | ||
|
|
||
| ```bash | ||
| ls -lh infra/backups/postgres/<timestamp> | ||
| ``` | ||
|
|
||
| Optional quick integrity check: | ||
|
|
||
| ```bash | ||
| docker exec -i grainguard-postgres pg_restore -l < infra/backups/postgres/<timestamp>/grainguard.dump | head | ||
| docker exec -i grainguard-postgres-read pg_restore -l < infra/backups/postgres/<timestamp>/grainguard_read.dump | head | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Restore | ||
|
|
||
| Warning: this is destructive. The target database is dropped and recreated before restore. | ||
|
|
||
| Restore both databases: | ||
|
|
||
| ```bash | ||
| ./infra/scripts/restore-postgres.sh infra/backups/postgres/<timestamp> | ||
| ``` | ||
|
|
||
| Restore only the write DB: | ||
|
|
||
| ```bash | ||
| ./infra/scripts/restore-postgres.sh infra/backups/postgres/<timestamp> write | ||
| ``` | ||
|
|
||
| Restore only the read DB: | ||
|
|
||
| ```bash | ||
| ./infra/scripts/restore-postgres.sh infra/backups/postgres/<timestamp> read | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Verify recovery | ||
|
|
||
| ```bash | ||
| docker exec grainguard-postgres psql -U postgres -d grainguard -c '\dt' | ||
| docker exec grainguard-postgres-read psql -U postgres -d grainguard_read -c '\dt' | ||
| curl -fsS http://localhost:8086/health | ||
| curl -fsS http://localhost:4000/graphql -H 'content-type: application/json' -d '{"query":"{ __typename }"}' | ||
| ``` | ||
|
|
||
| Check application logs if a service still has stale connections: | ||
|
|
||
| ```bash | ||
| docker logs --tail 100 grainguard-gateway | ||
| docker logs --tail 100 grainguard-bff | ||
| docker logs --tail 100 grainguard-telemetry | ||
| ``` | ||
|
|
||
| If needed, restart readers and API services: | ||
|
|
||
| ```bash | ||
| docker compose -f infra/docker/docker-compose.yml restart gateway bff telemetry-service read-model-builder saga-orchestrator | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Escalate if | ||
|
|
||
| - `pg_restore` reports schema corruption | ||
| - backup files cannot be listed by `pg_restore -l` | ||
| - write DB restores successfully but read projections remain empty after service restart | ||
| - WAL/replication behavior is required rather than simple logical dump restore | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,93 @@ | ||||||||||||||
| # Runbook: Redis Backup and Restore | ||||||||||||||
|
|
||||||||||||||
| **Purpose:** Capture and restore the standalone Redis instance used by the local Docker stack for cache and lock validation drills. | ||||||||||||||
| **Service affected:** bff, saga-orchestrator, jobs-worker, workflow-alerts | ||||||||||||||
|
|
||||||||||||||
| --- | ||||||||||||||
|
|
||||||||||||||
| ## Scope | ||||||||||||||
|
|
||||||||||||||
| This runbook targets the standalone Redis container in local Docker: | ||||||||||||||
|
|
||||||||||||||
| - redis container: `grainguard-redis` | ||||||||||||||
| - scripts: | ||||||||||||||
| - [`backup-redis.sh`](infra/scripts/backup-redis.sh) | ||||||||||||||
| - [`restore-redis.sh`](infra/scripts/restore-redis.sh) | ||||||||||||||
|
Comment on lines
+13
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Markdown links won't resolve correctly. Same issue as the Postgres runbook—since this file is at 📝 Proposed fix - scripts:
- - [`backup-redis.sh`](infra/scripts/backup-redis.sh)
- - [`restore-redis.sh`](infra/scripts/restore-redis.sh)
+ - [`backup-redis.sh`](../../infra/scripts/backup-redis.sh)
+ - [`restore-redis.sh`](../../infra/scripts/restore-redis.sh)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| It does **not** back up the six-node Redis cluster used for cluster-mode experiments. | ||||||||||||||
|
|
||||||||||||||
| --- | ||||||||||||||
|
|
||||||||||||||
| ## Backup | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| ./infra/scripts/backup-redis.sh | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Optional custom target: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| BACKUP_ROOT=/tmp/grainguard-backups ./infra/scripts/backup-redis.sh | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Expected output: | ||||||||||||||
|
|
||||||||||||||
| - `infra/backups/redis/<timestamp>/dump.rdb` | ||||||||||||||
| - `infra/backups/redis/<timestamp>/metadata.env` | ||||||||||||||
|
|
||||||||||||||
| --- | ||||||||||||||
|
|
||||||||||||||
| ## Verify backup | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| ls -lh infra/backups/redis/<timestamp> | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Sanity check Redis before restore work: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| docker exec grainguard-redis redis-cli PING | ||||||||||||||
| docker exec grainguard-redis redis-cli DBSIZE | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| --- | ||||||||||||||
|
|
||||||||||||||
| ## Restore | ||||||||||||||
|
|
||||||||||||||
| Warning: this restarts the Redis container and can evict hot cache state and distributed locks. | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| ./infra/scripts/restore-redis.sh infra/backups/redis/<timestamp> | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| --- | ||||||||||||||
|
|
||||||||||||||
| ## Verify recovery | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| docker exec grainguard-redis redis-cli PING | ||||||||||||||
| docker exec grainguard-redis redis-cli DBSIZE | ||||||||||||||
| docker logs --tail 100 grainguard-bff | ||||||||||||||
| docker logs --tail 100 grainguard-saga-orchestrator | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Optional application check: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| curl -fsS http://localhost:8086/health | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| If application logs still show stale lock/cache issues, restart the consumers: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| docker compose -f infra/docker/docker-compose.yml restart bff saga-orchestrator jobs-worker workflow-alerts | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| --- | ||||||||||||||
|
|
||||||||||||||
| ## Escalate if | ||||||||||||||
|
|
||||||||||||||
| - Redis fails to start after replacing `dump.rdb` | ||||||||||||||
| - `PING` fails after restore | ||||||||||||||
| - cache recovers but saga lock keys remain permanently stale | ||||||||||||||
| - you need Redis Cluster restore, not standalone Redis restore | ||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.