Skip to content

feat(server): add plikd migrate command for live backend-to-backend migration#728

Open
camathieu wants to merge 1 commit intomasterfrom
feat/migrate-command
Open

feat(server): add plikd migrate command for live backend-to-backend migration#728
camathieu wants to merge 1 commit intomasterfrom
feat/migrate-command

Conversation

@camathieu
Copy link
Copy Markdown
Member

What

Adds a new plikd migrate CLI command for direct, live backend-to-backend
migration of metadata and file data — no intermediate archives needed.

Why

Currently the only way to move data between backends is via plikd export +
plikd import, which requires writing a compressed intermediate archive to disk.
For large deployments (e.g. migrating from SQLite → PostgreSQL, or local files → S3)
this is wasteful and slow. The new migrate command streams data directly between
backends, using a parallel worker pool for file blobs.

Changes

server/cmd/migrate.go — CLI command

  • plikd migrate --to <target.cfg> migrates both metadata and file data
  • Flags: --metadata-only, --data-only, --workers N (default 4), --dry-run, --ignore-errors
  • --dry-run enumerates all items and prints them without writing anything
  • --ignore-errors lets the migration continue past individual record/file failures (useful for re-runs)

server/metadata/migrator.go — Metadata streamer

  • Migrates records in FK-safe order: users → tokens → uploads (unscoped) → files → settings
  • CLI auth sessions excluded (ephemeral)
  • Uses the backend's own logger (src.log) for progress output

server/data/migrator.go — File blob parallel copier

  • Worker pool with context-based cancellation (no panic/recover)
  • Copies uploaded and removed files; skips missing, uploading, deleted
  • Reports bytes transferred alongside file counts

Testing

  • Unit testsserver/metadata/migrator_test.go and server/data/migrator_test.go
    cover: basic migration, soft-deleted uploads (FK integrity), dry-run, ignore-errors,
    status-based filtering, multi-worker concurrency
  • E2E testtesting/migrate/run.sh uses plikd fakedb to seed a source SQLite DB,
    runs plikd migrate, verifies record counts match, dry-run writes nothing, re-run
    with --ignore-errors is idempotent. No Docker required; included in test_backends.sh.

Docs

  • New guide: docs/operations/migration.md with 4 real-world scenarios
    (SQLite→PostgreSQL, local→S3, full migration, resuming a failed run)
  • Side-nav entry added to docs
  • Cross-link from the metadata backends page

…igration

Add a new `plikd migrate` CLI command that migrates metadata and file data
directly between backends without intermediate archive files.

## Metadata migration (server/metadata/migrator.go)
- Streams all records from source to destination in FK-safe order:
  users → tokens → uploads (unscoped) → files → settings
- Uses src.log.Infof/Warningf for progress (consistent with exporter/importer)
- Supports --ignore-errors to skip individual record failures

## Data migration (server/data/migrator.go)
- Parallel worker pool (default: 4, configurable via --workers)
- Uses context cancellation for clean fatal-error propagation (no panics)
- Copies only `uploaded` and `removed` files (both have backing data)
- Skips `missing`, `uploading`, `deleted` (no data in backend)
- Supports --dry-run and --ignore-errors

## CLI command (server/cmd/migrate.go)
- Flags: --to (required), --metadata-only, --data-only, --workers, --dry-run, --ignore-errors
- --data-only and --metadata-only are mutually exclusive
- Dry-run enumerates and prints all items without writing; errors are reported

## Tests
- server/metadata/migrator_test.go: basic migration, soft-deleted uploads, ignore-errors
- server/data/migrator_test.go: blob streaming, status filtering, dry-run, ignore-errors,
  multi-worker concurrency
- testing/migrate/run.sh: e2e test using `plikd fakedb` to seed a source SQLite DB,
  migrate to destination, verify record counts, dry-run writes nothing, re-run is idempotent

## Docs
- docs/operations/migration.md: full migration guide with 4 real-world scenarios
- Side-nav entry in docs/.vitepress/config.js
- Cross-link in docs/backends/metadata.md
- server/ARCHITECTURE.md + testing/ARCHITECTURE.md updated
- AGENTS.md Key Files table updated
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