feat(db): Redis and MinIO snapshot/restore dumpers (spec 15) - #105
Merged
Conversation
Extend the spec-15 data-lifecycle verbs beyond Postgres to the other stateful shared engines, behind the existing db.Dumper seam. - RedisDumper: shells `redis-cli` behind the injectable Runner. Snapshot captures a whole-instance RDB via `redis-cli --rdb` (SYNC, no server stop → other tenants undisturbed); restore streams it back through the mass-insert pipe (`sh -c "redis-cli … --pipe < dump"`, since the Runner has no stdin channel). Password rides REDISCLI_AUTH in the env, never argv. Preflight gives a 'redis-cli not found' remediation. Redis is the documented best-effort engine: a host client cannot cheaply carve one logical DB out of a live shared instance, and a byte-faithful whole-RDB reload would need a controlled restart the never-recreate guard forbids. - MinioDumper: uses the already-vendored pure-Go aws-sdk-go-v2 S3 client (no new external binary) behind an S3Factory seam. Snapshot lists+gets the tenant bucket's objects into a deterministic (key-sorted) tar under the content-addressed store; restore puts them back into the same bucket. Only the tenant bucket is read → project A can never capture project B. - snapshot.go: engine selection by kind (pg|redis|minio) — resolveTenant now derives the per-engine tenant namespace (pg db / redis index / minio bucket), tenantConn builds the right ConnInfo (redis auth-less by default), and SelectDumper wires the correct dumper. Dump file extension and SnapshotMeta.Kind follow the engine (.dump/.rdb/.tar). - cli/db.go: `db snapshot`/`db restore` gain `--kind pg|redis|minio` and select the dumper via orchestrate.SelectDumper. Tests: redis snapshot/restore argv + auth/env via a mock runner; minio snapshot/restore round-trip + determinism + tenant isolation via a mock S3; dumper-selection-by-engine; full-flow redis/minio Snapshot/Restore over the host-port overlay with the mock docker client. Host-port overlay reachability pattern and lock-first ledger writes are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gustavobertoi
added a commit
that referenced
this pull request
Jul 1, 2026
#103 (db reset/pull) and #105 (redis/minio dumpers) each passed CI alone but broke `main` when both merged — a semantic conflict git didn't flag: - #105 changed `resolveTenant` to take a `kind` and return `engine,label` (5 args / 6 returns); #103's `reset.go` still called the 4-arg form. - #105 replaced the `defaultPgDumper()` helper with `SelectDumper(d, kind)`; #103's `db pull` still called the removed helper. Both call sites now use the merged signatures (pg kind, extra returns discarded). Build, `go vet`, full `go test ./internal/...`, and `make determinism` all green. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Extends the spec-15
db snapshot/db restoredata-lifecycle verbs beyond Postgres to the other stateful shared engines, behind the existinginternal/dbDumperseam. Today only Postgres has a dumper; this adds Redis and MinIO and wires engine selection.RedisDumper (
internal/db/redis.go)redis-clibehind the injectableRunner(mirrorsPgDumper).redis-cli --rdb <out>— a whole-instance RDB via replication SYNC; does not stop the shared server, so other tenants are undisturbed.sh -c "redis-cli … --pipe < dump", because the sharedRunnerhas no stdin channel). Never restarts/bounces the container.REDISCLI_AUTHin the process env, never on argv.Preflightdegrades the db verbs only, with a one-lineredis-cli not foundremediation.MinioDumper (
internal/db/minio.go)S3Factoryseam.Wiring (
internal/orchestrate/snapshot.go,internal/cli/db.go)resolveTenantnow derives the per-engine tenant namespace (pg db / redis index / minio bucket);tenantConnbuilds the rightConnInfo(redis auth-less by default);SelectDumperreturns the correct dumper by--kind.SnapshotMeta.Kindfollow the engine (.dump/.rdb/.tar).db snapshot/db restoregain--kind pg|redis|minio.Why
Redis/MinIO tenants deserve the same per-project snapshot/restore lifecycle as Postgres; the
Dumperseam was designed for exactly this extension.How tested
CGO_ENABLED=1 go test ./internal/...(+-raceon db/orchestrate/cli) all green;CGO_ENABLED=0 go build ./...,go vet ./...,gofmt -lclean.Snapshot/Restoreover the host-port overlay with the mock docker client.No changes to
internal/generateortemplates/, so generated-artifact determinism is unaffected.🤖 Generated with Claude Code