feat(database): add MySQL point-in-time recovery - #1144
Open
paulocsanz wants to merge 1 commit into
Open
Conversation
Collaborator
Author
|
Note on the thin check list: Verified locally on this exact commit in the meantime: |
paulocsanz
force-pushed
the
pcs/mysql-redis-ha-cli
branch
from
August 27, 2026 20:29
8e7a9f7 to
859f13e
Compare
paulocsanz
force-pushed
the
pcs/mysql-pitr-cli
branch
from
August 27, 2026 20:31
aa7c8b6 to
696bc3f
Compare
paulocsanz
force-pushed
the
pcs/mysql-redis-ha-cli
branch
from
August 31, 2026 19:31
859f13e to
fd5ee15
Compare
paulocsanz
force-pushed
the
pcs/mysql-pitr-cli
branch
from
August 31, 2026 19:34
696bc3f to
179ddfa
Compare
MySQL PITR is binlog archiving into a Railway bucket, enabled by the
`mysql-pitr` composable overlay. The generic `pitr` tree already drives
everything an engine's archive needs from its declared contract, so this is
mostly the declaration plus the two ways MySQL genuinely differs from Postgres.
Both differences become declarations rather than branches on the engine name:
- `supports_ha: false`. The image's archiver refuses to run whenever the
Group Replication seed list is set, so MySQL PITR is standalone-only.
Every path that would take (or follow) the rolling HA workflow now checks
this first -- `progress`/`cancel`/`clear` refuse before any network call,
and `enable`/`disable` refuse before the HA mutation -- so the user gets
one clear sentence instead of a server error from a workflow that was
never going to start.
- `probe_kind: None`. The live coverage probe in `pitr status` is pgBackRest
shelling into the container, which MySQL has no equivalent tool for.
Selecting the probe by declared kind means MySQL renders no coverage
section at all, rather than a probe run with another engine's tooling or a
fake "unavailable" for something it simply does not implement.
The archive variable contract needs no code: `BINLOG_ARCHIVE_` as the declared
prefix is enough for enabled-state detection and the enable overlay, and the
image-eligibility rules ship with the `mysql-pitr` template record. Notably
that template does NOT require a floating major tag, unlike postgres-pitr --
its image matrix only publishes exact minors, so a hardcoded "minor pins are
bad" rule would have refused every MySQL image.
Restore, backups and schedules ride the volume-instance mutations, which are
engine-agnostic server-side and needed no change.
paulocsanz
force-pushed
the
pcs/mysql-pitr-cli
branch
from
August 31, 2026 22:36
179ddfa to
c258497
Compare
Collaborator
Author
|
Rebased onto v5.47.0 ( |
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.
Stacked: 2 of 2, on top of #1143 — review that one first. Base is
pcs/mysql-redis-ha-cli, so the diff here is only the PITR delta (4 files, ~180 lines).What this adds
railway mysql pitr— binlog archiving into a Railway bucket, enabled by themysql-pitrcomposable overlay.The generic
pitrtree (from #1143) already drives everything an engine's archive needs from its declared contract, so this is mostly the declaration plus the two ways MySQL genuinely differs from Postgres. Both become declarations rather than branches on the engine name:supports_ha: false— the image's archiver refuses to run whenever the Group Replication seed list is set, so MySQL PITR is standalone-only. Every path that would take or follow the rolling HA workflow checks this first:progress/cancel/clearrefuse before any network callenable/disablerefuse before the HA mutationso you get one clear sentence instead of a server error from a workflow that was never going to start:
probe_kind: None— the live coverage probe inpitr statusis pgBackRest shelling into the container, which MySQL has no equivalent tool for. Selecting the probe by declared kind means MySQL renders no coverage section at all, rather than a probe run with another engine's tooling or a fake "unavailable" for something it simply doesn't implement.What needed no code
BINLOG_ARCHIVE_as the declared prefix is all the enabled-state detection and the enable overlay need.mysql-pitrtemplate record. Worth noting that template does not setrequireFloatingMajorTag, unlikepostgres-pitr— its image matrix only publishes exact minors, so the old hardcoded "minor pins are bad" rule would have refused every MySQL image. Reading the declaration is what makes both engines correct at once.Verification
cargo test— 1305 pass. New coverage for the per-engine archive-variable contrast (a Postgres service reads as unconfigured under MySQL's contract and vice versa), the HA-workflow gate refusing MySQL while passing Postgres, and probe-kind selection.cargo clippy/cargo fmtclean.mysql-pitrtemplate record was read from the live API; the fixtures mirror it.