Skip to content

Switchover mechanism, for use when primary itself is doing switchover - #83

Open
serprex wants to merge 5 commits into
mainfrom
switchover
Open

Switchover mechanism, for use when primary itself is doing switchover#83
serprex wants to merge 5 commits into
mainfrom
switchover

Conversation

@serprex

@serprex serprex commented Aug 7, 2026

Copy link
Copy Markdown
Member

Includes support for changing source/destination config without restart

@serprex

serprex commented Aug 17, 2026

Copy link
Copy Markdown
Member Author

depends on ClickHouse/wal-rus/pull/24

@serprex serprex changed the title Start on plans/future/failover.md Switchover mechanism, for use when primary itself is doing switchover Aug 17, 2026
@serprex
serprex marked this pull request as ready for review August 17, 2026 20:43
Comment thread plans/failover.md
configured `[source] slot` name, when slot mode is on. Physical slots
are never synchronized to a standby at any PostgreSQL version; PG 17
slot sync covers logical slots created with `failover = true`
(`src/backend/replication/logical/slotsync.c`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we create the slot on the standby target before hand? We could make the slot on the standby all the time. We can keep the wal available on primary and standby in sync. This could help avoid wal hole problem.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes but then you need to report slot progress to both primary & standbys

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, would that be a big issue?

Comment thread src/backfill/backfill_types.rs Outdated
Comment thread src/config.rs Outdated
Comment thread src/source/transition.rs
Implements support for changing source/destination config without restart

Some issues being avoided:
- boundary aligned fork needs zero crc
- pre-commit restart skipping ancestor crossing, ie
1. manifest still says timeline 1, crossing commit has not happened
2. floor is start of segment containing fork, common when `C` and `F` share a segment
3. target is promoted to timeline 2
4. daemon dies after promotion while paused or waiting inside barrier
5. boot reads live history, `tli_of_segment(floor)` returns timeline 2 because descendant owns fork segment filename
6. condition accepts timeline 2 despite manifest still naming timeline 1
7. pump starts directly on timeline 2, so it never performs timeline 1 to 2
Block on erroneous scenarios so daemon still accessible,
pause/resume to retry. Improve handling stop/promote/start

Protocol extends status with necessary information for controlplane doing switchover

Add more validation. Test more restart scenarios
Comment thread src/config.rs
Comment thread src/config.rs
use ahash::{HashMap, HashMapExt, HashSet};

/// Source PG connection, `[source]` minus `slot`. Live: a reload that moves
/// the endpoint swaps the pump's `SourceFeed` at a chunk boundary and points

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why slot isn't there? it also gets updated? is it because if it changes we do something different?

Comment thread src/config.rs
pub struct CliOverrides {
pub drop_table_strategy: Option<String>,
pub flush_timeout: Option<Duration>,
/// `--slot`. Set means the operator pinned the slot name for this process,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment not required. i don't think we need flush_timeout here either.
in the headdoc above it's mentioned that source_slot is updatable? but here we are negating any updates.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is the only reason for source_slot to be separate from SourceConn, lets just keep one source_slot here and update CliOverrides later accordingly.

Comment thread src/source/wal_stream.rs
self.timeline
}

pub fn seg_size(&self) -> u64 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i can't see the function being used anywhere

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transition.rs

Comment thread src/bin/stream.rs
begin: u64,
}

/// Dial the source and resume at `resume_lsn`, proving continuity first:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also implemented in transition.rs. we can move this implementation there, reduce some burden from stream.rs
in general there's a lot of stuff here in stream.rs from transition.rs

pub fn identity(&self) -> server::Identity {
server::Identity {
system_id: self.system_identifier.clone(),
timeline: self.timeline,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can keep timeline and system_id in walshadow status? would help with ubicloud for orchestration. and any other things that you might think might be helpful.

Comment thread src/ops/metrics.rs
writeln!(s, "{name}{{reason=\"{reason}\"}} {v}").unwrap();
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also update grafana dashboard to consume it?

Comment thread src/source/source_feed.rs Outdated
Comment thread src/bin/stream.rs
slot = source_slot.as_deref(),
"crossed source timeline",
);
history = crossing.history;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

source_swap_pending should also be cleared here no?

Comment thread src/bin/stream.rs
)
.await?;
}
if ancestor_ended {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could be over engineering, but there's a lot of a of these state parameters, can we do something about it? like some state machine?

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.

2 participants