feat(controller): OPCode_probeConfigTag handler with Request envelope reply (bug-1506)

- Add OPCode_probeConfigTag dispatch in cluster.c
- Implement probe_config_tag handler returning config tag via
  standard xce_reply() → RequestReply envelope
- Populate redirectHost/redirectPort for follow_redirects support
- Wire probeConfigTag reply through typemap
- Add probeConfigTagReply struct to controller.capnp schema
This commit is contained in:
Rongsong Shen 2026-08-10 10:00:08 +00:00
parent b00e97ffe6
commit 90d7dd8241
Signed by: rshen
SSH key fingerprint: SHA256:8Vf2pZ3h6rJa7EhGK+WaAQ9Mta/apZvteW6g9U/WKKk
5 changed files with 64 additions and 8 deletions

View file

@ -816,6 +816,15 @@ static int myreq_handler(vtask_t* task)
}
break;
#endif
case OPCode_probeConfigTag:
/* bug-1506: return the current config generation tag for xceadmin's
* config push --dry-run. Read-only — no WAL commit, no SHA
* verification. Any role (PRIMARY or STANDBY) can service this;
* ha_dispatch_gate already allows OPCode_probeConfigTag on every
* non-INIT role. Redirect hints are filled inside the handler. */
rc = handle_probe_config_tag(c, ep, &request);
break;
case OPCode_schedAdmin: {
/* Stateless pass-through forward to the scheduler (task 10.1, Req
* 5.10). The controller commits no WAL entry and interprets no

View file

@ -1891,6 +1891,48 @@ int handle_upgrade_config(cluster_t *c, endpoint_t *ep, xce_request_t *req)
}
#endif
/* fill_redirect_reply is defined in join.c (no header declaration). */
extern void fill_redirect_reply(xce_reply_t *reply, const ha_state_t *ha);
/* ── handle_probe_config_tag ──────────────────────────────────────────────
*
* Server-side handler for OPCode_probeConfigTag (bug-1506). Returns the
* current config_version_tag so xceadmin's config push --dry-run can
* report the real generation number instead of fabricating "accepted=True"
* with no wire signal.
*
* Unlike handle_upgrade_config, no SHA verification, no decode, no WAL
* commit — just a read of an in-memory field. Usable by any role (PRIMARY
* or STANDBY); the ha_dispatch_gate already allows OPCode_probeConfigTag
* on every non-INIT role. Redirect hints are filled via fill_redirect_reply
* so xceadmin's follow_redirects path works identically to push_config.
*/
int handle_probe_config_tag(cluster_t *c, endpoint_t *ep, xce_request_t *req)
{
xce_reply_t reply;
probe_config_tag_reply_t prep;
memset(&prep, 0, sizeof(prep));
prep.config_tag = c->myconf->config_version_tag;
init_reply_by_req(&reply, req);
reply.status = 0;
reply.data_which = RequestReply_data_probeconfigtagreplymsg;
reply.data.probeconfigtagreplymsg = &prep;
/* If this is a standby, redirect the admin tool to the primary
* (same pattern as handle_controller_join). Do NOT redirect when
* we ARE the primary — that would send the client back to us and
* infinite-loop inside follow_redirects. */
if (ha_should_redirect(&c->ha))
fill_redirect_reply(&reply, &c->ha);
xce_reply(ep, c->myhost, &reply);
return 0;
}
/* ── xce_probe_config_tag ───────────────────────────────────────────────────
*
* Single-RTT config tag probe to one peer controller over SSL.

View file

@ -351,6 +351,7 @@ int push_config_to_standbys(cluster_t *c, const uint8_t *bytes, size_t blen,
* Only callable when CONF_ENABLE_UPGRADE_CONFIG is set.
*/
int handle_upgrade_config(cluster_t *c, endpoint_t *ep, xce_request_t *req);
int handle_probe_config_tag(cluster_t *c, endpoint_t *ep, xce_request_t *req);
/*
* ha_stream_wal_to_standby: batch-stream WAL entries [standby_lsn+1, committed_lsn]