-
Notifications
You must be signed in to change notification settings - Fork 652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adopt NIOThrowingAsyncSequenceProducer 2nd try #2917
Adopt NIOThrowingAsyncSequenceProducer 2nd try #2917
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great aside from a couple of small things to fix.
lowWatermark: 4, | ||
highWatermark: 8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We pass in the watermarks to makeFileChunksStream
so presumably we should use them here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
internal enum RangeUpdateOutcome { | ||
case moreToRead | ||
case cannotReadMore | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can you move this to the extension where its used?
return .success((descriptor, state.range)) | ||
} else { | ||
case .producing(let producingState), .pausedProducing(let producingState): | ||
guard let descriptor = producingState.handle.descriptorIfAvailable() else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I don't think a guard
is any clearer here as the exit on the failure path isn't earlier than on the success path. IMO if both paths immediately return then if
/else
is clearer.
/// Updates the range (the offsets to read from and up to) to reflect the number of bytes which have been read. | ||
/// - Parameter count: The number of bytes which have been read. | ||
/// - Returns: Returns `True` if there are no remaining bytes to read, `False` otherwise. | ||
mutating func updateRangeWithReadBytes(_ count: Int) -> ProducerState.RangeUpdateOutcome { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is definitely clearer than the existing in-line range updates 🙂
// update range, we are not done | ||
self.range = newLowerBound..<currentRange.upperBound | ||
if currentRange.upperBound - newLowerBound < 1 { | ||
fatalError("here \(newLowerBound) \(currentRange.upperBound)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leftover debugging?
Motivation: Adopt `NIOThrowingAsyncSequenceProducer` in NIOFileSystem to reduce code duplication. Modifications: Adopt `NIOThrowingAsyncSequenceProducer` in NIOFileSystem `DirectoryEntryProducer` and `FileChunkProducer` Result: No functional changes. Internal changes reduce code duplication.
In the original adoption of `NIOThrowingAsyncSequenceProducer` the code did not deal with backpressure being applied very well. A key bug was that it was not protected against re-entrant calls to `produceMore`. Such calls may happen e.g. when the producer has been asked to pause producing and then resume again before the initial read had completed. This resulted in overlapping reads and re-ordered data. This change introduces a new activity state which is protected by a lock and keeps track of if we are in the critical section to serialize access. `DirectoryEntryProducer` performs most of its logic within a lock and so doesn't seem to be impacted in the same way.
b83970c
to
8e8bf85
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, thanks @rnro!
2ae78e6
to
51720a8
Compare
Motivation:
Adopt
NIOThrowingAsyncSequenceProducer
in NIOFileSystem to reduce codeduplication.
Modifications:
Adopt
NIOThrowingAsyncSequenceProducer
in NIOFileSystemDirectoryEntryProducer
andFileChunkProducer
.This change was previously merged and then backed out due to issues (#2879). The original change is in the first commit, the second commit contains additional changes.
In the original adoption of
NIOThrowingAsyncSequenceProducer
the code did not deal with backpressure being applied very well, in some cases causes hangs.A key bug was that it was not protected against re-entrant calls to
produceMore
. Such calls may happen e.g. when the producer has been asked to pause producing and then resume again before the initial read had completed. This resulted in overlapping reads and re-ordered data.This change introduces a new activity state which is protected by a lock and keeps track of if we are in the critical section to serialize access.
DirectoryEntryProducer
performs most of its logic within a lock and sodoesn't seem to be impacted in the same way.
Result:
No functional changes. Internal changes reduce code duplication.