@@ -314,6 +314,19 @@ impl IdempotenceManager {
314314 }
315315 }
316316
317+ /// Returns true if the batch has already been committed on the server.
318+ ///
319+ /// If the batch's sequence is less than or equal to `last_acked_sequence`, it means
320+ /// a higher-sequence batch has already been acknowledged. This implies the current batch
321+ /// was also successfully written on the server (otherwise the higher-sequence batch could
322+ /// not have been committed).
323+ pub fn is_already_committed ( & self , bucket : & TableBucket , batch_sequence : i32 ) -> bool {
324+ let entries = self . bucket_entries . lock ( ) ;
325+ entries
326+ . get ( bucket)
327+ . is_some_and ( |e| e. last_acked_sequence >= 0 && batch_sequence <= e. last_acked_sequence )
328+ }
329+
317330 pub fn can_retry_for_error (
318331 & self ,
319332 bucket : & TableBucket ,
@@ -530,6 +543,36 @@ mod tests {
530543 assert ! ( mgr. can_send_more_requests( & b0) ) ; // under limit again
531544 }
532545
546+ #[ test]
547+ fn test_is_already_committed ( ) {
548+ let mgr = IdempotenceManager :: new ( true , 5 ) ;
549+ let b0 = test_bucket ( 0 ) ;
550+ mgr. set_writer_id ( 42 ) ;
551+
552+ // No entry yet → not committed
553+ assert ! ( !mgr. is_already_committed( & b0, 0 ) ) ;
554+
555+ // Initialize bucket and ack seq=0
556+ let _ = mgr. next_sequence_and_increment ( & b0) ; // 0
557+ mgr. add_in_flight_batch ( & b0, 0 , 100 ) ;
558+ mgr. handle_completed_batch ( & b0, 100 , 42 ) ; // last_acked=0
559+
560+ // seq=0 <= last_acked(0) → committed
561+ assert ! ( mgr. is_already_committed( & b0, 0 ) ) ;
562+ // seq=1 > last_acked(0) → not committed
563+ assert ! ( !mgr. is_already_committed( & b0, 1 ) ) ;
564+
565+ // Ack up to seq=4, then check seq=0 still committed
566+ for seq in 1 ..=4 {
567+ let _ = mgr. next_sequence_and_increment ( & b0) ;
568+ mgr. add_in_flight_batch ( & b0, seq, 100 + seq as i64 ) ;
569+ mgr. handle_completed_batch ( & b0, 100 + seq as i64 , 42 ) ;
570+ }
571+ assert ! ( mgr. is_already_committed( & b0, 0 ) ) ; // seq=0 <= last_acked(4)
572+ assert ! ( mgr. is_already_committed( & b0, 4 ) ) ; // seq=4 <= last_acked(4)
573+ assert ! ( !mgr. is_already_committed( & b0, 5 ) ) ; // seq=5 > last_acked(4)
574+ }
575+
533576 #[ test]
534577 fn test_reset_batch_ids_cleaned_on_complete ( ) {
535578 let ( mgr, b0) = setup_three_in_flight ( ) ;
0 commit comments