UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

103 lines 4.01 kB
/** * Per-peer sender-side retention buffer for fragmented message bytes, * used to satisfy NACK retransmits from the peer's {@link FragmentAssembler}. * * Lifecycle: * 1. {@link retain} — called on each fragmented send; copies the source * bytes into the retention so they're available to retransmit. If * the per-peer slot cap is hit, the oldest retained entry is FIFO- * evicted. * 2. {@link consume_nack} — looks up retained bytes for a NACK target * and bumps the retry counter. Returns `null` if the entry is gone * (aged out, evicted, or out of retry budget — in which case the * entry is dropped here too). * 3. {@link service} — call once per tick to age out entries older * than `max_age_ms`. * 4. {@link clear} — drop everything; call on peer disconnect. * * Memory cost: each retained entry holds a fresh copy of its source * payload (the upstream send buffer is a reused scratch). With the * default 16 slots × up-to-64 KiB cap on the receiver, worst case is * 1 MiB per peer; steady-state is empty because steady traffic fits in * one packet and bypasses fragmentation. * * @author Alex Goldring * @copyright Company Named Limited (c) 2025 */ export class FragmentRetention { /** * @param {{ * max_messages?: number, * max_age_ms?: number, * max_retries?: number, * }} [options] * `max_messages` caps simultaneously-retained messages; oldest is * FIFO-evicted on overflow. `max_age_ms` is the per-entry TTL. * `max_retries` caps how many NACK retransmit rounds a single * retained message can satisfy before being dropped. */ constructor({ max_messages, max_age_ms, max_retries, }?: { max_messages?: number; max_age_ms?: number; max_retries?: number; }); /** @type {number} @readonly */ readonly max_messages: number; /** @type {number} @readonly */ readonly max_age_ms: number; /** @type {number} @readonly */ readonly max_retries: number; /** * Copy `payload[0..length)` into retention under `message_id`. * Evicts the oldest retained entry if `max_messages` is exceeded. * * If a retained entry already exists for `message_id` (only legitimate * cause: uint16 wrap), the old entry is dropped first so the FIFO * position and retry budget restart from the new send. * * @param {number} message_id * @param {Uint8Array} payload source bytes (caller may overwrite after return) * @param {number} length number of bytes from `payload[0]` to copy * @param {number} now_ms monotonic timestamp for age-out */ retain(message_id: number, payload: Uint8Array, length: number, now_ms: number): void; /** * Mark a NACK round for `message_id` and return the retained entry * so the caller can re-emit the missing chunks. Returns `null` if * no entry exists, or if the per-message retry budget is now * exhausted (in which case the entry is dropped). * * @param {number} message_id * @returns {{payload: Uint8Array, length: number}|null} */ consume_nack(message_id: number): { payload: Uint8Array; length: number; } | null; /** * Per-tick maintenance: evict any entry older than `max_age_ms`. * * The FIFO is in strict insertion order, so we can stop at the first * still-fresh entry rather than scanning the whole map. * * @param {number} now_ms */ service(now_ms: number): void; /** * Number of currently-retained messages. * @returns {number} */ size(): number; /** * Whether `message_id` is currently retained. * @param {number} message_id * @returns {boolean} */ has(message_id: number): boolean; /** * Drop every retained entry. Use on peer disconnect. */ clear(): void; #private; } //# sourceMappingURL=FragmentRetention.d.ts.map