Skip to content

v3.12.1 — a summary may be pessimistic, not optimistic

Latest

Choose a tag to compare

@productdevbook productdevbook released this 20 Aug 10:01

Fixes a regression in v3.12.0 that could publish NaN %. Anyone on 3.12.0 with a group should take this.

A group of one member published NaN

  • v3.12.0's "never worse than the second-worst" indexed past the end of the ranking when a day had exactly one member row. Spreading undefined gave a row with no day, no total and no ok: the page printed NaN %, status.json said uptime_90d: null — which the docs define as "before the first day of data" — and history.json published 86 of 90 days with every field missing.
  • It reaches a group of one member, or a group of two on any day only one of them has a row for: a member onboarded later, a member removed, a round the rollup missed.
  • The clamp was wrong the other way too. Two members each down 30% of the time, never on the same day: every day had exactly one bad member, so every day published as good and the group read 100% where neither member was above 70%. A summary may be pessimistic; it may not claim things were fine when they were not.

An outage was reported as 72 hours

  • fail_at remembers when a run of failures began, and nothing bounded how old it could be. A process whose last round ended in one sub-threshold failure keeps that moment; three days later it returns, fails once more, crosses the threshold, and recovers a minute after that — ✅ recovered (after 72 h 1 m) for a sixty-second outage. Any restart, redeploy or missed cron in that state produces it.
  • Two failures cannot span three days at a minute a round, and the row knows how many there were. The start is never further back than the failures reach.

The phone fix stopped one breakpoint short

  • Below 481px v3.12.0 clipped nothing; from 481 to 600 it clipped up to 121 pixels of a 220-pixel timestamp. Both the event row and the day strip use 600 now.
  • The same rewrite left out the element the event row exists for: the monitor's name had no min-width, so the panel cut it — 59 pixels of a 42-character name at 320px.
  • The no-data bar's hover ignored prefers-reduced-motion: three classes beat the guard's one, so the one bar that grows threefold was the one that still moved.

Corrected

  • The upgrade notes gave one failure mode for every missing column — five surfaces returning 500. For this release's column that is false: every surface keeps answering and only the probe round throws, so the page freezes and updated_at stops moving, which is the only tell there is.
  • The migration blocks are in order; the newest sat between v3.6 and v3.9, where nobody reading downward from their own version reaches it.
  • wrangler.toml, compose.yaml and deploy/k8s/README.md — the three places an operator reads what LANG takes — still said five languages.

One word for one thing, in each of the six

  • A reader went through every string in all six languages against what the probe does. The meanings held: no language claims a cause the probe did not observe.
  • Turkish had two words for an answer and two for a notice, and three error messages in the formal second person where every button is informal. German and French each called a notice by a second name in the refusal and the aria label. Spanish said interrupción for a severity while saying caído for a state. Chinese wrote the sparkline title in English word order and used two roots for one outage.
  • The punctuation around a duration is the language's own now: 已恢复 (2小时5分钟后) rather than full-width text in half-width brackets.

The dialog fits every language

  • Measured at 360px: the four Spanish severities needed 247 pixels of the 218 there are, so the last one ran past the dialog and the dialog became horizontally scrollable. German had five pixels to spare. The row wraps now and a button is never narrower than its own word.
  • The language select was half the row by assumption, and todos los idiomas and toutes les langues were cut off inside it on every phone.

Ratchets, fourth pass

  • Seven more walk-arounds, each closed and verified by replaying it: a hardcoded "en" fallback satisfying the ?lang= rule, border-color: white invisible to the theme rule, a hex laundered through color-mix(), a two-label hostname, a top-level domain not in the list, a hostname in a CSS comment, and a Set used as a cross-request memo where the rule looked only for a Map.

Upgrading

  • A pull. The container adds v3.12's column on start; on Cloudflare the ALTER is in docs/UPGRADING.md.