Skip to content

Introduce SourceRuntime to own the source connection (GTID failover 1/3)#451

Open
driv3r wants to merge 1 commit into
gtid-stage5-replica-progressfrom
gtid-stage6-master-failover
Open

Introduce SourceRuntime to own the source connection (GTID failover 1/3)#451
driv3r wants to merge 1 commit into
gtid-stage5-replica-progressfrom
gtid-stage6-master-failover

Conversation

@driv3r

@driv3r driv3r commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

What

Introduces SourceRuntime, a single owner of Ghostferry's current source connection and its DatabaseConfig.

This is PR 1 of 3 reworking master failover recovery into a clean abstraction:

  1. This PR — introduce SourceRuntime (no consumers migrated, behavior-neutral).
  2. Migrate source consumers (data iterator, cursors, verifiers) to depend on SourceRuntime.
  3. GTID master failover recovery implemented as an in-process resume onto a new source session, plus a Ruby integration test.

Supersedes the earlier single-PR spike (streamer recovery + hand-picked Ferry-wide field swap), which proved what needs to move but wired every source field by hand. The spike is preserved on the backup/gtid-failover-spike-964f52d branch / failover-spike-backup tag for reference.

Why

Ghostferry's source *sql.DB and *DatabaseConfig are copied by value into every consumer: the data iterator, each cursor, the inline/iterative/checksum verifiers, and ad-hoc SHOW CREATE queries. That is fine while the source never changes, but a source master failover must repoint every consumer at a promoted writer atomically. Doing that by editing a field on each consumer is brittle — every future source consumer would have to remember to join the swap.

Centralising ownership behind one type inverts that: consumers ask the runtime for the current source instead of holding stale copies.

How

SourceRuntime (source_runtime.go):

  • Holds the source *sql.DB + *DatabaseConfig behind concurrency-safe accessors (DB(), Config()).
  • Replace(config, logger) opens a new source connection, installs it, and retires (retains, does not close) the previous handle, since in-flight cursors and cached prepared statements may still reference it.
  • CloseRetired() releases retired handles at a safe point (teardown).

Ferry wiring:

  • Initialize constructs a SourceRuntime alongside SourceDB.
  • Ferry.SourceRuntime() exposes it.
  • No consumer is migratedSourceDB / Config.Source remain authoritative, so this PR changes no runtime behavior.

Testing

  • Unit tests for accessors, Replace (install + retire + multi-swap retention), CloseRetired drain, and nil-initial handling; -race clean.
  • Full test/go integration suite passes in both file_position and gtid modes (confirming behavior neutrality).
  • go build + gofmt clean.

@driv3r driv3r changed the title Add opt-in master failover recovery (GTID stage 6) Add opt-in master failover recovery with Ferry-wide source swap (GTID stage 6) Jul 23, 2026
Ghostferry's source connection and its DatabaseConfig are currently
copied by value into every consumer (data iterator, cursors, verifiers,
ad-hoc SHOW CREATE queries). That is fine while the source never changes,
but a source master failover needs to repoint every consumer at a newly
promoted writer atomically, which today would mean hand-editing a field
on each one.

Introduce SourceRuntime as the future single owner of "the current
source": it holds the source *sql.DB and *DatabaseConfig behind
concurrency-safe accessors and offers Replace to swap in a new source
(opening the new connection and retaining the old handle rather than
closing it, since in-flight cursors and cached statements may still
reference it) plus CloseRetired to release retired handles at teardown.

This change only introduces the type and has the Ferry construct/hold one
alongside SourceDB in Initialize; no consumer is migrated yet, so behavior
is unchanged. Follow-up changes migrate consumers to the runtime and then
use Replace to implement master failover.
@driv3r
driv3r force-pushed the gtid-stage6-master-failover branch from 964f52d to b465681 Compare July 23, 2026 14:29
@driv3r driv3r changed the title Add opt-in master failover recovery with Ferry-wide source swap (GTID stage 6) Introduce SourceRuntime to own the source connection (GTID failover 1/3) Jul 23, 2026
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