@@ -529,6 +529,7 @@ pub struct BootstrapArgs {
529
529
pub struct Connection < S > {
530
530
stash : S ,
531
531
consolidations_tx : mpsc:: UnboundedSender < Vec < mz_stash:: Id > > ,
532
+ boot_ts : mz_repr:: Timestamp ,
532
533
}
533
534
534
535
impl < S : Append > Connection < S > {
@@ -555,29 +556,46 @@ impl<S: Append> Connection<S> {
555
556
556
557
// Initialize connection.
557
558
initialize_stash ( & mut stash) . await ?;
559
+
560
+ // Choose a time at which to boot. This is the time at which we will run
561
+ // internal migrations, and is also exposed upwards in case higher
562
+ // layers want to run their own migrations at the same timestamp.
563
+ //
564
+ // This time is usually the current system time, but with protection
565
+ // against backwards time jumps, even across restarts.
566
+ let previous_now_ts = try_get_persisted_timestamp ( & mut stash, & Timeline :: EpochMilliseconds )
567
+ . await ?
568
+ . unwrap_or ( mz_repr:: Timestamp :: MIN ) ;
569
+ let boot_ts = timeline:: monotonic_now ( now, previous_now_ts) ;
570
+
558
571
let mut conn = Connection {
559
572
stash,
560
573
consolidations_tx,
574
+ boot_ts,
561
575
} ;
562
576
563
577
if !conn. stash . is_readonly ( ) {
564
- // Choose a time at which to apply migrations. This is usually the
565
- // current system time, but with protection against backwards time
566
- // jumps, even across restarts.
567
- let previous_now_ts = conn
568
- . try_get_persisted_timestamp ( & Timeline :: EpochMilliseconds )
569
- . await ?
570
- . unwrap_or ( mz_repr:: Timestamp :: MIN ) ;
571
- let now_ts = timeline:: monotonic_now ( now, previous_now_ts) ;
572
578
// IMPORTANT: we durably record the new timestamp before using it.
573
- conn. persist_timestamp ( & Timeline :: EpochMilliseconds , now_ts )
579
+ conn. persist_timestamp ( & Timeline :: EpochMilliseconds , boot_ts )
574
580
. await ?;
575
-
576
- migrate ( & mut conn. stash , skip, now_ts. into ( ) , bootstrap_args) . await ?;
581
+ migrate ( & mut conn. stash , skip, boot_ts. into ( ) , bootstrap_args) . await ?;
577
582
}
578
583
579
584
Ok ( conn)
580
585
}
586
+
587
+ /// Returns the timestamp at which the storage layer booted.
588
+ ///
589
+ /// This is the timestamp that will have been used to write any data during
590
+ /// migrations. It is exposed so that higher layers performing their own
591
+ /// migrations can write data at the same timestamp, if desired.
592
+ ///
593
+ /// The boot timestamp is derived from the durable timestamp oracle and is
594
+ /// guaranteed to never go backwards, even in the face of backwards time
595
+ /// jumps across restarts.
596
+ pub fn boot_ts ( & self ) -> mz_repr:: Timestamp {
597
+ self . boot_ts
598
+ }
581
599
}
582
600
583
601
impl < S : Append > Connection < S > {
@@ -917,23 +935,6 @@ impl<S: Append> Connection<S> {
917
935
. collect ( ) )
918
936
}
919
937
920
- /// Get a global timestamp for a timeline that has been persisted to disk.
921
- ///
922
- /// Returns `None` if no persisted timestamp for the specified timeline
923
- /// exists.
924
- pub async fn try_get_persisted_timestamp (
925
- & mut self ,
926
- timeline : & Timeline ,
927
- ) -> Result < Option < mz_repr:: Timestamp > , Error > {
928
- let key = TimestampKey {
929
- id : timeline. to_string ( ) ,
930
- } ;
931
- Ok ( COLLECTION_TIMESTAMP
932
- . peek_key_one ( & mut self . stash , & key)
933
- . await ?
934
- . map ( |v| v. ts ) )
935
- }
936
-
937
938
/// Persist new global timestamp for a timeline to disk.
938
939
#[ tracing:: instrument( level = "debug" , skip( self ) ) ]
939
940
pub async fn persist_timestamp (
@@ -971,6 +972,25 @@ impl<S: Append> Connection<S> {
971
972
}
972
973
}
973
974
975
+ /// Gets a global timestamp for a timeline that has been persisted to disk.
976
+ ///
977
+ /// Returns `None` if no persisted timestamp for the specified timeline exists.
978
+ async fn try_get_persisted_timestamp < S > (
979
+ stash : & mut S ,
980
+ timeline : & Timeline ,
981
+ ) -> Result < Option < mz_repr:: Timestamp > , Error >
982
+ where
983
+ S : Append ,
984
+ {
985
+ let key = TimestampKey {
986
+ id : timeline. to_string ( ) ,
987
+ } ;
988
+ Ok ( COLLECTION_TIMESTAMP
989
+ . peek_key_one ( stash, & key)
990
+ . await ?
991
+ . map ( |v| v. ts ) )
992
+ }
993
+
974
994
#[ tracing:: instrument( level = "trace" , skip_all) ]
975
995
pub async fn transaction < ' a , S : Append > ( stash : & ' a mut S ) -> Result < Transaction < ' a , S > , Error > {
976
996
let databases = COLLECTION_DATABASE . peek_one ( stash) . await ?;
0 commit comments