@@ -88,8 +88,9 @@ pub struct MockFlightServer {
8888 row_count : Arc < Mutex < u64 > > ,
8989 /// Track response index across connection attempts
9090 response_indices : Arc < Mutex < HashMap < String , usize > > > ,
91- /// Track expected offset per table (must be strictly sequential starting from 0)
92- expected_offsets : Arc < Mutex < HashMap < String , i64 > > > ,
91+ /// Observation of every `ack_up_to_records` value emitted on the auto-ack path,
92+ /// in emission order. Used by tests to assert acks are connection-relative.
93+ auto_ack_records : Arc < Mutex < Vec < u64 > > > ,
9394}
9495
9596impl MockFlightServer {
@@ -100,7 +101,7 @@ impl MockFlightServer {
100101 batch_count : Arc :: new ( Mutex :: new ( 0 ) ) ,
101102 row_count : Arc :: new ( Mutex :: new ( 0 ) ) ,
102103 response_indices : Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ,
103- expected_offsets : Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ,
104+ auto_ack_records : Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ,
104105 }
105106 }
106107
@@ -128,6 +129,12 @@ impl MockFlightServer {
128129 * self . row_count . lock ( ) . await
129130 }
130131
132+ /// Get every `ack_up_to_records` value emitted on the auto-ack path, in order.
133+ #[ allow( dead_code) ]
134+ pub async fn get_auto_ack_records ( & self ) -> Vec < u64 > {
135+ self . auto_ack_records . lock ( ) . await . clone ( )
136+ }
137+
131138 /// Reset the server state
132139 #[ allow( dead_code) ]
133140 pub async fn reset ( & self ) {
@@ -138,8 +145,7 @@ impl MockFlightServer {
138145 * self . max_offset_received . lock ( ) . await = -1 ;
139146 * self . batch_count . lock ( ) . await = 0 ;
140147 * self . row_count . lock ( ) . await = 0 ;
141- let mut expected_offsets = self . expected_offsets . lock ( ) . await ;
142- expected_offsets. clear ( ) ;
148+ self . auto_ack_records . lock ( ) . await . clear ( ) ;
143149 }
144150}
145151
@@ -219,11 +225,18 @@ impl FlightService for MockFlightServer {
219225 let batch_count = Arc :: clone ( & self . batch_count ) ;
220226 let row_count = Arc :: clone ( & self . row_count ) ;
221227 let response_indices = Arc :: clone ( & self . response_indices ) ;
222- let expected_offsets = Arc :: clone ( & self . expected_offsets ) ;
228+ let auto_ack_records = Arc :: clone ( & self . auto_ack_records ) ;
223229
224230 tokio:: spawn ( async move {
225231 let mut stream_responses: Vec < MockFlightResponse > = Vec :: new ( ) ;
226232 let mut is_first_message = true ;
233+ // Per-connection state, owned as locals like the real server (fresh per
234+ // DoPut connection). These must not leak across reconnects or concurrent
235+ // same-table streams: `expected_offset` validates wire ordering, and
236+ // `connection_record_count` is the cumulative-record tracker that drives
237+ // auto-acks (the server derives ack_up_to_records per connection).
238+ let mut expected_offset: i64 = 0 ;
239+ let mut connection_record_count: u64 = 0 ;
227240
228241 // Load configured responses
229242 {
@@ -240,12 +253,6 @@ impl FlightService for MockFlightServer {
240253 * indices. get ( & table_name) . unwrap_or ( & 0 )
241254 } ;
242255
243- // Reset expected offset to 0 for each new connection
244- {
245- let mut offsets = expected_offsets. lock ( ) . await ;
246- offsets. insert ( table_name. clone ( ) , 0 ) ;
247- }
248-
249256 while let Ok ( Some ( flight_data) ) = stream. message ( ) . await {
250257 // Handle schema message (first message has no app_metadata or empty app_metadata)
251258 if is_first_message {
@@ -278,30 +285,23 @@ impl FlightService for MockFlightServer {
278285 if let Some ( metadata) = & metadata {
279286 debug ! ( "Received batch with offset_id: {}" , metadata. offset_id) ;
280287
281- // Validate offset is strictly sequential
282- let expected = {
283- let offsets = expected_offsets. lock ( ) . await ;
284- * offsets. get ( & table_name) . unwrap_or ( & 0 )
285- } ;
286- if metadata. offset_id != expected {
288+ // Validate offset is strictly sequential (connection-local).
289+ if metadata. offset_id != expected_offset {
287290 error ! (
288291 "Non-incremental offset: expected {}, got {}" ,
289- expected , metadata. offset_id
292+ expected_offset , metadata. offset_id
290293 ) ;
291294 let _ = tx
292295 . send ( Err ( Status :: invalid_argument ( format ! (
293296 "Non-incremental offset: expected {}, actual {}" ,
294- expected , metadata. offset_id
297+ expected_offset , metadata. offset_id
295298 ) ) ) )
296299 . await ;
297300 return ;
298301 }
299302
300- // Update expected offset for next batch
301- {
302- let mut offsets = expected_offsets. lock ( ) . await ;
303- offsets. insert ( table_name. clone ( ) , metadata. offset_id + 1 ) ;
304- }
303+ // Update expected offset for next batch.
304+ expected_offset = metadata. offset_id + 1 ;
305305
306306 // Update max offset
307307 {
@@ -324,6 +324,10 @@ impl FlightService for MockFlightServer {
324324 . map ( |rb| rb. length ( ) as u64 )
325325 . unwrap_or ( 0 ) ;
326326 if rows > 0 {
327+ // Connection-local counter drives acks (mirrors the server's
328+ // per-connection cumulative tracker); the global row_count is
329+ // kept only as a cross-connection observation metric.
330+ connection_record_count += rows;
327331 let mut count = row_count. lock ( ) . await ;
328332 * count += rows;
329333 }
@@ -446,10 +450,10 @@ impl FlightService for MockFlightServer {
446450 } else {
447451 // Auto-ack if no more configured responses
448452 if let Some ( metadata) = metadata {
449- let records = {
450- let count = row_count . lock ( ) . await ;
451- * count
452- } ;
453+ // Use the connection-local record count so acks are
454+ // connection-relative, matching the real server.
455+ let records = connection_record_count ;
456+ auto_ack_records . lock ( ) . await . push ( records ) ;
453457 let ack_metadata = FlightAckMetadata {
454458 ack_up_to_offset : metadata. offset_id ,
455459 ack_up_to_records : records,
@@ -511,7 +515,7 @@ pub async fn start_mock_flight_server(
511515 batch_count : Arc :: clone ( & mock_server. batch_count ) ,
512516 row_count : Arc :: clone ( & mock_server. row_count ) ,
513517 response_indices : Arc :: clone ( & mock_server. response_indices ) ,
514- expected_offsets : Arc :: clone ( & mock_server. expected_offsets ) ,
518+ auto_ack_records : Arc :: clone ( & mock_server. auto_ack_records ) ,
515519 } ;
516520
517521 let addr: std:: net:: SocketAddr = "127.0.0.1:0" . parse ( ) ?;
0 commit comments