78 lines
2.6 KiB
Markdown
78 lines
2.6 KiB
Markdown
# `limits/timeout-ceiling`
|
|
|
|
## Purpose
|
|
|
|
Enforces the hard 30 000 ms ceiling on caller-supplied `timeoutMs`
|
|
values. The check fires at the public entry point of `run2pc` so
|
|
above-ceiling calls never contact a participant; the operational
|
|
warning in design doc §9.2 is that long prepares hold row-level locks,
|
|
so surfacing the misuse loudly is more useful than silently clamping.
|
|
|
|
This module is intentionally tiny — one function — because the
|
|
behaviour is small but the gate is one of the most-asserted contracts
|
|
in the spec.
|
|
|
|
## Features
|
|
|
|
- `assertTimeoutBelowCeiling(timeoutMs)` — throws
|
|
`TWOPC_TIMEOUT_CEILING_EXCEEDED` for above-ceiling, non-positive,
|
|
non-finite, or `NaN` inputs.
|
|
- Re-uses the `TIMEOUT_CEILING_MS` constant from `options/` so the
|
|
ceiling stays a single source of truth.
|
|
|
|
## Usage: Basic
|
|
|
|
```ts
|
|
import { assertTimeoutBelowCeiling } from "@suaveplan/api-2pc/limits";
|
|
|
|
assertTimeoutBelowCeiling(5000); // ok
|
|
assertTimeoutBelowCeiling(30001); // throws TWOPC_TIMEOUT_CEILING_EXCEEDED
|
|
```
|
|
|
|
## Usage: Advanced
|
|
|
|
The function is intentionally side-effect-free so callers can wrap it
|
|
in a per-tenant override path:
|
|
|
|
```ts
|
|
import { TIMEOUT_CEILING_MS } from "@suaveplan/api-2pc/options";
|
|
import { assertTimeoutBelowCeiling } from "@suaveplan/api-2pc/limits";
|
|
|
|
function resolveTimeout(
|
|
requested: number | undefined,
|
|
tenantMax: number
|
|
): number {
|
|
const effective = requested ?? DEFAULT_TIMEOUT_MS;
|
|
assertTimeoutBelowCeiling(effective);
|
|
if (effective > tenantMax) {
|
|
return tenantMax;
|
|
}
|
|
if (effective > TIMEOUT_CEILING_MS) {
|
|
// unreachable given the assert above — included only to
|
|
// illustrate that the ceiling acts as the strict upper bound.
|
|
return TIMEOUT_CEILING_MS;
|
|
}
|
|
return effective;
|
|
}
|
|
```
|
|
|
|
## API Reference
|
|
|
|
- `function assertTimeoutBelowCeiling(timeoutMs: number): void`
|
|
- Throws `TwoPcError(TWOPC_CODES.TIMEOUT_CEILING_EXCEEDED)` for any
|
|
of: `NaN`, `Infinity`, `-Infinity`, values `<= 0`, values
|
|
`> TIMEOUT_CEILING_MS`.
|
|
|
|
## Implementation Notes
|
|
|
|
The check rejects non-positive values for the same reason it rejects
|
|
above-ceiling ones: an immediate or backwards-in-time deadline would
|
|
collapse phase 1 to a single tick and the rollback path would fire
|
|
before any participant could finish a real prepare. Treating that as
|
|
the same misuse class as "30 minutes" is a deliberate ergonomic
|
|
choice — operators get one error code to grep for.
|
|
|
|
`Number.isFinite` is used in preference to `Number.isNaN` because the
|
|
former covers `Infinity` and `-Infinity` in addition to `NaN`. The
|
|
explicit `<= 0` check then excludes zero and negative-finite values.
|