Skip to content

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 11 Sep 03:01
· 30 commits to master since this release
05a7238

This release puts a bound on the parts of a run, and of the reference
server, that had none. A peer that stopped responding could hang the idle
phase for as long as it liked, return a probe body of any size, or hold a
server's byte budget open for ever. Each now has a limit, a warning that
names the limit it hit, and partial results that survive it.
schema_version stays 1.

Added

  • Options.IdleTimeout and nq --idle-timeout bound the entire idle probing
    phase (default 10 s). A stalled idle response now times out, preserves any
    completed samples, warns, and allows the selected load phases to run (#39).
    This flat cap also applies to healthy slow paths and existing callers with
    large IdleProbes values; raise IdleTimeout to collect more samples and
    reach higher percentile thresholds.

Changed

  • Server byte budgets now limit active downloads and uploads per client IP or
    signed subject to 32 by default (--client-concurrency /
    server.Options.MaxClientConcurrency). Nonpositive values select 32;
    disabling the byte budget also disables these slots. Higher concurrency
    gets 429; admitted transfers remain unthrottled. Default request caps allow
    up to 512 GiB of outstanding payload, so this is not a strict byte quota (#41).
    Slots have no expiry: stalled requests can indefinitely deny large/download
    and upload endpoints to clients sharing an identity. Separately issued
    signed subjects isolate clients behind shared IPs.
  • Small probe responses must now be complete, nonempty bodies of 1–10 bytes.
    Previously accepted empty or larger custom-server responses are invalid.
    The ten-byte ceiling is fixed, with no caller override; it preserves the
    observed Apple and Cloudflare responses (#40).

Fixed

  • nqserver warns when an explicit --client-concurrency is ignored because
    byte budgeting is disabled, including self-signed mode's default; a large
    positive byte budget can retain concurrency-only admission (#41).
  • Server budget admission and completion are accounted atomically, preventing
    unlimited concurrent overshoot. Cancellation and I/O errors settle actual
    bytes; panic unwinding releases the slot and charges the request cap.
    Cleanup preserves active admissions and unpaid debt; extreme byte-debt
    retry hints saturate portably. Authenticated unsupported methods return
    405 before admission checks (#41).
  • Declared oversized probe bodies are rejected before reading, and streamed
    bodies after at most 11 bytes. Invalid sizes no longer become latency
    samples; bounded warnings explain rejection while valid samples and load
    measurements survive (#40).
    Probe cost remains estimated; transport buffering can exceed body-read limits.
  • Idle-timeout warnings retain the preceding probe error and are omitted
    when all requested idle samples have already completed (#39).
  • Caller cancellation retains completed idle samples in partial results;
    caller deadlines during load report cancelled rather than the phase's
    duration_cap. Discovery, idle, and load phase budgets are documented
    together with their teardown and caller-code limitations (#39).
  • Cancellation closes an upload's response body and joins its cleanup, so
    an HTTP/2 upload peer that responds early and then stops reading cannot
    leave the client waiting on flow control after its deadline (#39).
  • Connections opened through a caller-supplied DialTLSContext (or DialTLS)
    were not tracked, so an HTTP/2 connection still winding down when Run
    returned outlived it — for ever, on a transport without IdleConnTimeout.
    They are now torn down with the run (INV-4). test_endpoint cannot be
    honoured through a custom TLS dialer; the run now warns instead of silently
    ignoring it (DISC-9).