@@ -2,8 +2,8 @@ use std::collections::{HashMap, HashSet};
22use std:: hash:: Hash ;
33
44use crate :: {
5- Attributes , CrdtError , Delta , ExportSlot , History , HotOp , HotSequence , Implementation , InputSlot , LamportClock , MAX_EXPORT_SLOTS , MAX_INPUT_SLOTS , Network , NetworkId , Node , NodeId , NodeInput ,
6- PeerId , PeerRegistration , Prior , Registry , RegistryDelta , ResourceEntry , ResourceId , RetiredMarks , Rev , SourceValue , TimeStamp , Tombstone , Touched , UserId ,
5+ Attributes , CrdtError , Delta , ExportSlot , History , HotOp , HotOpId , HotSequence , Implementation , InputSlot , LamportClock , MAX_EXPORT_SLOTS , MAX_INPUT_SLOTS , Network , NetworkId , Node , NodeId ,
6+ NodeInput , PeerId , PeerRegistration , Prior , Registry , RegistryDelta , ResourceEntry , ResourceId , RetiredMarks , Rev , SourceValue , TimeStamp , Tombstone , Touched , UserId ,
77} ;
88
99#[ derive( Clone , Debug ) ]
@@ -16,7 +16,7 @@ pub struct Document {
1616 pub ( crate ) hot_log : Vec < HotOp > ,
1717 /// The stamps of the hot log's ops, so a re-announced op is recognised without a scan.
1818 pub ( crate ) hot_timestamps : HashSet < TimeStamp > ,
19- /// Which hot ops are retired into history , so a late copy is dropped.
19+ /// Which hot ops are retired or taken back , so a late copy is dropped.
2020 pub ( crate ) retired : RetiredMarks ,
2121 /// The registry as of the last retirement, with no un-retired hot ops applied. Retirement computes
2222 /// each delta's `reverse` against this (so LWW reverses capture the true pre-op value, not the
@@ -112,12 +112,35 @@ impl Document {
112112 Ok ( ( ) )
113113 }
114114
115+ /// Mark hot ops retired, dropping any the hot log holds. Returns what the dropped ops named.
116+ pub ( crate ) fn mark_retired ( & mut self , retired : impl IntoIterator < Item = HotOpId > ) -> Touched {
117+ self . retired . extend ( retired) ;
118+ self . drop_retired_hot_ops ( )
119+ }
120+
115121 /// Take on a peer's marks as well as this peer's. Returns what the dropped ops named.
116122 pub ( crate ) fn absorb_retired_marks ( & mut self , remote : & RetiredMarks ) -> Touched {
117123 self . retired . absorb ( remote) ;
118124 self . drop_retired_hot_ops ( )
119125 }
120126
127+ /// Take back hot ops for good, re-deriving the working registry without them. Returns what they named and the ops.
128+ pub ( crate ) fn retract_hot_ops ( & mut self , ids : & [ HotOpId ] ) -> ( Touched , Vec < HotOp > ) {
129+ let wanted: HashSet < HotOpId > = ids. iter ( ) . copied ( ) . collect ( ) ;
130+ let taken: Vec < HotOp > = self . hot_log . extract_if ( .., |hot_op| wanted. contains ( & hot_op. id ( ) ) ) . collect ( ) ;
131+ self . retired . take_back ( ids) ;
132+
133+ let mut touched = Touched :: default ( ) ;
134+ for hot_op in & taken {
135+ touched. record ( & hot_op. op ) ;
136+ self . hot_timestamps . remove ( & hot_op. timestamp ) ;
137+ }
138+ if !taken. is_empty ( ) {
139+ self . rebuild_working ( ) ;
140+ }
141+ ( touched, taken)
142+ }
143+
121144 /// Bring the stamp index back in line after the hot log was filtered as a whole.
122145 pub ( crate ) fn resync_hot_timestamps ( & mut self ) {
123146 self . hot_timestamps = self . hot_log . iter ( ) . map ( |hot_op| hot_op. timestamp ) . collect ( ) ;
0 commit comments