feat: wire HA candidate-list reconnect into worker+scheduler join paths

Worker (xcecd):
- Add xce_cluster_config_t cluster_cfg field to controller_connector_ctx_t
  (controller_connector.h includes xce/cluster.h)
- Populate cc_ctx->cluster_cfg from parsed cluster_cfg after xcecd_start()
  sets cc_ctx (main.c, removes the P3 placeholder)
- Replace xcecd_join_cluster() single-shot connect with a candidate-iterating
  loop: tries each candidate, calls xcecli_stop() before the next attempt,
  falls back to the original single-host path when candidates_count == 0

Scheduler (xce_scheduler):
- Add xce_cluster_config_t cluster_cfg field to xce_scheduler_t
  (scheduler.h includes xce/cluster.h)
- Add sched_set_cluster_cfg() setter
- Replace the hardcoded xcecli_start/xcecli_join pair in sched_init() with
  the same candidate-iterating pattern; original single-host path preserved
- main.c calls sched_set_cluster_cfg() before sched_init() when --peers given
  (removes the P3 placeholder comment)

checking_connection() already calls xcecd_join_cluster() on retry, giving
the worker free reconnect-after-failover behaviour for no additional code.
This commit is contained in:
Rongsong Shen 2026-05-08 03:05:56 +00:00
parent fd9cfce1c1
commit b75703ba6b
6 changed files with 131 additions and 20 deletions

View file

@ -15,6 +15,7 @@
#include "kvmgr.h"
#include "mylock.h"
#include "plugin.h"
#include "xce/cluster.h"
#include "xce/types.h"
#include "xlist.h"
#include "xvec.h"
@ -88,10 +89,12 @@ typedef struct {
_Atomic int eval_in_progress; /* 1 while eval_select loop runs */
_Atomic int staging_merge_complete; /* 1 after staging merge completes */
select_eval_ctx_t* sel_eval_ctx; /* session-level memoisation context; NULL between sessions */
xce_cluster_config_t cluster_cfg; /* HA candidate list — empty means single-host mode */
} xce_scheduler_t;
extern int sched_init(xce_scheduler_t*, xce_client_config_t*,
xce_request_handler_t);
extern void sched_set_cluster_cfg(xce_scheduler_t*, const xce_cluster_config_t*);
extern void sched_fini(xce_scheduler_t*);
extern int sched_init_config(xce_scheduler_t* sched, xce_conf4sched_t*);
extern int sched_update(xce_scheduler_t*);

View file

@ -188,7 +188,7 @@ int main(int argc, char* argv[])
INFO("HA cluster config: %d candidate(s), identity=%s, ca_cert=%s",
cluster_cfg.candidates_count, cluster_cfg.identity,
cluster_cfg.ca_cert_path);
/* P3 will call xce_connect_cluster(&cluster_cfg) here */
sched_set_cluster_cfg(&sched, &cluster_cfg);
} else {
INFO("No --peers flag; using single-controller path");
}

View file

@ -426,14 +426,52 @@ int sched_init(xce_scheduler_t* sched, xce_client_config_t* config,
xcecli_set_handler(sched->apictx, handler, sched);
rc = xcecli_start(sched->apictx);
if (rc < 0) {
return rc;
}
/* HA mode: iterate candidates until one accepts as primary */
if (sched->cluster_cfg.candidates_count > 0) {
int joined = 0;
for (int i = 0; i < sched->cluster_cfg.candidates_count; i++) {
const char* host = sched->cluster_cfg.candidates[i].hostname;
int port = sched->cluster_cfg.candidates[i].port;
rc = xcecli_join(sched->apictx, HostRole_scheduler, NULL);
if (rc < 0) {
return rc;
config->nmasters = 1;
config->masters[0] = (char*)host;
config->master_ports[0] = port;
rc = xcecli_ctx_init(&(sched->apictx), config);
if (rc < 0) {
continue;
}
xcecli_set_handler(sched->apictx, handler, sched);
rc = xcecli_start(sched->apictx);
if (rc < 0) {
continue;
}
rc = xcecli_join(sched->apictx, HostRole_scheduler, NULL);
if (rc == 0) {
joined = 1;
break;
}
/* Standby replied — try next candidate */
xcecli_stop(sched->apictx);
}
if (!joined) {
return -1;
}
} else {
/* Single-host path (original) */
rc = xcecli_start(sched->apictx);
if (rc < 0) {
return rc;
}
rc = xcecli_join(sched->apictx, HostRole_scheduler, NULL);
if (rc < 0) {
return rc;
}
}
rc = pthread_create(&(sched->jobpicker), NULL, &sched_job_picker, sched);
@ -446,6 +484,15 @@ int sched_init(xce_scheduler_t* sched, xce_client_config_t* config,
return rc;
}
void sched_set_cluster_cfg(xce_scheduler_t* sched,
const xce_cluster_config_t* cfg)
{
if (sched == NULL || cfg == NULL) {
return;
}
sched->cluster_cfg = *cfg;
}
void sched_fini(xce_scheduler_t* sched)
{
void* res;