Skip to content

Keep fallback probes out of the rolling three-hour average - #1

Open
CodeAThing wants to merge 1 commit into
f:mainfrom
CodeAThing:fix/fallback-samples-in-average
Open

Keep fallback probes out of the rolling three-hour average#1
CodeAThing wants to merge 1 commit into
f:mainfrom
CodeAThing:fix/fallback-samples-in-average

Conversation

@CodeAThing

Copy link
Copy Markdown

What changed

threeHourSamples filters out fallback measurements by comparing source
against "FAST CDN" and "fallback probe". Neither string is produced
anywhere in the codebase -- the values actually written are "Fast.com",
"FAST probe fallback" and "Cloudflare fallback", so the filter matched
nothing and every fallback result was averaged in.

I replaced the raw String with a SpeedSource enum so the comparison
cannot silently drift again, and derived the filter from isFallback.

Three smaller fixes in the same paths:

  • Cancelling a run -- which happens on every interval change -- no longer falls
    through to the fallback probes, and no longer writes
    "Speed test failed: CancellationError" into the popover.
  • When Fast.com and the fallback both fail, the reported error now names
    both causes instead of only the last one.
  • webView.stopLoading() moved into a defer, so an abandoned run cannot
    keep downloading on the cancellation path.

Why

The fallback probes are not comparable to the Fast.com run: they pull a fixed
2-8 MB payload instead of Fast.com's adaptive test, so they report a much
lower figure. One Cloudflare fallback in a quiet three-hour window can halve
the average shown in the popover.

The README already describes fallback results as labelled in the history, so I
read the exclusion as the intended behaviour rather than a change of policy.
Happy to drop the enum and just fix the two string literals if you'd rather
keep the diff minimal.

How it was validated

xcodebuild -project FastBar/FastBar.xcodeproj -scheme FastBar -configuration Debug -destination 'platform=macOS' CODE_SIGNING_ALLOWED=NO build -- succeeds, no new warnings. git diff --check is clean.

Ran the app on a Mac and confirmed measurements still record and render in the
menu bar and the popover.

Since there's no test target yet, I checked the encoding contract by compiling
the real SpeedMonitor.swift against a small harness:

  • A speed-history.json written by 1.0.1 decodes unchanged, and re-encoding it
    is byte-identical -- the enum's raw values are the strings already on disk.
  • An unrecognised source decodes as .fastDotCom rather than throwing.
    loadHistory() uses try?, so a throw there would silently discard the
    user's entire history.
  • With one Fast.com sample at 92.4 and two fallbacks, the average is 92.4;
    before the fix it was 47.4.

If a test target would be welcome I'm glad to open a follow-up PR that adds one
and moves these checks into it.

`threeHourSamples` filtered on the source strings "FAST CDN" and
"fallback probe", but no code path ever produced either name. The values
actually written are "Fast.com", "FAST probe fallback" and "Cloudflare
fallback", so the filter matched nothing and every fallback measurement
was averaged in.

That matters because the fallback probes are not comparable to the
Fast.com run: they download a fixed 2-8 MB payload instead of Fast.com's
adaptive test, so they report a much lower figure. A single Cloudflare
fallback could halve the reported three-hour average.

Replace the source string with a `SpeedSource` enum so the comparison
cannot silently drift again, and derive the filter from `isFallback`.
The raw values match the strings written by 1.0.x, and the enum decodes
an unrecognised source as `.fastDotCom` rather than throwing, because
`loadHistory()` uses `try?` and would otherwise discard the whole file.

While in the same paths:

- Cancelling a run (which happens on every interval change) no longer
  falls through to the fallback probes, and no longer surfaces
  "Speed test failed: CancellationError" in the popover.
- When both Fast.com and the fallback fail, the reported error now names
  both causes instead of only the last one.
- `webView.stopLoading()` moved to a `defer`, so an abandoned run cannot
  keep downloading on the cancellation path.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

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