@@ -69,6 +69,7 @@ pub struct Replicator {
6969 join_set : JoinSet < ( ) > ,
7070 upload_progress : Arc < Mutex < CompletionProgress > > ,
7171 last_uploaded_frame_no : Receiver < u32 > ,
72+ skip_snapshot : bool ,
7273}
7374
7475#[ derive( Debug ) ]
@@ -113,6 +114,8 @@ pub struct Options {
113114 pub s3_upload_max_parallelism : usize ,
114115 /// Max number of retries for S3 operations
115116 pub s3_max_retries : u32 ,
117+ /// Skip snapshot upload per checkpoint.
118+ pub skip_snapshot : bool ,
116119}
117120
118121impl Options {
@@ -202,6 +205,17 @@ impl Options {
202205 other
203206 ) ,
204207 } ;
208+ let skip_snapshot = match env_var_or ( "LIBSQL_BOTTOMLESS_SKIP_SNAPSHOT" , false )
209+ . to_lowercase ( )
210+ . as_ref ( )
211+ {
212+ "yes" | "true" | "1" | "y" | "t" => true ,
213+ "no" | "false" | "0" | "n" | "f" => false ,
214+ other => bail ! (
215+ "Invalid LIBSQL_BOTTOMLESS_SKIP_SNAPSHOT environment variable: {}" ,
216+ other
217+ ) ,
218+ } ;
205219 let s3_max_retries = env_var_or ( "LIBSQL_BOTTOMLESS_S3_MAX_RETRIES" , 10 ) . parse :: < u32 > ( ) ?;
206220 let cipher = match encryption_cipher {
207221 Some ( cipher) => Cipher :: from_str ( & cipher) ?,
@@ -226,6 +240,7 @@ impl Options {
226240 region,
227241 bucket_name,
228242 s3_max_retries,
243+ skip_snapshot,
229244 } )
230245 }
231246}
@@ -386,6 +401,7 @@ impl Replicator {
386401 encryption_config : options. encryption_config ,
387402 max_frames_per_batch : options. max_frames_per_batch ,
388403 s3_upload_max_parallelism : options. s3_upload_max_parallelism ,
404+ skip_snapshot : options. skip_snapshot ,
389405 join_set,
390406 upload_progress,
391407 last_uploaded_frame_no,
@@ -901,7 +917,12 @@ impl Replicator {
901917 // Sends the main database file to S3 - if -wal file is present, it's replicated
902918 // too - it means that the local file was detected to be newer than its remote
903919 // counterpart.
904- pub async fn snapshot_main_db_file ( & mut self ) -> Result < Option < JoinHandle < ( ) > > > {
920+ pub async fn snapshot_main_db_file ( & mut self , force : bool ) -> Result < Option < JoinHandle < ( ) > > > {
921+ if self . skip_snapshot && !force {
922+ tracing:: trace!( "database snapshot skipped" ) ;
923+ let _ = self . snapshot_notifier . send ( Ok ( self . generation ( ) . ok ( ) ) ) ;
924+ return Ok ( None ) ;
925+ }
905926 if !self . main_db_exists_and_not_empty ( ) . await {
906927 let generation = self . generation ( ) ?;
907928 tracing:: debug!(
@@ -1301,6 +1322,14 @@ impl Replicator {
13011322 ) ;
13021323 match wal_pages. cmp ( & last_consistent_frame) {
13031324 std:: cmp:: Ordering :: Equal => {
1325+ if local_counter == [ 0u8 ; 4 ] && wal_pages == 0 {
1326+ if self . get_dependency ( & generation) . await ?. is_some ( ) {
1327+ // empty generation and empty local state, but we have a dependency
1328+ // to previous generation: restore required
1329+ return Ok ( None ) ;
1330+ }
1331+ }
1332+
13041333 tracing:: info!(
13051334 "Remote generation is up-to-date, reusing it in this session"
13061335 ) ;
0 commit comments