You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix the tooltips, the speedtest engine's bookkeeping, and the recovery paths
The settings tooltips said several things the daemon does not do - a wrong
retry floor, a power button that supposedly stopped manual actions, colour
and logging switches described backwards - and the overgrown ones buried
what decides a toggle. All corrected and cut to size: the Best of 3 tooltip
was a forty-line essay in a 250-pixel bubble, most of it a scoring formula
the README already documents. Warnings were added where decisions get made
(retries at 0 also disable the slow-uplink rescue; the packet-loss probe's
traffic is not counted in the data-used figure), and unbacked advice was
replaced with measured numbers.
The server picker judged health with a cheap read check a server can pass
while refusing every actual upload; our fleet survey found about one server
in seven refuses them, and when such a server is nearest it won every
selection and the speed history sat empty forever. A finished run's own
evidence now feeds back: a run where the server answered every upload and
accepted none marks it unusable for 12 hours. What does not count is
deliberate - a starved slow uplink, a redirect, overload answers (429, 502,
503, 504), any accepted upload, and any run we cancelled ourselves. The
verdict holds its ground: a health probe already in flight when the run
convicted the server cannot land late and quietly overwrite it - expiry is
the only readmission - and when several DIFFERENT servers get convicted in
quick succession, the log says what that pattern means: a firewall or proxy
on the operator's own network is probably filtering upload POSTs. Uploads
themselves are recognized by what they are - the engine's only POSTs - so
no server's choice of endpoint path can blind that evidence chain. And a
server answering the endpoint probe with a relative redirect (the ordinary
nginx shape) is followed to its working endpoint instead of blacklisted for
a perfectly legal header.
A speedtest that measured its download and lost only its upload used to be
thrown away whole - and on uplinks under roughly 3 Mbps the upload always
fails, so those users had a permanently empty chart. Such a run is now
stored as a partial, like the iperf3 engine has always done: download, ping
and jitter land on the chart, the upload shows as unmeasured rather than a
fake zero, and the failed upload's traffic is still billed through the
accounting channel that cannot masquerade as a measurement. The boundaries
hold everywhere: an upload-only test still fails outright, a cancelled run
is recorded as cancelled, the packet-loss probe is skipped (it would measure
through the failed upload's leftovers), and in a best-of round a partial
winner's blank upload stays blank instead of inheriting other servers'
bytes. And a direction the run tried and LOST now counts as a breach of any
minimum configured on it, in both engines - the alternative judged such
runs healthy, silencing the upload alert with the very failure it watches
and wiping an in-progress alert streak at the moment the uplink fell off
the cliff.
A speedtest row's timestamp is its identity everywhere - deleting a run,
merging a backup, linking chart to table - but the accounting rows could
land on an occupied second, where deleting one row silently un-billed
another and a restore quietly dropped one of the two. Every insert now
takes the first free second, in one atomic statement protected by the same
busy-wait as every ordinary write: the first version used a read-then-write
transaction, the exact shape this database already broke on once, and under
the daemon's own probe traffic it dropped a COMPLETED measurement within a
handful of inserts on a real file-backed database (the in-memory test
databases run a single connection and could never see it; a file-backed
test now hammers exactly that). The spend row is also written only after
the measurement it references, so a crash can no longer leave a permanent
orphan billing bytes for a run that never landed.
The outage repair could corrupt a neighbouring outage's record. It paired
outages only two minutes into the future while its own design notes work to
a 48-hour horizon, and its correction grabbed the first recovery row after
an outage began without checking whether a different outage started in
between - given a complete future pair from a fast clock, it rewrote that
pair's recovery as the old outage's and left a permanently open outage that
never happened. The pairing now reaches the full 48 hours, corrections are
made by row identity so nothing can be seized, and a future-dated recovery
whose proving samples are pruned in the same pass is moved back to the
proven second - while one whose samples survive stays exactly where the
operator's history put it.
The documented lockout recovery for containers - restart with
PINGULARITY_ACCESS=network - only worked when the boot's first settings
read succeeded. The settings controller now runs the access sequence after
every successful load through a single hook, so the retry loop after a
transient database fault, the reload signal, and a settings import or
backup restore all apply the operator's explicit choice; the reload signal
no longer bails on the harmless legacy-password warning, one shared rule
defines a usable load for every path, and the first-load flag is read under
the writer lock so two racing first loads cannot both claim to be first.
Nothing changes for installs without the explicit flag.
And whether Quick Setup has been answered is decided from the loaded
settings before any database read: a passing disk fault at boot used to put
a long-since-answered install back on the first-run hold, pausing
monitoring and announcing a first run to an operator who answered it months
ago. Answered installs also stop paying a database read on every probe
round's hold check.
Co-Authored-By: Claude <noreply@anthropic.com>
0 commit comments