@@ -6,6 +6,7 @@ use std::ops::{Deref, DerefMut};
66use std:: sync:: Arc ;
77use std:: time:: { Duration , SystemTime } ;
88
9+ use backon:: { ConstantBuilder , Retryable } ;
910use cloudkit_derive:: CloudKitRecord ;
1011use cloudkit_proto:: request_operation:: header:: IsolationLevel ;
1112use cloudkit_proto:: retrieve_changes_response:: RecordChange ;
@@ -400,7 +401,7 @@ impl Into<Option<MMCSAttachmentMeta>> for &Attachment {
400401#[ derive( Serialize , Deserialize , Debug , Clone , Default ) ]
401402pub struct AttachmentMetaExtra {
402403 #[ serde( rename = "pgens" ) ]
403- pub preview_generation_state : Option < u32 > , // set to 1
404+ pub preview_generation_state : Option < i32 > , // set to 1
404405}
405406
406407#[ derive( Serialize , Deserialize , Debug , Clone , Default ) ]
@@ -412,7 +413,7 @@ pub struct AttachmentMeta {
412413 #[ serde( rename = "tb" ) ]
413414 pub total_bytes : u64 ,
414415 #[ serde( rename = "st" ) ]
415- pub transfer_state : u32 ,
416+ pub transfer_state : i32 ,
416417 #[ serde( rename = "is" ) ]
417418 pub is_sticker : bool ,
418419 #[ serde( rename = "aguid" ) ]
@@ -430,7 +431,7 @@ pub struct AttachmentMeta {
430431 #[ serde( rename = "tn" ) ]
431432 pub transfer_name : String ,
432433 #[ serde( rename = "vers" ) ]
433- pub version : u32 , // set to 1
434+ pub version : i32 , // set to 1
434435 #[ serde( rename = "t" ) ]
435436 pub uti : Option < String > , // uti type
436437 #[ serde( rename = "cdt" ) ]
@@ -474,26 +475,17 @@ impl<P: AnisetteProvider> CloudMessagesClient<P> {
474475 return Ok ( locked. clone ( ) . unwrap ( ) )
475476 }
476477
477- // todo keep syncing until end
478- async fn sync_records < T : CloudKitRecord > ( & self , zone : & str , mut continuation_token : Option < Vec < u8 > > ) -> Result < ( Vec < u8 > , HashMap < String , Option < T > > ) , PushError > {
478+ async fn sync_records < T : CloudKitRecord > ( & self , zone : & str , continuation_token : Option < Vec < u8 > > ) -> Result < ( Vec < u8 > , HashMap < String , Option < T > > , i32 ) , PushError > {
479479 let container = self . get_container ( ) . await ?;
480480
481481 let zone = container. private_zone ( zone. to_string ( ) ) ;
482482 let key = container. get_zone_encryption_config ( & zone, & self . keychain , & MESSAGES_SERVICE ) . await ?;
483- let ( _assets, mut response) = container. perform ( & CloudKitSession :: new ( ) ,
483+ let ( _assets, response) = container. perform ( & CloudKitSession :: new ( ) ,
484484 FetchRecordChangesOperation :: new ( zone. clone ( ) , continuation_token, & NO_ASSETS ) ) . await ?;
485- let mut items = vec ! [ ] ;
486- while !response. change . is_empty ( ) {
487- items. extend ( response. change ) ;
488- continuation_token = response. sync_continuation_token . clone ( ) ;
489- response = container. perform ( & CloudKitSession :: new ( ) ,
490- FetchRecordChangesOperation :: new ( zone. clone ( ) , continuation_token, & NO_ASSETS ) ) . await ?. 1 ;
491- }
492-
493485
494486 let mut results = HashMap :: new ( ) ;
495487
496- for change in & items {
488+ for change in & response . change {
497489 let identifier = change. identifier . as_ref ( ) . unwrap ( ) . value . as_ref ( ) . unwrap ( ) . name ( ) . to_string ( ) ;
498490
499491 let Some ( record) = & change. record else {
@@ -515,7 +507,7 @@ impl<P: AnisetteProvider> CloudMessagesClient<P> {
515507 results. insert ( identifier, Some ( item) ) ;
516508 }
517509
518- Ok ( ( response. sync_continuation_token ( ) . to_vec ( ) , results) )
510+ Ok ( ( response. sync_continuation_token ( ) . to_vec ( ) , results, response . status ( ) ) )
519511 }
520512
521513 async fn save_records < T : CloudKitRecord > ( & self , zone : & str , records : HashMap < String , T > ) -> Result < HashMap < String , Result < ( ) , PushError > > , PushError > {
@@ -555,13 +547,16 @@ impl<P: AnisetteProvider> CloudMessagesClient<P> {
555547
556548 let zone = container. private_zone ( zone. to_string ( ) ) ;
557549
558- let mut operations = vec ! [ ] ;
559- for record_id in records {
560- operations. push ( DeleteRecordOperation :: new ( record_identifier ( zone. clone ( ) , record_id) ) ) ;
550+ for batch in records. chunks ( 256 ) {
551+ let mut operations = vec ! [ ] ;
552+ for record_id in batch {
553+ operations. push ( DeleteRecordOperation :: new ( record_identifier ( zone. clone ( ) , record_id) ) ) ;
554+ }
555+ ( || async {
556+ container. perform_operations_checked ( & CloudKitSession :: new ( ) , & operations, IsolationLevel :: Operation ) . await
557+ } ) . retry ( & ConstantBuilder :: default ( ) . with_delay ( Duration :: from_secs ( 5 ) ) . with_max_times ( 3 ) ) . await ?;
561558 }
562559
563- container. perform_operations_checked ( & CloudKitSession :: new ( ) , & operations, IsolationLevel :: Operation ) . await ?;
564-
565560 Ok ( ( ) )
566561 }
567562
@@ -575,11 +570,18 @@ impl<P: AnisetteProvider> CloudMessagesClient<P> {
575570 ZoneDeleteOperation :: new ( container. private_zone ( "messageManateeZone" . to_string ( ) ) ) ,
576571 ZoneDeleteOperation :: new ( container. private_zone ( "attachmentManateeZone" . to_string ( ) ) ) ,
577572 ZoneDeleteOperation :: new ( container. private_zone ( "chat1ManateeZone" . to_string ( ) ) ) ,
573+ ZoneDeleteOperation :: new ( container. private_zone ( "messageUpdateZone" . to_string ( ) ) ) ,
574+ ZoneDeleteOperation :: new ( container. private_zone ( "recoverableMessageDeleteZone" . to_string ( ) ) ) ,
575+ ZoneDeleteOperation :: new ( container. private_zone ( "scheduledMessageZone" . to_string ( ) ) ) ,
576+ ZoneDeleteOperation :: new ( container. private_zone ( "chatBotMessageZone" . to_string ( ) ) ) ,
577+ ZoneDeleteOperation :: new ( container. private_zone ( "chatBotAttachmentZone" . to_string ( ) ) ) ,
578+ ZoneDeleteOperation :: new ( container. private_zone ( "chatBotRecoverableMessageDeleteZone" . to_string ( ) ) ) ,
579+
578580 ] , IsolationLevel :: Operation ) . await ?;
579581 Ok ( ( ) )
580582 }
581583
582- pub async fn sync_chats ( & self , continuation_token : Option < Vec < u8 > > ) -> Result < ( Vec < u8 > , HashMap < String , Option < CloudChat > > ) , PushError > {
584+ pub async fn sync_chats ( & self , continuation_token : Option < Vec < u8 > > ) -> Result < ( Vec < u8 > , HashMap < String , Option < CloudChat > > , i32 ) , PushError > {
583585 self . sync_records ( "chatManateeZone" , continuation_token) . await
584586 }
585587
@@ -591,7 +593,7 @@ impl<P: AnisetteProvider> CloudMessagesClient<P> {
591593 self . delete_records ( "chatManateeZone" , chats) . await
592594 }
593595
594- pub async fn sync_messages ( & self , continuation_token : Option < Vec < u8 > > ) -> Result < ( Vec < u8 > , HashMap < String , Option < CloudMessage > > ) , PushError > {
596+ pub async fn sync_messages ( & self , continuation_token : Option < Vec < u8 > > ) -> Result < ( Vec < u8 > , HashMap < String , Option < CloudMessage > > , i32 ) , PushError > {
595597 self . sync_records ( "messageManateeZone" , continuation_token) . await
596598 }
597599
@@ -603,7 +605,7 @@ impl<P: AnisetteProvider> CloudMessagesClient<P> {
603605 self . delete_records ( "messageManateeZone" , messages) . await
604606 }
605607
606- pub async fn sync_attachments ( & self , continuation_token : Option < Vec < u8 > > ) -> Result < ( Vec < u8 > , HashMap < String , Option < CloudAttachment > > ) , PushError > {
608+ pub async fn sync_attachments ( & self , continuation_token : Option < Vec < u8 > > ) -> Result < ( Vec < u8 > , HashMap < String , Option < CloudAttachment > > , i32 ) , PushError > {
607609 self . sync_records ( "attachmentManateeZone" , continuation_token) . await
608610 }
609611
0 commit comments