fix(streaming): report a truncated final article as corruption instead of a bare EOF - #945
Merged
Merged
Conversation
…d of a bare EOF A file whose metadata advertises more bytes than its last article holds could never serve its tail. Since #940 the reader returned io.ErrUnexpectedEOF there, which the WebDAV layer passed through as a 206 with a short body and which never reached the health pipeline. Players that want the tail (MKV cues) retried the same range ~15 times a second, and every attempt rebuilt the reader and fetched the final article twice. Wrap the no-progress verdict in a DataCorruptionError (NoRetry, FileOffset at the truncation point) and route it through classifyReadError, so the failure records file health, triggers repair, and returns CorruptedFileError (503). Follow-up requests get a 404 without touching Usenet. The ephemeral ReadAt path applies the same verdict when a fresh reader inside the advertised size yields nothing. The error still unwraps to io.ErrUnexpectedEOF.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A user on 026bd93 reported high CPU while streaming. Their log was one client retrying the same 4760-byte tail range ~15×/s for the whole window, every attempt failing with
unexpected EOF: reader ended at offset N before the requested end.Root cause: the file's final article holds fewer bytes than its metadata claims (truncated last part), so the advertised FileSize can never be served. Since #940 the no-progress guard returned a bare
io.ErrUnexpectedEOF. WebDAV had already committed a 206 with the full Content-Length, the body came up short, nothing reached the health pipeline, and the player (MKV cues live at the tail) retried forever. Each retry rebuilt the reader and fetched the final article twice.Fix:
truncatedTailError(at)wraps the verdict in ausenet.DataCorruptionError(NoRetry,FileOffsetat the truncation point).Read, sharedReadAtContext) route it throughclassifyReadError→ health update → repair trigger →CorruptedFileError(503). Follow-up requests return 404 without touching Usenet.ReadAtpath applies the same verdict when a fresh reader inside the advertised size yields nothing.io.ErrUnexpectedEOF, so the fix(streaming): read the padded final AES block; stop rotating readers that make no progress #940 tests keep passing.Test plan
internal/nzbfilesystem/truncated_tail_test.go(RED before, GREEN after): Read path, ReadAt path, and health/repair trigger with the real SQLite health repo.go test ./internal/nzbfilesystem/... ./internal/webdav/... ./internal/usenet/...pass;go vetclean.golangci-lintis broken with Go 1.27 (export-data version mismatch); relying on CI lint.