Skip to content

Commit 9f2b898

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 e5faaf7 commit 9f2b898

File tree

2 files changed

+23
-17
lines changed

2 files changed

+23
-17
lines changed

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
@@ -684,6 +684,28 @@ async fn atomic_write<P: AsRef<Path>>(path: P, data: &[u8]) -> Result<()> {
684684
Ok(())
685685
}
686686

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

0 commit comments

Comments
 (0)