@@ -20,6 +20,7 @@ use std::sync::{RwLock, RwLockReadGuard};
2020use tokio_util:: sync:: CancellationToken ;
2121use tracing:: { debug, trace, warn} ;
2222
23+ pub mod cli;
2324pub mod config;
2425
2526/// This layer manages separate databases for each realm.
@@ -37,6 +38,8 @@ pub struct DatabaseLayer {
3738impl DatabaseLayer {
3839 /// Create a new `DatabaseLayer` initialized with the default realm.
3940 pub fn new ( config : DatabaseConfig , models : & ' static Models ) -> Result < Self > {
41+ debug ! ( "Initializing database layer" ) ;
42+
4043 let default = if let Some ( path) = config. get_storage_dir ( ) ? {
4144 let path = path. join ( "default.db" ) ;
4245
@@ -149,11 +152,10 @@ impl RealmDatabase {
149152 } else {
150153 // Otherwise, watch the upper half of the primary ID which is the same for all
151154 // revisions
152- self . 0
153- . watch ( )
154- . scan ( )
155- . primary ( )
156- . range :: < T , _ > ( item. id ( ) & 0x0000_0000 ..=item. id ( ) | 0xFFFF_FFFF ) ?
155+ self . 0 . watch ( ) . scan ( ) . primary ( ) . range :: < T , _ > (
156+ DataIdentifier ( ( item. id ( ) . revision_id ( ) as u64 ) << 32 )
157+ ..=DataIdentifier ( ( ( item. id ( ) . revision_id ( ) as u64 ) << 32 ) | 0xFFFF_FFFF ) ,
158+ ) ?
157159 } ;
158160
159161 // Safe to end the transaction once the watcher is registered
@@ -410,7 +412,36 @@ impl ToKey for DataRevision {
410412
411413/// Uniquely identifies a record in the database. All revisions of the same
412414/// `Data` share the upper 4 bytes of this value.
413- pub type DataIdentifier = u64 ; // TODO tuple struct
415+ #[ derive( Serialize , Deserialize , Debug , PartialEq , Eq , Copy , Clone , PartialOrd , Ord ) ]
416+ pub struct DataIdentifier ( u64 ) ;
417+
418+ impl Default for DataIdentifier {
419+ fn default ( ) -> Self {
420+ Self ( rand:: rng ( ) . next_u64 ( ) )
421+ }
422+ }
423+
424+ impl ToKey for DataIdentifier {
425+ fn to_key ( & self ) -> native_db:: Key {
426+ self . 0 . to_key ( )
427+ }
428+
429+ fn key_names ( ) -> Vec < String > {
430+ vec ! [ "DataIdentifier" . to_string( ) ]
431+ }
432+ }
433+
434+ impl DataIdentifier {
435+ /// Create a new `DataIdentifier` for a revision based on this one.
436+ fn new_revision ( & self ) -> Self {
437+ Self ( ( self . 0 & 0x0000_0000 ) | ( 0xFFFF_FFFF & rand:: rng ( ) . next_u64 ( ) ) )
438+ }
439+
440+ /// Get the portion of the `DataIdentifier` shared across all revisions
441+ fn revision_id ( & self ) -> u32 {
442+ ( ( self . 0 >> 32 ) & 0xFFFF_FFFF ) as u32
443+ }
444+ }
414445
415446/// When some `Data` will expire and no longer be returnable by queries.
416447/// Eventually it will be removed from the database altogether.
@@ -534,9 +565,7 @@ impl<T: Data> Resident<T> {
534565
535566 if previous. expiration ( ) . is_some ( ) {
536567 // Derive new id from the previous
537- next. set_id (
538- ( previous. id ( ) & 0x0000_0000 ) | ( 0xFFFF_FFFF & rand:: rng ( ) . random :: < u64 > ( ) ) ,
539- ) ;
568+ next. set_id ( previous. id ( ) . new_revision ( ) ) ;
540569
541570 rw. insert ( next. clone ( ) ) ?;
542571 rw. upsert ( previous. clone ( ) ) ?;
@@ -551,7 +580,7 @@ impl<T: Data> Resident<T> {
551580 }
552581
553582 pub fn history ( & self , range : impl RangeBounds < DataCreation > ) -> Result < Vec < T > > {
554- let revision_id = self . read ( ) . id ( ) & 0x0000_0000 ;
583+ let revision_id = self . read ( ) . id ( ) . revision_id ( ) ;
555584
556585 let r = self . db . r_transaction ( ) ?;
557586
@@ -566,7 +595,7 @@ impl<T: Data> Resident<T> {
566595
567596 Ok ( items
568597 . into_iter ( )
569- . filter ( |item| ( item. id ( ) & 0x0000_0000 ) == revision_id)
598+ . filter ( |item| item. id ( ) . revision_id ( ) == revision_id)
570599 . collect ( ) )
571600 }
572601}
@@ -601,16 +630,15 @@ mod test_resident {
601630 async fn test_data ( ) -> Result < ( ) > {
602631 let database = test_db ! ( TestData ) ;
603632
604- let db = database. realm ( RealmName :: default ( ) ) . await ?;
633+ let db = database. realm ( RealmName :: default ( ) ) ?;
605634 let res: Resident < TestData > = db. resident ( DataCondition :: equal ( TestDataKey :: a, "A" ) ) ?;
606635
607636 // Update data a bunch of times
608637 for i in 1 ..10 {
609638 res. update ( |data| {
610639 data. a = format ! ( "test {i}" ) ;
611640 Ok ( ( ) )
612- } )
613- . await ?;
641+ } ) ?;
614642 }
615643
616644 // Resident should reflect "test 9"
@@ -649,16 +677,15 @@ mod test_resident {
649677 async fn test_temporal_data ( ) -> Result < ( ) > {
650678 let database = test_db ! ( TestHistoryData ) ;
651679
652- let db = database. realm ( RealmName :: default ( ) ) . await ?;
680+ let db = database. realm ( RealmName :: default ( ) ) ?;
653681 let res: Resident < TestHistoryData > = db. resident ( ( ) ) ?;
654682
655683 // Update data a bunch of times
656684 for i in 1 ..10 {
657685 res. update ( |data| {
658686 data. b = format ! ( "test {i}" ) ;
659687 Ok ( ( ) )
660- } )
661- . await ?;
688+ } ) ?;
662689 }
663690
664691 // Database should have 10 items
@@ -670,7 +697,7 @@ mod test_resident {
670697
671698 // Check history
672699 {
673- assert_eq ! ( res. history( DataCreation :: all( ) ) . await ?. len( ) , 10 ) ;
700+ assert_eq ! ( res. history( DataCreation :: all( ) ) ?. len( ) , 10 ) ;
674701 }
675702
676703 Ok ( ( ) )
@@ -707,8 +734,8 @@ impl<T: Data> ResidentVec<T> {
707734 assert ! (
708735 self . conditions
709736 . first( )
710- . expect ( "There must be at least one condition" )
711- . check ( & d )
737+ . map ( |condition| condition. check ( & d ) )
738+ . unwrap_or ( true )
712739 ) ;
713740
714741 // Make sure the remaining conditions are satisfied
@@ -920,30 +947,27 @@ mod test_resident_vec {
920947 async fn test_nonhistorical ( ) -> Result < ( ) > {
921948 let database = test_db ! ( TestData ) ;
922949
923- let db = database. realm ( RealmName :: default ( ) ) . await ?;
950+ let db = database. realm ( RealmName :: default ( ) ) ?;
924951 let test_data: ResidentVec < TestData > =
925952 db. resident_vec ( DataCondition :: equal ( TestDataKey :: b, "B" ) ) ?;
926953
927- assert_eq ! ( test_data. len( ) . await , 0 ) ;
954+ assert_eq ! ( test_data. len( ) , 0 ) ;
928955
929956 // Add item
930- let data: Resident < TestData > = test_data
931- . push ( TestData {
932- a : "A" . to_string ( ) ,
933- b : "B" . to_string ( ) ,
934- ..Default :: default ( )
935- } )
936- . await ?;
957+ let data: Resident < TestData > = test_data. push ( TestData {
958+ a : "A" . to_string ( ) ,
959+ b : "B" . to_string ( ) ,
960+ ..Default :: default ( )
961+ } ) ?;
937962
938- assert_eq ! ( test_data. len( ) . await , 1 ) ;
963+ assert_eq ! ( test_data. len( ) , 1 ) ;
939964
940965 // Update a bunch of times
941966 for i in 1 ..10 {
942967 data. update ( |d| {
943968 d. a = format ! ( "test {i}" ) ;
944969 Ok ( ( ) )
945- } )
946- . await ?;
970+ } ) ?;
947971 }
948972
949973 // Database should reflect "test 9"
0 commit comments