feat(libxce-failover): reconnect recovery — ctx ERR->RUN reset + stale wbuf drain (fixes post-failover EINVAL) (task 3.2)
This commit is contained in:
parent
84c5e32c2c
commit
12284bc3f5
5 changed files with 170 additions and 1 deletions
|
|
@ -159,6 +159,36 @@ int xce_failover_rotate(api_ctx_t *ac)
|
|||
return rc < 0 ? rc : 0;
|
||||
}
|
||||
|
||||
/* ════════════════════════════════════════════════════════════════════════
|
||||
* Reconnect recovery — context-state reset (CI2) + stale-reply drain (CI1)
|
||||
* ════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
int xcecli_ctx_recover(api_ctx_t* ac)
|
||||
{
|
||||
if (ac == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* CI2 — state reset: the transport-error path (handle_disconnect) left
|
||||
* ctx->state = XCE_CTX_ERR, which the per-op XCE_CTX_RUN guard in xceapi.c
|
||||
* rejects as -EINVAL — the reported bug. After a successful reconnect,
|
||||
* restore RUN so the next xce_* attempt passes. ONLY flip ERR→RUN: a
|
||||
* deliberately-stopped (DOWN) or not-yet-started (INIT/BUSY) ctx is left
|
||||
* untouched. */
|
||||
if (ac->ctx.state == XCE_CTX_ERR)
|
||||
ac->ctx.state = XCE_CTX_RUN;
|
||||
|
||||
/* CI1 — stale-reply drain: handle_disconnect may have injected a stale
|
||||
* transport status into the single-slot wbuf. Drain any pending entry with
|
||||
* a NON-BLOCKING get so the next attempt's cbuf_get cannot consume a
|
||||
* prior-attempt reply. cbuf_tryget returns -EAGAIN when the channel is
|
||||
* already empty — the normal, no-op case. The reconnect closed the old fd
|
||||
* first, so no further replies arrive from the dead connection. */
|
||||
int stale = 0;
|
||||
cbuf_tryget(&ac->ctx.wbuf, &stale);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ════════════════════════════════════════════════════════════════════════
|
||||
* XcecliRetryLoop — decision core (pure) + side-effecting wrapper
|
||||
* ════════════════════════════════════════════════════════════════════════ */
|
||||
|
|
@ -289,6 +319,11 @@ bool xcecli_retry_next(api_ctx_t* ac, int* rc, bool is_write,
|
|||
if (rrc < 0) {
|
||||
WARN("xcecli failover: rotate failed (rc=%d); retrying anyway", rrc);
|
||||
} else {
|
||||
/* Reconnect succeeded: repair the ctx before the next xce_* attempt
|
||||
* (CI2 ERR→RUN state reset, CI1 stale-reply drain) so the per-op guard
|
||||
* passes and no prior-attempt reply is consumed (1.2, 4.4). */
|
||||
xcecli_ctx_recover(ac);
|
||||
|
||||
/* Log the rotation target (7.1). xce_failover_rotate consumes the
|
||||
* redirect hint when present (so the post-rotate target is not always
|
||||
* the sticky master); report the sticky master cursor as a best-effort
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue