Problem: currently, the following migration modes are defined:
- MIGRATION_OLD: Only read and write the old schema. The new schema need not
even exist. This is used from when the patch is merged until the schema
change is actually applied to the database.
- MIGRATION_WRITE_BOTH: Write both the old and new schema. Read the new
schema preferentially, falling back to the old. This is used while the
change is being tested, allowing easy roll-back to the old schema.
- MIGRATION_WRITE_NEW: Write only the new schema. Read the new schema
preferentially, falling back to the old. This is used while running the
maintenance script to migrate existing entries in the old schema to the
new schema.
- MIGRATION_NEW: Only read and write the new schema. The old schema (and the
feature flag) may now be removed.
This requires code to be written that can read the new schema, but falls back to the old schema. This is simple enough in many cases, but for storage layer code that exposes a getQueryInfo mothod, like RevisionStore::getQueryInfo, this is quite difficult, since it requires conditional joins.
In such cases, the code path with fallback executed MIGRATION_WRITE_BOTH and MIGRATION_WRITE_NEW is quite different from the post-migration code path later used by MIGRATION_NEW, resulting in the post-migration code not being tested in MIGRATION_WRITE_BOTH and MIGRATION_WRITE_NEW modes.
To solve this, a new MIGRATION_READ_NEW shojld be introduced, with the following semantics:
- MIGRATION_READ_NEW: Write both the old and new schema. Read only the new schema.
This is used to test operation based on the new schema, while still allowing easy roll-back to the
old schema.
Logically, this mode is an alternative to MIGRATION_WRITE_NEW. In natural order of the migration modes, it could be placed before or after MIGRATION_WRITE_NEW, but both placements have issues in the interpretation of the order: if MIGRATION_READ_NEW is placed before MIGRATION_WRITE_NEW, it disables reading from the old schema, but MIGRATION_WRITE_NEW enables it again. if placed after MIGRATION_WRITE_NEW, MIGRATION_READ_NEW re-enabled writing to the old schema after MIGRATION_WRITE_NEW disabled it.
A solution might be to re-define the semantic of all modes:
- MIGRATION_OLD: Only read and write the old schema. The new schema need not
even exist. This is used from when the patch is merged until the schema
change is actually applied to the database.
- MIGRATION_WRITE_BOTH: Write both the old and new schema. May try to read the
new schema, but must fall back to the old. This is used while the
change is being tested, allowing easy roll-back to the old schema. Maintenance script
to migrate existing entries in the old schema to the new schema may already be run.
- MIGRATION_WRITE_NEW: Write only the new schema. May try to read the
new schema, but must fall back to the old. This is used while running the
maintenance script to migrate existing entries in the old schema to the
new schema.
- MIGRATION_READ_NEW: Write both the old and new schema. Read only the new schema.
This is used to test operation based on the new schema, while still allowing easy roll-back to the
old schema.
- MIGRATION_NEW: Only read and write the new schema. The old schema (and the
feature flag) may now be removed.
Sensibly, migrations would be done either with read-fallback via the MIGRATION_WRITE_NEW stage, or without read-fallback with a MIGRATION_READ_NEW stage.
NOTE: all code that uses greater/smaller comparison on these constants should be changed to check for equality. Greater/smaller comparison can no longer be used safely.