@@ -28,6 +28,7 @@ use packed_value::{
28
28
} ;
29
29
use pb:: common:: {
30
30
DocumentUpdate as DocumentUpdateProto ,
31
+ DocumentUpdateWithPrevTs as DocumentUpdateWithPrevTsProto ,
31
32
ResolvedDocument as ResolvedDocumentProto ,
32
33
} ;
33
34
#[ cfg( any( test, feature = "testing" ) ) ]
@@ -588,18 +589,91 @@ impl ResolvedDocument {
588
589
589
590
#[ derive( Clone , Debug , Eq , PartialEq ) ]
590
591
#[ cfg_attr( any( test, feature = "testing" ) , derive( proptest_derive:: Arbitrary ) ) ]
591
- pub struct DocumentUpdate {
592
+ pub struct DocumentUpdateWithPrevTs {
592
593
pub id : ResolvedDocumentId ,
593
- pub old_document : Option < ResolvedDocument > ,
594
+ /// The old document and its timestamp in the document log.
595
+ /// The timestamp will become the update's `prev_ts`.
596
+ // TODO: make the timestamp non-optional after everything has pushed
597
+ pub old_document : Option < ( ResolvedDocument , Option < Timestamp > ) > ,
594
598
pub new_document : Option < ResolvedDocument > ,
595
599
}
596
600
597
- impl HeapSize for DocumentUpdate {
601
+ impl DocumentUpdateWithPrevTs {
602
+ /// Checks if two DocumentUpdates are almost equal, ignoring the case where
603
+ /// one has a missing old timestamp
604
+ // TODO: remove this once the old timestamp is non-optional
605
+ pub fn eq_ignoring_none_old_ts ( & self , other : & DocumentUpdateWithPrevTs ) -> bool {
606
+ self . id == other. id
607
+ && self . old_document . as_ref ( ) . map ( |( d, _) | d)
608
+ == other. old_document . as_ref ( ) . map ( |( d, _) | d)
609
+ && self
610
+ . old_document
611
+ . as_ref ( )
612
+ . map ( |( _, ts) | ts)
613
+ . zip ( other. old_document . as_ref ( ) . map ( |( _, ts) | ts) )
614
+ . is_none_or ( |( a, b) | a == b)
615
+ && self . new_document == other. new_document
616
+ }
617
+ }
618
+
619
+ impl HeapSize for DocumentUpdateWithPrevTs {
598
620
fn heap_size ( & self ) -> usize {
599
621
self . old_document . heap_size ( ) + self . new_document . heap_size ( )
600
622
}
601
623
}
602
624
625
+ impl TryFrom < DocumentUpdateWithPrevTs > for DocumentUpdateWithPrevTsProto {
626
+ type Error = anyhow:: Error ;
627
+
628
+ fn try_from (
629
+ DocumentUpdateWithPrevTs {
630
+ id,
631
+ old_document,
632
+ new_document,
633
+ } : DocumentUpdateWithPrevTs ,
634
+ ) -> anyhow:: Result < Self > {
635
+ let ( old_document, old_ts) = old_document. unzip ( ) ;
636
+ Ok ( Self {
637
+ id : Some ( id. into ( ) ) ,
638
+ old_document : old_document. map ( |d| d. try_into ( ) ) . transpose ( ) ?,
639
+ old_ts : old_ts. flatten ( ) . map ( |ts| ts. into ( ) ) ,
640
+ new_document : new_document. map ( |d| d. try_into ( ) ) . transpose ( ) ?,
641
+ } )
642
+ }
643
+ }
644
+
645
+ impl TryFrom < DocumentUpdateWithPrevTsProto > for DocumentUpdateWithPrevTs {
646
+ type Error = anyhow:: Error ;
647
+
648
+ fn try_from (
649
+ DocumentUpdateWithPrevTsProto {
650
+ id,
651
+ old_document,
652
+ old_ts,
653
+ new_document,
654
+ } : DocumentUpdateWithPrevTsProto ,
655
+ ) -> anyhow:: Result < Self > {
656
+ let id = id
657
+ . context ( "Document updates missing document id" ) ?
658
+ . try_into ( ) ?;
659
+ Ok ( Self {
660
+ id,
661
+ old_document : old_document
662
+ . map ( |d| anyhow:: Ok ( ( d. try_into ( ) ?, old_ts. map ( Timestamp :: try_from) . transpose ( ) ?) ) )
663
+ . transpose ( ) ?,
664
+ new_document : new_document. map ( |d| d. try_into ( ) ) . transpose ( ) ?,
665
+ } )
666
+ }
667
+ }
668
+
669
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
670
+ #[ cfg_attr( any( test, feature = "testing" ) , derive( proptest_derive:: Arbitrary ) ) ]
671
+ pub struct DocumentUpdate {
672
+ pub id : ResolvedDocumentId ,
673
+ pub old_document : Option < ResolvedDocument > ,
674
+ pub new_document : Option < ResolvedDocument > ,
675
+ }
676
+
603
677
impl TryFrom < DocumentUpdate > for DocumentUpdateProto {
604
678
type Error = anyhow:: Error ;
605
679
@@ -639,6 +713,51 @@ impl TryFrom<DocumentUpdateProto> for DocumentUpdate {
639
713
}
640
714
}
641
715
716
+ impl From < DocumentUpdateWithPrevTs > for DocumentUpdate {
717
+ fn from ( update : DocumentUpdateWithPrevTs ) -> Self {
718
+ Self {
719
+ id : update. id ,
720
+ old_document : update. old_document . map ( |( d, _) | d) ,
721
+ new_document : update. new_document ,
722
+ }
723
+ }
724
+ }
725
+
726
+ /// Either a [`DocumentUpdate`] or a [`DocumentUpdateWithPrevTs`]
727
+ pub trait DocumentUpdateRef {
728
+ fn id ( & self ) -> ResolvedDocumentId ;
729
+ fn old_document ( & self ) -> Option < & ResolvedDocument > ;
730
+ fn new_document ( & self ) -> Option < & ResolvedDocument > ;
731
+ }
732
+
733
+ impl DocumentUpdateRef for DocumentUpdateWithPrevTs {
734
+ fn id ( & self ) -> ResolvedDocumentId {
735
+ self . id
736
+ }
737
+
738
+ fn old_document ( & self ) -> Option < & ResolvedDocument > {
739
+ self . old_document . as_ref ( ) . map ( |( d, _) | d)
740
+ }
741
+
742
+ fn new_document ( & self ) -> Option < & ResolvedDocument > {
743
+ self . new_document . as_ref ( )
744
+ }
745
+ }
746
+
747
+ impl DocumentUpdateRef for DocumentUpdate {
748
+ fn id ( & self ) -> ResolvedDocumentId {
749
+ self . id
750
+ }
751
+
752
+ fn old_document ( & self ) -> Option < & ResolvedDocument > {
753
+ self . old_document . as_ref ( )
754
+ }
755
+
756
+ fn new_document ( & self ) -> Option < & ResolvedDocument > {
757
+ self . new_document . as_ref ( )
758
+ }
759
+ }
760
+
642
761
impl DeveloperDocument {
643
762
pub fn new (
644
763
id : DeveloperDocumentId ,
@@ -899,13 +1018,15 @@ mod tests {
899
1018
900
1019
use super :: {
901
1020
DocumentUpdateProto ,
1021
+ DocumentUpdateWithPrevTsProto ,
902
1022
ResolvedDocumentProto ,
903
1023
} ;
904
1024
use crate :: {
905
1025
assert_obj,
906
1026
document:: {
907
1027
CreationTime ,
908
1028
DocumentUpdate ,
1029
+ DocumentUpdateWithPrevTs ,
909
1030
ResolvedDocument ,
910
1031
} ,
911
1032
paths:: FieldPath ,
@@ -951,7 +1072,13 @@ mod tests {
951
1072
952
1073
953
1074
#[ test]
954
- fn test_document_update_proto_roundtrips( left in any:: <DocumentUpdate >( ) ) {
1075
+ fn test_document_update_proto_roundtrips( left in any:: <DocumentUpdateWithPrevTs >( ) ) {
1076
+ assert_roundtrips:: <DocumentUpdateWithPrevTs , DocumentUpdateWithPrevTsProto >( left) ;
1077
+ }
1078
+
1079
+
1080
+ #[ test]
1081
+ fn test_index_document_update_proto_roundtrips( left in any:: <DocumentUpdate >( ) ) {
955
1082
assert_roundtrips:: <DocumentUpdate , DocumentUpdateProto >( left) ;
956
1083
}
957
1084
}
0 commit comments