/* * client_failover.h — public StatusClassifier surface for the libxce-failover * spec. * * Task 2.1 (StatusClassifier): pure mapping from a reply status / transport rc * to a failover action. No I/O, no globals — see design.md * "Components and Interfaces → StatusClassifier". */ #ifndef XCE_CLIENT_FAILOVER_H #define XCE_CLIENT_FAILOVER_H #include /* Failover action a round-trip outcome maps to. Order mirrors the harness' * fo_expected_action_t (failover_harness.h) and design.md. */ typedef enum { XCE_FO_SUCCESS, /* status == 0, or idempotent-replay success (DUP on a re-sent write) */ XCE_FO_RETRY_NOW, /* E_XCE_REDIRECT / E_XCE_STANDBY / transport error — rotate, no backoff */ XCE_FO_RETRY_BACKOFF, /* E_XCE_NOMASTER / E_XCE_NOT_READY — rotate after jittered backoff */ XCE_FO_TERMINAL /* AUTH/PERM/INVALID/NOENT and other non-retriable — surface to caller */ } xce_fo_action_t; /* * Map a reply status / transport rc to a failover action. * * status : the controller reply status or negative -errno transport rc, as * the failover loop observes it. Controller codes (E_XCE_*) are * accepted in either sign. * is_write: true for mutating ops (e.g. job submit); false for reads. * attempt : 0 for the first send; >0 for a re-send after failover. * * Invariant (2.5): E_XCE_REDIRECT/STANDBY/NOMASTER/NOT_READY never map to * XCE_FO_SUCCESS. * * Idempotent-replay rule (5.2): E_XCE_DUP_JOB / EEXIST on a re-sent write * (is_write && attempt > 0) → XCE_FO_SUCCESS; otherwise → XCE_FO_TERMINAL. * * Unknown / unrecognized statuses are treated conservatively as * XCE_FO_TERMINAL (surfaced, not retried). * * Pure function: no I/O, no globals. */ xce_fo_action_t xce_failover_classify(int status, bool is_write, int attempt); #endif /* XCE_CLIENT_FAILOVER_H */