Referencia Zigspire-zig (SDK consumido)

zig/src/replay.zig

Declaraciones públicas de zig/src/replay.zig (spire-zig (SDK consumido)).

ImplementadoSin versión del tren todavía· generada desde apps/docs/generated/zig/spire.json

Página generada desde spire@spire-0.2.0-XvnrRek1BgCX4Bh8miuITCQgkn0FqeQrYYE3goFfDcQd (zig/src/root.zig). No se edita a mano: bun run docs:gen la regenera y bun run docs:check falla si difiere.

Anti-replay de sobres (dec-0119 §5.3).

  • ts_ms tiene que caer en now ± window_ms; fuera es Stale o FromFuture.
  • Cada (source, nonce) se recuerda mientras el sobre podría admitirse (ts + window). Visto otra vez: · con el mismo id → duplicate: redelivery legítima de JetStream o reintento del cliente con los mismos bytes; el llamador responde con la respuesta cacheada o status = duplicate, sin re-ejecutar. · con otro id → Replayed: alguien reutiliza el nonce. Se audita.
  • Cuota por fuente: cada source sólo puede tener vivas las entradas que le reserva reserve (lo que su rate admitido mete en una ventana). Una fuente que inunda agota su cuota (ReplayCacheFull para ella), nunca la de otra. Una fuente sin reserva no entra (cuota 0).
  • Memoria fija: reserve (al registrar los handlers) reserva la suma de las cuotas; check no asigna. Llena de entradas vivas rechaza en vez de olvidar (olvidar abriría el replay).

Thread-safe (un mutex). La caché es local al proceso: vale para unix e inproc; con varias réplicas consumiendo el mismo subject NATS hace falta la variante compartida (Valkey) del lado TS (ADR del SDK §5).

replay.Verdict

type · línea 27

pub const Verdict = enum

Sin ///.

replay.Error

const · línea 29

pub const Error = error{ Stale, FromFuture, Replayed, ReplayCacheFull }

Sin ///.

replay.ReserveError

const · línea 31

pub const ReserveError = error{ ReplayBudgetTooLarge, TooManySources } || std.mem.Allocator.Error

Sin ///.

replay.Options

type · línea 33

pub const Options = struct

Sin ///.

replay.max_sources

const · línea 45

pub const max_sources = 64

Fuentes distintas por guard (las identidades de un keyring).

replay.quota

fn · línea 51

pub fn quota(opts: Options, per_sec: u32, burst: u32) u64

Entradas de la caché que un rate per_sec/burst mete en una ventana con las opciones opts: burst + ⌈per_sec × (window_ms + prune_interval_ms) / 1000⌉. Para dimensionar max_entries: la suma de esto por cada (emisor, ruta) que admite el router.

replay.BudgetReport

type · línea 57

pub const BudgetReport = struct

Datos de un reserve que no cabe.

replay.BudgetReport.source

fn · línea 77

pub fn source(self: *const BudgetReport) []const u8

Primera fuente de la llamada que ya no cabe.

replay.BudgetReport.format

fn · línea 81

pub fn format(self: BudgetReport, w: *std.Io.Writer) std.Io.Writer.Error!void

Sin ///.

replay.ReplayGuard

type · línea 120

pub const ReplayGuard = struct

Sin ///.

replay.ReplayGuard.init

fn · línea 135

pub fn init(allocator: std.mem.Allocator, opts: Options) ReplayGuard

Sin ///.

replay.ReplayGuard.deinit

fn · línea 139

pub fn deinit(self: *ReplayGuard) void

Sin ///.

replay.ReplayGuard.quotaFor

fn · línea 148

pub fn quotaFor(self: *const ReplayGuard, per_sec: u32, burst: u32) u64

Entradas que caben en una ventana a per_sec con ráfaga burst (más el intervalo de poda) con las opciones de este guard.

replay.ReplayGuard.reserve

fn · línea 155

pub fn reserve(self: *ReplayGuard, source: []const u8, per_sec: u32, burst: u32) ReserveError!void

Reserva para source lo que un rate per_sec/burst admite en una ventana; se acumula (una fuente en varias rutas suma cada una). Se llama al registrar (asigna); check después no asigna.

replay.ReplayGuard.reserveAll

fn · línea 163

pub fn reserveAll(self: *ReplayGuard, sources: []const []const u8, per_sec: u32, burst: u32) ReserveError!void

reserve de todas las sources a la vez: o se reservan todas o ninguna (una ruta que no cabe no deja cuota reservada a medias). Si no cabe, last_budget_error dice qué fuente, cuánto pedía y cuánto quedaba (el router lo registra en el log con el subject).

replay.ReplayGuard.lastBudgetError

fn · línea 205

pub fn lastBudgetError(self: *ReplayGuard) ?BudgetReport

Copia, bajo el mutex, del informe del último reserveAll.

replay.ReplayGuard.check

fn · línea 260

pub fn check(self: *ReplayGuard, source: []const u8, id: envelope.Id, nonce: envelope.Nonce, ts_ms: u64, now_ms: u64) Error!Verdict

Sin ///.

replay.ReplayGuard.count

fn · línea 295

pub fn count(self: *ReplayGuard) usize

Sin ///.

replay.ReplayGuard.quotaOf

fn · línea 302

pub fn quotaOf(self: *ReplayGuard, source: []const u8) u32

Cuota reservada para source (0 si no tiene).