Commits
Jetstream cursors are time-based and the upstream docs explicitly note
that exact-boundary replay across a disconnect is not guaranteed
gapless. Resuming from the precise saved TimeUS could therefore drop
events that straddle the reconnect window.
On every (re)connect, subtract a fixed jetstreamRewind (5s) from the
loaded cursor before handing it to ConnectAndRead, clamping at zero so
a tiny saved cursor can't go negative. The replayed events are safe to
re-apply: applyCommit dispatches only to UPSERTs and DELETEs keyed on
(did, rkey), so duplicates collapse into the same row state.
The /logs and /events handlers wrote frames with conn.WriteMessage
and never set a write deadline. A client that stopped reading but
kept the TCP connection open could fill the kernel send buffer and
park the handler goroutine on a write forever, leaking the request
context, the broker subscription, and the log producer.
Add a wsWriteWait constant (10s) and call SetWriteDeadline before
every WriteMessage in the logs drain loop and in streamEvents. The
keep-alive ping and the closing close-frame already used WriteControl,
which takes a deadline argument directly; raise their bounds from 1s
to wsWriteWait for consistency. A stuck peer now fails the next write
within ~10s and the handler unwinds cleanly.
A workflow can override the spindle's default Buildkite organisation
via `tack.buildkite.org`, but `BuildkiteBuildRef` didn't carry the org
field. Spawn used the override for `CreateBuild` and then dropped it,
so `Logs` always recomputed org := p.defaultOrg and any cross-org
workflow's /logs request 404'd against the wrong organisation.
Extend TestBuildkiteSpawnWorkflowConfig to assert the org survives
the round-trip via LookupBuildkiteBuildByTuple.
Adds an `extraServiceConfig` option to the NixOS module that is
merged into the systemd service's `serviceConfig` after the
module's defaults. This lets operators set arbitrary `[Service]`
settings, most notably resource limits like `MemoryMax` and
`CPUQuota`, without needing to fork the module, and also lets
them override any of the defaults we set out of the box (e.g.
to relax a sandboxing knob).
Implemented as `attrsOf unspecified` merged with `//` so the
user's attrs win on conflict.
Jetstream cursors are time-based and the upstream docs explicitly note
that exact-boundary replay across a disconnect is not guaranteed
gapless. Resuming from the precise saved TimeUS could therefore drop
events that straddle the reconnect window.
On every (re)connect, subtract a fixed jetstreamRewind (5s) from the
loaded cursor before handing it to ConnectAndRead, clamping at zero so
a tiny saved cursor can't go negative. The replayed events are safe to
re-apply: applyCommit dispatches only to UPSERTs and DELETEs keyed on
(did, rkey), so duplicates collapse into the same row state.
The /logs and /events handlers wrote frames with conn.WriteMessage
and never set a write deadline. A client that stopped reading but
kept the TCP connection open could fill the kernel send buffer and
park the handler goroutine on a write forever, leaking the request
context, the broker subscription, and the log producer.
Add a wsWriteWait constant (10s) and call SetWriteDeadline before
every WriteMessage in the logs drain loop and in streamEvents. The
keep-alive ping and the closing close-frame already used WriteControl,
which takes a deadline argument directly; raise their bounds from 1s
to wsWriteWait for consistency. A stuck peer now fails the next write
within ~10s and the handler unwinds cleanly.
A workflow can override the spindle's default Buildkite organisation
via `tack.buildkite.org`, but `BuildkiteBuildRef` didn't carry the org
field. Spawn used the override for `CreateBuild` and then dropped it,
so `Logs` always recomputed org := p.defaultOrg and any cross-org
workflow's /logs request 404'd against the wrong organisation.
Extend TestBuildkiteSpawnWorkflowConfig to assert the org survives
the round-trip via LookupBuildkiteBuildByTuple.
Adds an `extraServiceConfig` option to the NixOS module that is
merged into the systemd service's `serviceConfig` after the
module's defaults. This lets operators set arbitrary `[Service]`
settings, most notably resource limits like `MemoryMax` and
`CPUQuota`, without needing to fork the module, and also lets
them override any of the defaults we set out of the box (e.g.
to relax a sandboxing knob).
Implemented as `attrsOf unspecified` merged with `//` so the
user's attrs win on conflict.