Surface Transfer Failures#222
Conversation
Core reports the truth via per-request counts; the CLI applies policy. - NetPace.Core: aggregate per-request failures into RequestsAttempted/ Succeeded/Failed on SpeedTestResult instead of swallowing them; validate upload HTTP status (a rejected upload is a failed request, not throughput); never throw for network outcomes (only cancellation and operational faults); stream each failure reason live via SpeedTestProgress.FailedRequestReason; reverse the ISpeedTestService exception-propagation contract. - NetPace.Console: route human/operational output to a stderr console; make the exit code reflect only NetPace's health (network conditions exit 0); add --fail-on total|partial|none (fail-fast); surface counts in every format (token annotation, CSV columns, JSON fields); stream failure reasons at Debug. - Docs: README --help snapshot and a USER_GUIDE section on detecting failures. Public NetPace.Core API change ships as a MINOR bump. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@claude Review this pull request. Analyse the code changes and provide feedback covering:
|
|
Claude finished @FrankRay78's task in 8m 17s —— View job Review: Surface Transfer Failures (#222)Todo list
Overall this is a well-scoped, thoroughly-tested implementation of the approved spec, and CI (Build and Test + CodeQL) is green. The core design — counts-not-exceptions in 1.
|
- CSV header no longer dropped when a leading --loop/--count iteration finds no server: key the header on the first actual data row, not the iteration index. - Scope the USER_GUIDE Debug live-streaming claim to normal/interactive output (machine formats never write failure reasons to stderr, including at Debug). - Rename the shadowing 'server' field in ScriptedSpeedTester (clears CodeQL). - Add tests: CSV header survives a leading no-server iteration; JSON+Debug writes nothing to stderr; --quiet still emits the all-failed stderr notice. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@claude Please re-review, identify only showstoppers or important issues (P1/P2). |
|
Claude finished @FrankRay78's task in 1m 29s —— View job Re-review: Surface Transfer Failures (#222)Todo list
No P1/P2 (showstopper/important) issues found. Commit
The two remaining CodeQL notes ( Spot-re-checked the core failure-aggregation path ( Nothing blocking merge from this pass. |
Closes #206.
Why
Certain upload endpoints (e.g. the Deutsche Telekom servers in #206) reported 0 bps while working on speedtest.net. The cause: the parallel test loop caught and discarded every per-request exception, counting failed requests as 0 bytes transferred. When every request failed,
0 bytes ÷ elapsed = 0 bpswas reported as if it were a valid measurement — with no log, no message, and no non-zero exit code. This makes that failure visible.Implements the approved specification in #206 (comment). Governing principle: Core reports the truth via request counts; the CLI applies policy. The exit code reflects only whether NetPace itself functioned — network conditions are data, not errors.
What changes
NetPace.Core (public API — MINOR bump)
SpeedTestResultgainsRequestsAttempted/RequestsSucceeded/RequestsFailed. Per-request failures (transport errors, timeouts, non-success HTTP status) are aggregated into these counts instead of being swallowed; the method no longer throws for network outcomes (only caller cancellation and operational faults propagate).SpeedTestProgressgainsFailedRequestReasonto stream each failure live; nothing is retained on the result.ISpeedTestServicedoc reversed to describe the counts-not-exceptions contract.NetPace.Console
0; only operational failures (e.g. can't write--file) exit non-zero.--fail-on <total|partial|none>(defaultnone) to opt in to a failure exit code; fail-fast and uniform across single /--count/--loop.Upload: 0 bps (32 of 32 requests failed)), CSV columns (DownloadSucceeded/DownloadFailed/…), and JSON integer fields. Human notices and operational errors now go to stderr; at--verbosity Debugeach failure reason is streamed live.Docs: README
--helpsnapshot and a new USER_GUIDE "Detecting failed measurements" section (counts, exit-code model,--fail-on).Non-obvious things a reviewer should know
0 bpsun-ignorable: it always co-travels with the counts, and the CLI is obligated to surface them. Known accepted trade-off:netpace && nextproceeds on a total outage by default; use--fail-onor inspect the counts to detect it.null"; I omit the speed field instead (System.Text.JsonWhenWritingNull, consistent with how--no-downloadalready drops fields), letting"UploadSucceeded": 0carry validity. Per-instance explicitnullisn't achievable without also emittingnullfor skipped dimensions. Happy to switch to explicitnullif preferred.Directory.Build.propsis intentionally untouched — tagv1.1.0at release.How to verify
dotnet build srcanddotnet test srcare clean (633 tests, 0 warnings).netpace --jsonagainst a server whose uploads all fail → JSON has"UploadSucceeded":0/"UploadFailed":N, noUploadSpeed, nothing on stderr, exit0.--csv→ the data row shows…,0,N,…; with default output →Upload: 0 bps (N of N requests failed)plus a stderr notice.--fail-on totalon an all-failed dimension → exit1; default → exit0.--server <unreachable>(latency on) → exit0with the no-servers notice (regression: previously exit 1 only in this path).