refactor(wal): Implement `Iterator` for ClosedSegmentFileReader

The ClosedSegmentFileReader is pretty much an iterator anyways, this
just enables using all the juicy combinators with it more easily.
pull/24376/head
Fraser Savage 2023-06-09 10:35:15 +01:00
parent c8a7a8ec91
commit fa69994358
No known key found for this signature in database
GPG Key ID: DE47C33CE8C5C446
5 changed files with 25 additions and 24 deletions

View File

@ -189,15 +189,15 @@ where
let start = Instant::now();
loop {
let ops = match file.next_batch() {
Ok(Some(v)) => v,
Ok(None) => {
let ops = match file.next() {
Some(Ok(v)) => v,
Some(Err(e)) => return Err(WalReplayError::ReadEntry(e)),
None => {
// This file is complete, return the last observed sequence
// number.
debug!("wal file replayed in {:?}", start.elapsed());
return Ok(max_sequence);
}
Err(e) => return Err(WalReplayError::ReadEntry(e)),
};
for op in ops {

View File

@ -219,7 +219,7 @@ mod tests {
// Obtain all the ops in the file
let mut ops = Vec::new();
while let Ok(Some(mut batch)) = reader.next_batch() {
while let Some(Ok(mut batch)) = reader.next() {
ops.append(&mut batch);
}

View File

@ -428,12 +428,7 @@ async fn graceful_shutdown() {
.expect("failed to open wal segment");
// Assert the file contains no operations
assert_matches!(
reader
.next_batch()
.expect("failed to read wal segment contents"),
None
);
assert_matches!(reader.next(), None);
// Validate the parquet files were added to the catalog during shutdown.
let parquet_files = catalog

View File

@ -553,12 +553,19 @@ pub struct ClosedSegmentFileReader {
file: RawClosedSegmentFileReader<BufReader<File>>,
}
impl ClosedSegmentFileReader {
/// Get the next batch of sequenced wal ops from the file
pub fn next_batch(&mut self) -> Result<Option<Vec<SequencedWalOp>>> {
self.file.next_batch().context(UnableToReadNextOpsSnafu)
}
impl Iterator for ClosedSegmentFileReader {
type Item = Result<Vec<SequencedWalOp>>;
/// Read the next batch of sequenced WAL operations from the file
fn next(&mut self) -> Option<Self::Item> {
self.file
.next_batch()
.context(UnableToReadNextOpsSnafu)
.transpose()
}
}
impl ClosedSegmentFileReader {
/// Return the segment file id
pub fn id(&self) -> SegmentId {
self.id
@ -624,9 +631,8 @@ impl Iterator for WriteOpEntryDecoder {
fn next(&mut self) -> Option<Self::Item> {
Some(
self.reader
.next_batch()
.next()?
.context(FailedToReadWalSnafu)
.transpose()?
.map(|batch| {
batch
.into_iter()
@ -730,7 +736,7 @@ mod tests {
let mut reader = wal.reader_for_segment(closed.id).unwrap();
let mut ops = vec![];
while let Ok(Some(mut batch)) = reader.next_batch() {
while let Some(Ok(mut batch)) = reader.next() {
ops.append(&mut batch);
}
assert_eq!(vec![op1, op2, op3, op4], ops);
@ -796,7 +802,7 @@ mod tests {
// There aren't any entries in the closed segment because nothing was written
let mut reader = wal.reader_for_segment(closed_segment_details.id()).unwrap();
assert!(reader.next_batch().unwrap().is_none());
assert!(reader.next().is_none());
// Can delete an empty segment, leaving no closed segments again
wal.delete(closed_segment_details.id()).await.unwrap();

View File

@ -57,13 +57,13 @@ async fn crud() {
// ensuring the per-partition sequence numbers match up to the current
// op-level sequence number while it is the source of truth.
let mut reader = wal.reader_for_segment(closed_segment_details.id()).unwrap();
let op = reader.next_batch().unwrap().unwrap();
let op = reader.next().unwrap().unwrap();
assert_eq!(op[0].sequence_number, 42);
op[0]
.table_write_sequence_numbers
.values()
.for_each(|sequence_number| assert_eq!(*sequence_number, op[0].sequence_number));
let op = reader.next_batch().unwrap().unwrap();
let op = reader.next().unwrap().unwrap();
assert_eq!(op[0].sequence_number, 43);
op[0]
.table_write_sequence_numbers
@ -107,7 +107,7 @@ async fn replay() {
// ensuring the per-partition sequence numbers match up to the current
// op-level sequence number while it is the source of truth.
let mut reader = wal.reader_for_segment(closed_segment_ids[0]).unwrap();
let op = reader.next_batch().unwrap().unwrap();
let op = reader.next().unwrap().unwrap();
assert_eq!(op[0].sequence_number, 42);
op[0]
.table_write_sequence_numbers
@ -116,7 +116,7 @@ async fn replay() {
// Can read the written entries from the previously open segment
let mut reader = wal.reader_for_segment(closed_segment_ids[1]).unwrap();
let op = reader.next_batch().unwrap().unwrap();
let op = reader.next().unwrap().unwrap();
assert_eq!(op[0].sequence_number, 43);
op[0]
.table_write_sequence_numbers