Files
ruoyi-vue-pro/docs/education/migration/issues/EDU-005-flyway-takeover-decision.md

12 KiB
Raw Blame History

EDU-005 — Decide PostgreSQL/Flyway takeover strategy

  • Status: done — forward-only takeover and EDU-006 version plan accepted
  • Type: decision
  • Phase: 1 / Phase 2 prerequisite
  • Blockers: EDU-002

Decision outcome

Education schema ownership moves exclusively to module-owned PostgreSQL Flyway migrations under yudao-module-education/src/main/resources/db/migration/education/. The existing root sql/postgresql/education/ files are classified as manual bootstrap/design history, not Flyway history. The MySQL files are obsolete archival artifacts and must not remain in operational instructions.

V4010__initialize_education_flyway.sql and V4020__create_native_catalog.sql are uncommitted working-tree resources in this checkout, and the inspected local disposable PostgreSQL database has no flyway_schema_history table and no Education tables. This proves neither migration ran in that database, but it does not prove they never ran in another environment. To avoid assigning a second meaning to a potentially distributed version, EDU-006 must preserve both files byte-for-byte and allocate new work from V4030.

No migration or production schema change was executed by EDU-005.

Evidence and classification

Artifact Verified state Classification Forward disposition
V4010__initialize_education_flyway.sql Untracked module resource; contains only SELECT 1; packaged in current target/classes Potentially distributed Flyway history; execution unverified Freeze byte-for-byte; do not repurpose
V4020__create_native_catalog.sql Untracked module resource; owns 11 native catalog tables; differs materially from manual 008 Potentially distributed Flyway history; execution unverified Freeze byte-for-byte; do not replace with manual 008
sql/postgresql/education/002005, 007, 009 Untracked manual scripts implementing the current Practice/report/wrong/favorite/unified-idempotency model in stages Manual bootstrap/design history, not active Flyway Consolidate the approved final state into higher Flyway versions; do not copy the obsolete intermediate tables as fresh schema
sql/postgresql/education/008 Manual native-catalog design predating/diverging from V4020 Superseded manual design V4020 remains the only intended Flyway owner of native catalog schema
sql/postgresql/education/000001 Placeholder schema plus menu/tenant seed scripts Manual bootstrap/seed history Do not create a separate education schema; evaluate the still-used education:capability menu seed separately
sql/mysql/education/** Historical MySQL schema, seeds, and rollback scripts Obsolete archive Remove from runbooks; retain only if explicitly labeled non-operational archive
src/test/resources/sql/postgresql/create_tables.sql EDU-016 disposable test bridge; 140 PostgreSQL persistence tests passed against it Temporary test fixture Replace with Flyway-driven test setup after EDU-006 proves equivalent schema
Docker init mounts for manual Education SQL Dirty Docker configuration mounts 000009 directly Obsolete delivery path Remove Education manual mounts after Flyway takeover; the server owns migration execution

Approved schema owner map

V4020 owner — unchanged

V4020 exclusively owns the native catalog tables:

  • education_region, education_school, education_major, education_subject, education_category;
  • education_content_entry, education_content_node;
  • education_question_collection, education_question, education_practice_blueprint;
  • education_question_collection_question.

EDU-006 does not fold Practice schema into V4020 and does not silently substitute manual 008.

EDU-006 new owner — Practice final state

The new Practice migration owns the final runtime shape of:

  • education_practice_session and education_practice_question;
  • education_practice_report and education_practice_report_detail;
  • education_wrong_question and education_wrong_question_idempotency;
  • education_favorite;
  • education_idempotency.

The approved fresh schema does not create education_answer_idempotency or education_submit_idempotency. Current production services use IdempotencyStoreMapper and education_idempotency; the old DOs/Mappers are unused compatibility residue and must be removed or explicitly isolated during EDU-006.

The migration must include all columns already required by runtime code and the proven EDU-016 bridge, including client_sequence, last_client_sequence, review_fingerprint, protected answer snapshots, report content snapshots, JSONB fields, tenant IDs, logical-delete fields, and observed conflict/query indexes.

Version plan for EDU-006

Version numbers are project-wide. With V4020 frozen, the next allocated version is:

  1. V4030 — Practice core-loop final schema and adoption
    • Create the final tables, columns, constraints, and indexes listed above.
    • Be adoption-aware for databases that contain manually bootstrapped Practice tables.
    • Validate existing column types and required uniqueness before treating existing objects as compatible; fail closed on incompatible shapes rather than silently accepting them.
    • Backfill the unified idempotency table from legacy answer/submit tables when those tables exist.
    • Preserve old idempotency tables during the initial adoption migration; do not make data destruction a prerequisite for application rollout.
  2. V4040 — deterministic Education capability seed, only if still approved
    • Seed menu IDs 6800/6801 idempotently if the existing EducationCapabilityController remains an exposed administrator capability.
    • Keep role assignment outside the migration.
    • If the capability endpoint/menu is retired before EDU-006, omit this migration rather than seeding dead UI.
  3. Later forward cleanup migration
    • Drop legacy education_answer_idempotency and education_submit_idempotency only after every adopted environment has verified backfill counts, the application no longer contains active references, and a separately reviewed forward cleanup is approved.

If repository-wide migration inventory changes before implementation, EDU-006 must re-run the version scan and use the next unused project-wide version instead of blindly taking V4030/V4040.

Existing-environment takeover classes

baseline-on-migrate=true with baseline 4009 is an adoption aid, not proof that Education objects match Flyway.

  1. Empty or platform-only database, no Education tables
    • Use baseline 4009 only when the non-empty platform schema requires adoption.
    • Run V4010, V4020, then V4030+ normally.
  2. Manual Practice tables exist, native catalog tables do not
    • Baseline 4009 may be used.
    • V4020 creates catalog objects; V4030 validates/adopts Practice objects and performs required backfills.
  3. Manual catalog tables equivalent to V4020 already exist, no Flyway history
    • Do not run V4020 into colliding tables.
    • First compare the actual schema with the frozen V4020 contract.
    • For a verified equivalent environment, use a one-time environment-specific baseline at 4020, then run V4030+. This records adoption, not execution of V4020, and must be documented per environment.
    • If the schema is not equivalent, correct it through an explicit higher-version adoption path; do not falsify history or edit V4020.
  4. Flyway history already contains V4010 and/or V4020
    • Compare script/checksum/success with the frozen resources.
    • Never edit an executed script. Any mismatch or failed row blocks rollout until an environment-specific repair decision is reviewed.
  5. Unknown shared environment
    • No migration rollout is authorized until its Education tables and flyway_schema_history are inventoried.

After all existing environments carry an explicit baseline/history record, changing baseline-on-migrate to false is a separate reviewed configuration ticket. validate-on-migrate=true, clean-disabled=true, and out-of-order=false remain mandatory.

Data compatibility and backfill rules

  • Copy legacy answer and submit idempotency rows into education_idempotency with deterministic operation values and ON CONFLICT ... DO NOTHING only after verifying duplicate-key/request-hash compatibility.
  • Preserve original IDs only if required by references; otherwise allow identity allocation and verify semantic row counts by operation.
  • Existing Practice tables must be compared with the final DO/Mapper contract, not merely checked for table-name existence.
  • JSON snapshot fields use PostgreSQL JSONB where current runtime/test behavior expects JSONB normalization.
  • Tenant-scoped uniqueness includes tenant_id where the business key is tenant-local. education_practice_report uses (tenant_id, session_id) as the final unique report key.
  • Do not copy Supabase RLS. Framework tenant isolation remains primary; database constraints enforce integrity and idempotency.
  • No destructive rollback SQL is delivered. Recovery is application rollback plus a higher-version forward correction.

Documentation and operational corrections

EDU-006 must update operational documentation in the same slice:

  • replace yudao-module-education/README.md MySQL apply/rollback commands with Flyway/PostgreSQL forward-only instructions;
  • remove the manual Education SQL mounts from script/docker/docker-compose.yml so a fresh Docker database is not initialized outside Flyway before server startup;
  • label sql/postgresql/education/ and sql/mysql/education/ as non-operational history or move them to an explicitly archival location without rewriting history;
  • replace the EDU-016 temporary PostgreSQL schema bridge with Flyway-driven setup after equivalence is proven;
  • state per environment whether Flyway was actually run, validated, or only packaged/compiled.

Required EDU-006 verification

Static and build gates:

git diff --check
mvn -pl yudao-module-education -am -DskipTests clean package
find yudao-module-education/target/classes/db/migration/education -type f -print
mvn -pl yudao-server -am -DskipTests clean compile

Real disposable PostgreSQL gate:

  1. initialize a disposable platform database or approved baseline fixture;
  2. run Flyway migrate using the server's exact migration locations and PostgreSQL driver;
  3. run Flyway validate;
  4. inspect flyway_schema_history with version, script, checksum, and success;
  5. inspect all approved tables, columns, constraints, indexes, and backfill counts;
  6. run the EDU-016 PostgreSQL persistence suite against the migrated schema;
  7. test at least the empty/platform-only path and one representative manually bootstrapped adoption path.

Only these real successful executions may be reported as migration success.

Acceptance criteria

  • No published or potentially distributed migration is authorized for editing.
  • Every required table/index/constraint/seed has one intended Flyway owner and version range.
  • Manual SQL is not silently treated as executed history.
  • The plan includes migration packaging and real PostgreSQL execution evidence requirements.
  • Documentation correction scope is explicit.

Verification performed by EDU-005

  • Read project Flyway rules, local/dev Flyway configuration, server dependencies, all active migration locations, manual PostgreSQL/MySQL artifacts, core-loop DOs/Mappers, PostgreSQL test bridge, Docker initialization, Git history, and dirty-tree state.
  • Inspected the reachable disposable postgresdb container. Target identity was database postgres, user postgres, schema public; it contained no flyway_schema_history relation and no Education tables. Container startup logs state that /docker-entrypoint-initdb.d/* was ignored because the volume was already initialized.
  • Confirmed V4010/V4020 are currently packaged under target/classes/db/migration/education/ from a prior build.
  • Did not modify migration SQL, application code, server configuration, Docker configuration, or any database object.
  • Did not run Flyway migrate/validate and does not claim a successful database migration.

Risk and rollback

  • Risk: High. Existing manually initialized databases may have partially overlapping or divergent table shapes, and a false baseline can hide incompatibility.
  • Rollback: No rollback is required for this decision-only ticket. EDU-006 uses forward migrations, preserves legacy idempotency tables during first adoption, and supports application rollback without flyway clean or destructive down scripts.