Skip to content

Commit aef6b24

Browse files
committed
bootstrap the db without using sqlite connection
If we try to bootstrap the db after a connection is opened, then it is incorrect, as it could create a local .db file and a successful sync would replace this file
1 parent eedcf14 commit aef6b24

2 files changed

Lines changed: 23 additions & 17 deletions

File tree

libsql/src/local/database.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,8 +465,8 @@ impl Database {
465465
/// Sync WAL frames to remote.
466466
pub async fn sync_offline(&self) -> Result<crate::database::Replicated> {
467467
let mut sync_ctx = self.sync_ctx.as_ref().unwrap().lock().await;
468+
crate::sync::bootstrap_db(&mut sync_ctx).await?;
468469
let conn = self.connect()?;
469-
470470
crate::sync::sync_offline(&mut sync_ctx, &conn).await
471471
}
472472

libsql/src/sync.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,28 @@ async fn atomic_write<P: AsRef<Path>>(path: P, data: &[u8]) -> Result<()> {
680680
Ok(())
681681
}
682682

683+
/// bootstrap_db brings the .db file from remote, if required. If the .db file already exists, then
684+
/// it does nothing. Calling this function multiple times is safe.
685+
pub async fn bootstrap_db(sync_ctx: &mut SyncContext) -> Result<()> {
686+
// todo: we are checking with the remote server only during initialisation. ideally,
687+
// we need to do this when we notice a large gap in generations, when bootstrapping is cheaper
688+
// than pulling each frame
689+
if !sync_ctx.initial_server_sync {
690+
// sync is being called first time. so we will call remote, get the generation information
691+
// if we are lagging behind, then we will call the export API and get to the latest
692+
// generation directly.
693+
let info = sync_ctx.get_remote_info().await?;
694+
sync_ctx
695+
.sync_db_if_needed(info.current_generation)
696+
.await?;
697+
// when sync_ctx is initialised, we set durable_generation to 0. however, once
698+
// sync_db is called, it should be > 0.
699+
assert!(sync_ctx.durable_generation > 0, "generation should be > 0");
700+
sync_ctx.initial_server_sync = true;
701+
}
702+
Ok(())
703+
}
704+
683705
/// Sync WAL frames to remote.
684706
pub async fn sync_offline(
685707
sync_ctx: &mut SyncContext,
@@ -701,22 +723,6 @@ pub async fn sync_offline(
701723
Err(e) => Err(e),
702724
}
703725
} else {
704-
// todo: we are checking with the remote server only during initialisation. ideally,
705-
// we should check everytime we try to sync with the remote server. However, we need to close
706-
// all the ongoing connections since we replace `.db` file and remove the `.db-wal` file
707-
if !sync_ctx.initial_server_sync {
708-
// sync is being called first time. so we will call remote, get the generation information
709-
// if we are lagging behind, then we will call the export API and get to the latest
710-
// generation directly.
711-
let info = sync_ctx.get_remote_info().await?;
712-
sync_ctx
713-
.sync_db_if_needed(info.current_generation)
714-
.await?;
715-
// when sync_ctx is initialised, we set durable_generation to 0. however, once
716-
// sync_db is called, it should be > 0.
717-
assert!(sync_ctx.durable_generation > 0, "generation should be > 0");
718-
sync_ctx.initial_server_sync = true;
719-
}
720726
try_pull(sync_ctx, conn).await
721727
}
722728
.or_else(|err| {

0 commit comments

Comments
 (0)