feat: 레거시 DB 순차 증분 이관 CLI 추가

This commit is contained in:
2026-08-18 12:35:24 +00:00
parent e910a635e6
commit da0e32f422
21 changed files with 1375 additions and 104 deletions
+70 -5
View File
@@ -1,14 +1,17 @@
# Legacy DB migration CLI
This package migrates the long-lived parts of a restored ref MariaDB database
into the core2026 PostgreSQL schemas. It is CLI-only; no HTTP or administrator
route invokes it.
This package migrates the long-lived parts of a restored or still-readable ref
MariaDB database into the core2026 PostgreSQL schemas. It is CLI-only; no HTTP
or administrator route invokes it. `run-plan` is the normal operator entrypoint:
it validates every configured connection first, then runs Gateway followed by
the enabled game profiles in the official order.
The default mode is a read-only dry-run. `--apply` is required before any target
write. PostgreSQL advisory locks prevent two applies for the same target.
Gateway writes are transactional. Game archive writes and their completed
`legacy_archive.import_run` record are transactional. Stable legacy keys make
completed or interrupted runs repeatable.
`legacy_archive.import_run` record are transactional. Both paths record an
import run and durable per-table checkpoints. Stable legacy keys make completed
or interrupted runs repeatable.
## Source restore
@@ -28,6 +31,64 @@ keeps the original dump as the recovery source.
Database URLs belong in a Git-ignored environment file or injected process
environment. They are deliberately not accepted as command-line flags.
## Ordered migration plan
Copy `migration-plan.example.json` to the Git-ignored `migration-plan.json`.
Set its mode to 0600, then enter the MariaDB host, port, database and user for
Gateway and each game profile. A password can come from a separate mode-0600
file (recommended), an environment variable, or directly from the mode-0600
plan. Target PostgreSQL URLs remain in the named environment variables.
```sh
mkdir -p tools/legacy-db-migration/secrets
chmod 700 tools/legacy-db-migration/secrets
cp tools/legacy-db-migration/migration-plan.example.json \
tools/legacy-db-migration/migration-plan.json
chmod 600 tools/legacy-db-migration/migration-plan.json
chmod 600 tools/legacy-db-migration/secrets/*
pnpm migrate:legacy -- check-plan \
--config tools/legacy-db-migration/migration-plan.json
pnpm migrate:legacy -- run-plan \
--config tools/legacy-db-migration/migration-plan.json --mode full
pnpm migrate:legacy -- run-plan \
--config tools/legacy-db-migration/migration-plan.json --mode full --apply
```
`check-plan` opens every source and target without writing. `run-plan` also
preflights every stage before the first import, is a dry-run without `--apply`,
and stops at the first failed stage. Completed earlier stages remain committed;
rerunning is safe because the Gateway and each profile have independent locks,
transactions and run records. The JSON output never includes a connection URL
or password.
For a later delta, keep the same `sourceSet`, connection identity and source
databases, restore or expose the newer snapshot, then run:
```sh
pnpm migrate:legacy -- run-plan \
--config tools/legacy-db-migration/migration-plan.json --mode incremental
pnpm migrate:legacy -- run-plan \
--config tools/legacy-db-migration/migration-plan.json --mode incremental --apply
```
Incremental mode refuses to start without checkpoints from a completed full
apply. It also refuses a changed host/database/user identity or a source table
whose maximum ID moved behind its checkpoint. Password rotation does not change
the source fingerprint.
| Source data | Incremental policy |
| --------------------------------------------- | --------------------------------------------------------------------- |
| `member_log` | Read only IDs after the committed high-water mark. |
| game archive/event-history tables | Read only IDs after the profile checkpoint. |
| `member`, root/game `storage`, `system`, bans | Rescan and idempotently upsert because old rows are mutable. |
| `ng_games` | Rescan because a season row can gain its final winner after creation. |
The append policy assumes Ref primary keys are never reused and completed
archive rows are immutable. Incremental mode does not mirror source deletions.
If either assumption is false, take a new reviewed backup and run full mode;
do not edit checkpoint rows by hand.
## Commands
```sh
@@ -45,6 +106,10 @@ the selected current profile schema. Accepted profiles are
`che,kwe,pwe,twe,nya,pya,hwe`; run them separately against the same PostgreSQL
database.
The individual commands also accept `--mode incremental` and `--source-key`.
Use the ordered plan for production so every configured connection is checked
before the Gateway stage starts.
### Isolated current-season comparison fixture
`current-season-fixture` is separate from the long-lived archive migration. It