Skip to content

Commit 9500a34

Browse files
committed
update cue files
1 parent fded9f2 commit 9500a34

1 file changed

Lines changed: 45 additions & 32 deletions

File tree

src/sinks/file/mod.rs

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,7 @@ impl FileSink {
375375
let input_next = input.next();
376376

377377
let next_timer_deadline = flush_deadlines.peek()
378-
.map(|r| (r.0).0)
379-
.copied();
378+
.map(|&std::cmp::Reverse((d, _, _))| d);
380379

381380
tokio::select! {
382381
event = input_next => {
@@ -458,9 +457,6 @@ impl FileSink {
458457
);
459458
*generation += 1;
460459
}
461-
// Reset the file-handle idle deadline so the file stays open while
462-
// events accumulate for this path.
463-
self.files.reset_at(&path, self.deadline_at());
464460
// Flush immediately when the batch reaches the item or byte limit.
465461
let needs_flush = buffers.get(&path).map_or(false, |(events, _)| {
466462
let total_size: usize = events.iter()
@@ -637,18 +633,21 @@ impl FileSink {
637633
self.files.get_mut(&path).unwrap()
638634
};
639635

640-
// Encode the entire batch into one buffer, then issue a single write_all per partition.
641-
// This reduces write syscalls from O(events) to O(1) per batch.
642-
let mut batch_buffer = BytesMut::new();
643-
let mut succeeded: Vec<(EventFinalizers, JsonSize)> = Vec::with_capacity(events.len());
636+
// Encode each event individually so we can write them one at a time.
637+
// This ensures that if a write fails partway through (e.g. ENOSPC),
638+
// events already written are acknowledged Delivered and only the
639+
// remaining events are retried, avoiding silent duplicates.
640+
let mut encoded: Vec<(BytesMut, EventFinalizers, JsonSize)> =
641+
Vec::with_capacity(events.len());
644642

645643
trace!(message = "Encoding batch.", batch_size = events.len(), path = ?path);
646644
for mut event in events {
647645
let event_size = event.estimated_json_encoded_size_of();
648646
let finalizers = event.take_finalizers();
649647
self.transformer.transform(&mut event);
650-
match self.encoder.encode(event, &mut batch_buffer) {
651-
Ok(()) => succeeded.push((finalizers, event_size)),
648+
let mut buf = BytesMut::new();
649+
match self.encoder.encode(event, &mut buf) {
650+
Ok(()) => encoded.push((buf, finalizers, event_size)),
652651
Err(error) => {
653652
finalizers.update_status(EventStatus::Errored);
654653
emit!(FileIoError {
@@ -662,37 +661,51 @@ impl FileSink {
662661
}
663662
}
664663

665-
if succeeded.is_empty() {
664+
if encoded.is_empty() {
666665
return;
667666
}
668667

669-
let byte_size = batch_buffer.len();
670-
match file.write_all(&batch_buffer).await {
671-
Ok(()) => {
672-
for (finalizers, event_size) in succeeded {
668+
// Write each encoded event separately so a mid-batch failure does
669+
// not retroactively erase acknowledgements for already-persisted records.
670+
let n = encoded.len();
671+
let mut total_bytes = 0usize;
672+
for i in 0..n {
673+
let (buf, finalizers, event_size) = encoded.remove(0);
674+
match file.write_all(&buf).await {
675+
Ok(()) => {
676+
total_bytes += buf.len();
673677
finalizers.update_status(EventStatus::Delivered);
674678
self.events_sent.emit(CountByteSize(1, event_size));
675679
}
676-
emit!(FileBytesSent {
677-
byte_size,
678-
file: String::from_utf8_lossy(&path),
679-
include_file_metric_tag: self.include_file_metric_tag,
680-
});
681-
}
682-
Err(error) => {
683-
let dropped_events = succeeded.len();
684-
for (finalizers, _) in succeeded {
680+
Err(error) => {
681+
// This event failed. Mark all remaining encoded events as
682+
// Errored so they are retried instead of silently delivered.
685683
finalizers.update_status(EventStatus::Errored);
684+
for (_, f, _) in encoded.drain(..) {
685+
f.update_status(EventStatus::Errored);
686+
}
687+
emit!(FileIoError {
688+
code: "failed_writing_file",
689+
message: "Failed to write the file.",
690+
error,
691+
path: &path,
692+
dropped_events: n - i,
693+
});
694+
emit!(FileBytesSent {
695+
byte_size: total_bytes,
696+
file: String::from_utf8_lossy(&path),
697+
include_file_metric_tag: self.include_file_metric_tag,
698+
});
699+
return;
686700
}
687-
emit!(FileIoError {
688-
code: "failed_writing_file",
689-
message: "Failed to write the file.",
690-
error,
691-
path: &path,
692-
dropped_events,
693-
});
694701
}
695702
}
703+
704+
emit!(FileBytesSent {
705+
byte_size: total_bytes,
706+
file: String::from_utf8_lossy(&path),
707+
include_file_metric_tag: self.include_file_metric_tag,
708+
});
696709
}
697710

698711
async fn should_truncate(&mut self, bytes_path: &BytesPath, path: &bytes::Bytes) -> bool {

0 commit comments

Comments
 (0)