Skip to content

Commit 323c60c

Browse files
committed
initialwq
1 parent d793088 commit 323c60c

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

compute_tools/src/compute_promote.rs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl ComputeNode {
4949
task.borrow().clone()
5050
}
5151

52-
async fn promote_impl(&self, mut cfg: PromoteConfig) -> Result<()> {
52+
async fn promote_impl(&self, cfg: PromoteConfig) -> Result<()> {
5353
{
5454
let state = self.state.lock().unwrap();
5555
let mode = &state.pspec.as_ref().unwrap().spec.mode;
@@ -134,25 +134,41 @@ impl ComputeNode {
134134
{
135135
let mut state = self.state.lock().unwrap();
136136
let spec = &mut state.pspec.as_mut().unwrap().spec;
137-
spec.mode = ComputeMode::Primary;
138-
let new_conf = cfg.spec.cluster.postgresql_conf.as_mut().unwrap();
139-
let existing_conf = spec.cluster.postgresql_conf.as_ref().unwrap();
140-
Self::merge_spec(new_conf, existing_conf);
137+
tracing::debug!("old spec: {:#?}, new spec: {:#?}", spec, cfg.spec);
138+
139+
// Local setup has different ports for pg process (port=) for primary and secondary.
140+
// In order for promotion to work, new spec needs to have port= with value for secondary
141+
if cfg!(feature = "testing") {
142+
let Some(existing_conf) = spec.cluster.postgresql_conf.as_ref() else {
143+
bail!("spec.cluster.postgresql_conf missing for endpoint");
144+
};
145+
let existing_conf = existing_conf.clone();
146+
147+
*spec = cfg.spec;
148+
149+
let Some(new_conf) = spec.cluster.postgresql_conf.as_mut() else {
150+
bail!("local setup was requested, but spec.cluster.postgresql_conf was not passed");
151+
};
152+
Self::update_conf_from_existing(new_conf, existing_conf);
153+
} else {
154+
*spec = cfg.spec;
155+
}
156+
157+
tracing::debug!("applied spec: {:#?}", spec);
141158
}
159+
142160
info!("applied new spec, reconfiguring as primary");
143161
self.reconfigure()
144162
}
145163

146164
/// Merge old and new Postgres conf specs to apply on secondary.
147-
/// Change new spec's port and safekeepers since they are supplied
148-
/// differenly
149-
fn merge_spec(new_conf: &mut String, existing_conf: &str) {
165+
/// Change new spec's port to old spec's ports, as they're different in local setup and
166+
/// if we don't change it, promoted primary connection won't be established
167+
fn update_conf_from_existing(new_conf: &mut String, existing_conf: String) {
150168
let mut new_conf_set: HashMap<&str, &str> = new_conf
151169
.split_terminator('\n')
152170
.map(|e| e.split_once("=").expect("invalid item"))
153171
.collect();
154-
new_conf_set.remove("neon.safekeepers");
155-
156172
let existing_conf_set: HashMap<&str, &str> = existing_conf
157173
.split_terminator('\n')
158174
.map(|e| e.split_once("=").expect("invalid item"))

test_runner/regress/test_replica_promotes.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ def test_replica_promote(neon_simple_env: NeonEnv, method: PromoteMethod):
112112
lsn_triple = get_lsn_triple(promo_cur)
113113
log.info(f"Secondary: LSN after promotion is {lsn_triple}")
114114

115+
# Removing this restart makes everything break TODO(myrrc)
116+
secondary.stop(mode="immediate-terminate")
117+
secondary.respec(mode="Primary")
118+
secondary.start()
119+
115120
# Reconnect to the secondary to make sure we get a read-write connection
116121
with secondary.connect() as conn, conn.cursor() as new_primary_cur:
117122
new_primary_cur.execute("select count(*) from t")
@@ -145,6 +150,7 @@ def test_replica_promote(neon_simple_env: NeonEnv, method: PromoteMethod):
145150
stop_and_check_lsn(secondary, None)
146151

147152
if method == PromoteMethod.COMPUTE_CTL:
153+
log.info("Restarting primary to check new config")
148154
secondary.stop()
149155
# In production, compute ultimately receives new compute spec from cplane.
150156
secondary.respec(mode="Primary")

0 commit comments

Comments
 (0)