Repository navigation
Conversation
… a download Five tests that fail on the current code, and the OpenSpec change reliable-flush.
… to the disk (#259) FlushAsync puts a flush marker into the write queue and waits for it. The queue is FIFO with one writer, so every block given before the call is written first. The writer then flushes the base stream (FileStream.Flush(true)) and completes the marker. When the writer fails or the stream is closed, FlushAsync throws instead of hanging or reporting dropped bytes as written. The 20 ms delay after each flush is removed.
This branch was successfully deployed
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.
Fixes #259.
Problem
To save a
DownloadPackagefor resume while it downloads, the safe order is: serialize the package, flush, then save the bytes. ButConcurrentStream.FlushAsynccould not do this:FileStreamit calledFlush(false): the bytes stayed in the OS cache, not on the disk.Fix
FlushAsyncadds a small flush marker (aPacketwith no bytes and aTaskCompletionSource) to the write queue and waits only for it. The queue is FIFO with one writer, so every block given before the call is written first.FileStream.Flush(true), elseFlushAsync), so a flush never runs at the same time as a write.FlushAsyncthrows the writer's error. If the stream is closed first, it throwsObjectDisposedException. It never hangs.Task.DelayinDownloadPackage.FlushInternalAsyncis removed (it is not needed now).DownloadPackage.FlushAsyncandConcurrentStream.FlushAsyncshow the safe order.AbstractDownloadService.UpdatePackageneeds no change: its metadata goes through the same FIFO queue after the blocks it counts.Tests
New file
UnitTests/ConcurrentStreamFlushTest.cs. The first commit has only the tests; these 5 fail on the old code:FlushAsyncEndsWhileOtherWritesKeepComingFlushAsyncWritesEveryBlockGivenBeforeItPackageFlushAsyncEndsWhileChunksKeepWritingFlushAsyncOnAFileStreamWritesToTheDiskFlushAsyncDoesNotReportSuccessWhenTheStreamIsClosedBeforeTheBytesAreWrittenThe guard test
FlushAsyncThrowsTheWriterErrorWhenTheWriterFailsDuringTheFlushkeeps the error path working.Local run (net10.0): build has 0 warnings, and all 714 tests pass.
Notes
openspec/changes/reliable-flush.writer-queue-accounting(M1) plans "count pending blocks and wait for zero". That would also never end during a running download. The marker here fixes M1 as well.ConcurrentPacketBuffer.WaitToCompleteis not used by the stream any more; I left it in place to avoid a conflict with Fix the critical and high issues of the 7.0.1 review #258, and it can be removed after that PR is merged.Generated by Claude Code