Skip to content

fix(din): clock-skew partition clamp + WriteTimeout (telematics-scale review) - #9

Open
zer0stars wants to merge 1 commit into
masterfrom
fix/scale-review-2026-07-08
Open

fix(din): clock-skew partition clamp + WriteTimeout (telematics-scale review)#9
zer0stars wants to merge 1 commit into
masterfrom
fix/scale-review-2026-07-08

Conversation

@zer0stars

Copy link
Copy Markdown
Member

Telematics-scale fixes (din) — #1 clock-skew partition clamp, #5 WriteTimeout

From the telematics-at-scale review (REVIEW-din-dq-vt-scale-2026-07-08.md), the two din items, hardened after an adversarial regression review.

#1 — broken-clock partition pollution

raw_events is PARTITIONED BY day("time"), so a device with a garbage RTC (epoch-0/1970, 1980/2019 GPS-week rollover, 2000 factory default, 2099 runaway) minted a permanent singleton day-partition that maintenance can never merge — an unbounded partition/file/catalog leak once even a small fraction of a large fleet has bad clocks. partitionSafeTime clamps a time outside [now-365d, now+24h] to now.

Applied at the write layer, not convert (adversarial-review fix): the clamp touches ONLY the value written to raw_events (fillRowArgs, the partition key), not the CloudEvent header time. An earlier convert-layer version clamped the header time, which changed the NATS MsgID + decodestream dedup id (both hash the header time) → a stable-id broken-clock device's retries drifted to new MsgIDs → duplicate raw rows → double-fire to vehicle-triggers, plus a sibling-collapse data-loss edge. Clamping only the stored partition value bounds the partition while leaving retry dedup and sibling identity exactly as before. Wide bounds leave offline buffers (days-weeks) and near-future skew untouched. now is computed once per bundle.

#5 — WriteTimeout(5s) < publishAckTimeout(10s)

The handler blocks up to the ack budget before mapping a lost ack to 503+Retry-After, which the 5s socket WriteTimeout cut short → the device saw a raw connection reset and retry-stormed under burst latency. Split WriteTimeout from the read timeout (DefaultWriteTimeout 15s, connection = publishAckTimeout+margin). The attestation server additionally budgets its pre-publish ERC-1271 verify (5s) + blob PUT on top of the ack budget so its 503 is writable too.

Verification

go build/vet/test ./... (18 pkgs ok) / golangci-lint (0 issues). Tests: partitionSafeTime bounds; rowArgs clamps the stored time but leaves the header untouched; server write budget exceeds read + ack budget. Adversarial regression review (4 lenses) confirmed no MsgID/dedup regression after the write-layer move.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SAgMMjdGVCD7M1yLy7BUPq

…ut > ack budget (scale review)

- #1 broken-clock partition pollution: raw_events is PARTITIONED BY day("time"), so a device
  with a garbage RTC (epoch-0/1970, 1980/2019 GPS-week rollover, 2000 factory default, 2099
  runaway) minted a permanent singleton day-partition maintenance can never merge — an
  unbounded partition/file/catalog leak once even a small fraction of a large fleet has bad
  clocks. partitionSafeTime clamps a time outside [now-365d, now+24h] to now.
  IMPORTANT (adversarial-review fix): the clamp is applied ONLY to the value WRITTEN to
  raw_events (fillRowArgs, the day("time") partition key), NOT to the CloudEvent header time.
  An earlier version clamped the header time in convert, which changed the NATS MsgID / the
  decodestream dedup id (both hash the header time) and made a stable-id broken-clock device's
  retries drift to new MsgIDs → duplicate raw rows → double-fire to vehicle-triggers, plus a
  sibling-collapse data-loss edge. Clamping only the stored partition value bounds the
  partition while leaving retry dedup and sibling identity exactly as before. Wide bounds keep
  legit offline buffers and near-future skew untouched. now is computed once per bundle.
- #5 WriteTimeout(5s) < publishAckTimeout(10s): the handler blocks up to the ack budget before
  mapping a lost ack to 503+Retry-After, which the socket WriteTimeout cut short → the device
  saw a raw reset and retry-stormed under burst latency. Split WriteTimeout from the read
  timeout (DefaultWriteTimeout 15s, connection = publishAckTimeout+margin). The ATTESTATION
  server additionally budgets its pre-publish ERC-1271 verify (5s) + blob PUT
  (attestationPrePublishBudget) on top of the ack budget so its 503 is writable too.

Tests: partitionSafeTime bounds; rowArgs clamps the STORED time but leaves the header time
untouched; server write budget exceeds read + ack budget.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant