@@ -397,8 +397,16 @@ impl Database {
397397 let start_frame_no = sync_ctx. durable_frame_num + 1 ;
398398 let end_frame_no = max_frame_no;
399399
400- for frame_no in start_frame_no..end_frame_no+1 {
401- self . push_one_frame ( & conn, & sync_ctx, generation, frame_no, page_size) . await ?;
400+ let mut frame_no = start_frame_no;
401+ while frame_no <= end_frame_no {
402+ // The server returns its maximum frame number. To avoid resending
403+ // frames the server already knows about, we need to update the
404+ // frame number to the one returned by the server.
405+ let max_frame_no = self . push_one_frame ( & conn, & sync_ctx, generation, frame_no, page_size) . await ?;
406+ if max_frame_no > frame_no {
407+ frame_no = max_frame_no;
408+ }
409+ frame_no += 1 ;
402410 }
403411
404412 let frame_count = end_frame_no - start_frame_no + 1 ;
@@ -409,7 +417,7 @@ impl Database {
409417 }
410418
411419 #[ cfg( feature = "sync" ) ]
412- async fn push_one_frame ( & self , conn : & Connection , sync_ctx : & SyncContext , generation : u32 , frame_no : u32 , page_size : u32 ) -> Result < ( ) > {
420+ async fn push_one_frame ( & self , conn : & Connection , sync_ctx : & SyncContext , generation : u32 , frame_no : u32 , page_size : u32 ) -> Result < u32 > {
413421 let frame_size: usize = 24 +page_size as usize ;
414422 let frame = vec ! [ 0 ; frame_size] ;
415423 let rc = unsafe {
@@ -419,12 +427,12 @@ impl Database {
419427 return Err ( crate :: errors:: Error :: SqliteFailure ( rc as std:: ffi:: c_int , format ! ( "Failed to get frame: {}" , frame_no) ) ) ;
420428 }
421429 let uri = format ! ( "{}/sync/{}/{}/{}" , sync_ctx. sync_url, generation, frame_no, frame_no+1 ) ;
422- self . push_with_retry ( uri, & sync_ctx. auth_token , frame. to_vec ( ) , sync_ctx. max_retries ) . await ?;
423- Ok ( ( ) )
430+ let max_frame_no = self . push_with_retry ( uri, & sync_ctx. auth_token , frame. to_vec ( ) , sync_ctx. max_retries ) . await ?;
431+ Ok ( max_frame_no )
424432 }
425433
426434 #[ cfg( feature = "sync" ) ]
427- async fn push_with_retry ( & self , uri : String , auth_token : & Option < String > , frame : Vec < u8 > , max_retries : usize ) -> Result < ( ) > {
435+ async fn push_with_retry ( & self , uri : String , auth_token : & Option < String > , frame : Vec < u8 > , max_retries : usize ) -> Result < u32 > {
428436 let mut nr_retries = 0 ;
429437 loop {
430438 let client = reqwest:: Client :: new ( ) ;
@@ -437,7 +445,9 @@ impl Database {
437445 }
438446 let res = builder. body ( frame. to_vec ( ) ) . send ( ) . await . unwrap ( ) ;
439447 if res. status ( ) . is_success ( ) {
440- return Ok ( ( ) ) ;
448+ let resp = res. json :: < serde_json:: Value > ( ) . await . unwrap ( ) ;
449+ let max_frame_no = resp. get ( "max_frame_no" ) . unwrap ( ) . as_u64 ( ) . unwrap ( ) ;
450+ return Ok ( max_frame_no as u32 ) ;
441451 }
442452 if nr_retries > max_retries {
443453 return Err ( crate :: errors:: Error :: ConnectionFailed ( format ! ( "Failed to push frame: {}" , res. status( ) ) ) ) ;
0 commit comments