mres.h includes the generated public config header mres_config.h.
Public config rules:
MRES_ENABLE_JITTERmust be exactly0or1MRES_MAX_ATTEMPTSmust be in1..255- consumer-side overrides that conflict with the generated header fail compilation
typedef int32_t mres_err_t;
typedef uint8_t mres_backoff_t;
typedef uint8_t mres_breaker_state_t;Status codes:
MRES_OKMRES_ERR_NULLMRES_ERR_INVALIDMRES_ERR_RANGEMRES_ERR_BUSYMRES_ERR_EXHAUSTEDMRES_ERR_OPENMRES_ERR_OP_FAILEDMRES_ERR_WAIT_REQUIREDMRES_ERR_WAIT_FAILEDMRES_ERR_UNSUPPORTED
typedef uint32_t (*mres_clock_fn)(void *context);
typedef int (*mres_wait_fn)(void *context, uint32_t delay_ms);
typedef struct {
void *context;
mres_clock_fn clock;
mres_wait_fn wait;
} mres_platform_t;Clock contract:
- units are milliseconds
- values are treated as a modulo
uint32_tcounter - wrap is supported only within one complete counter cycle
- arbitrary backward jumps are unsupported
- the callback must be valid in the calling context and must return promptly
Wait contract:
- returns
0only when the wait was accepted or completed under the host platform contract - any non-zero wait result stops retry execution and returns
MRES_ERR_WAIT_FAILED
Policy:
typedef struct {
uint8_t max_attempts;
uint8_t strategy;
uint8_t jitter;
uint8_t reserved0;
uint32_t base_delay_ms;
uint32_t max_delay_ms;
} mres_retry_policy_t;Instance:
typedef struct {
uint32_t magic;
uint32_t jitter_state;
mres_retry_policy_t policy;
int32_t last_operation_result;
uint8_t attempts;
uint8_t initialized;
uint8_t active;
uint8_t reserved0;
} mres_retry_t;Functions:
mres_err_t mres_retry_init(mres_retry_t *retry, const mres_retry_policy_t *policy);
mres_err_t mres_retry_seed(mres_retry_t *retry, uint32_t seed);
mres_err_t mres_retry_exec(
mres_retry_t *retry,
mres_op_fn operation,
void *operation_context,
const mres_platform_t *platform,
int *operation_result);
mres_err_t mres_retry_reset(mres_retry_t *retry);
mres_err_t mres_delay_calc(mres_retry_t *retry, uint8_t attempt, uint32_t *delay_ms);Retry semantics:
mres_retry_execis synchronousMRES_OKmeans the operation ran and returned0MRES_ERR_EXHAUSTEDmeans all permitted attempts were used and each operation call returned non-zeroMRES_ERR_WAIT_REQUIREDmeans a positive delay was computed but no wait callback was availableoperation_resultis written only after an operation callback actually runs- same-instance recursive execution or reset during execution returns
MRES_ERR_BUSY
Backoff formulas:
- fixed:
base - linear:
base * (attempt + 1) - exponential:
base * 2^attempt
Arithmetic rules:
- intermediate overflow saturates at
UINT32_MAX max_delay_msis applied after mathematical saturation- jitter never wraps arithmetic and is capped again after jitter when
max_delay_ms != 0
Policy:
typedef struct {
uint8_t failure_threshold;
uint8_t half_open_max_calls;
uint8_t reserved0;
uint8_t reserved1;
uint32_t recovery_timeout_ms;
} mres_breaker_policy_t;Only a single synchronous half-open probe is supported, so half_open_max_calls must be 1.
Key functions:
mres_err_t mres_breaker_init(mres_breaker_t *breaker, const mres_breaker_policy_t *policy);
mres_err_t mres_breaker_call(
mres_breaker_t *breaker,
mres_op_fn operation,
void *operation_context,
const mres_platform_t *platform,
int *operation_result);
mres_err_t mres_breaker_get_state(const mres_breaker_t *breaker, mres_breaker_state_t *state);
mres_err_t mres_breaker_state_name(const mres_breaker_t *breaker, const char **name);
mres_err_t mres_breaker_remaining_ms(
const mres_breaker_t *breaker,
const mres_platform_t *platform,
uint32_t *remaining_ms,
bool *is_open);Breaker semantics:
- invalid or corrupted states fail closed with
MRES_ERR_INVALID MRES_ERR_OPENmeans the operation was not calledMRES_OKmeans the operation was called and returned0MRES_ERR_OP_FAILEDmeans the operation was called and returned non-zero- open timestamps are captured after the failed operation returns, using a fresh clock sample
- manual success in
OPENleaves the breaker open - manual failure in
OPENleaves the existing timeout in place
Policy:
typedef struct {
uint16_t max_tokens;
uint16_t refill_count;
uint32_t refill_ms;
} mres_ratelimit_policy_t;Functions:
mres_err_t mres_ratelimit_init(
mres_ratelimit_t *limiter,
const mres_ratelimit_policy_t *policy,
const mres_platform_t *platform);
mres_err_t mres_ratelimit_acquire(
mres_ratelimit_t *limiter,
uint16_t count,
const mres_platform_t *platform,
bool *allowed);
mres_err_t mres_ratelimit_tokens(
mres_ratelimit_t *limiter,
const mres_platform_t *platform,
uint16_t *tokens);
mres_err_t mres_ratelimit_reset(mres_ratelimit_t *limiter, const mres_platform_t *platform);Rate-limiter semantics:
- zero capacity, zero refill interval, and zero refill count are invalid
count == 0is invalidcount > max_tokensreturnsMRES_ERR_RANGE- temporary rate limiting returns
MRES_OKwithallowed == false - policy is copied into the instance during successful initialization
- same-instance recursion during acquire, query, or reset returns
MRES_ERR_BUSY