Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions libsql/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,18 @@ impl Database {
};
use tokio::sync::Mutex;

let _ = tokio::task::block_in_place(move || {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks Db initialization under Actix due to its blocking nature. It forces the user to separate the db initialization out of the actix main and create a custom main which initializes the db first in a multi-threaded Tokio runtime and then passes it to Actix.

let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
rt.block_on(async {
// we will ignore if any errors occurred during the bootstrapping the db,
// because the client could be offline when trying to connect.
let _ = db.bootstrap_db().await;
})
});

let local = db.connect()?;

if *remote_writes {
Expand Down
10 changes: 10 additions & 0 deletions libsql/src/local/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,11 +465,21 @@ impl Database {
/// Sync WAL frames to remote.
pub async fn sync_offline(&self) -> Result<crate::database::Replicated> {
let mut sync_ctx = self.sync_ctx.as_ref().unwrap().lock().await;
// it is important we call `bootstrap` before we `sync`. Because sync uses a connection
// to the db and during bootstrap we replace the sqlite db file. This can lead to
// inconsistencies and data corruption.
crate::sync::bootstrap_db(&mut sync_ctx).await?;
let conn = self.connect()?;
crate::sync::sync_offline(&mut sync_ctx, &conn).await
}

#[cfg(feature = "sync")]
/// Brings the .db file from server, if required.
pub async fn bootstrap_db(&self) -> Result<()> {
let mut sync_ctx = self.sync_ctx.as_ref().unwrap().lock().await;
crate::sync::bootstrap_db(&mut sync_ctx).await
}

pub(crate) fn path(&self) -> &str {
&self.db_path
}
Expand Down
2 changes: 2 additions & 0 deletions libsql/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,8 @@ async fn atomic_write<P: AsRef<Path>>(path: P, data: &[u8]) -> Result<()> {

/// bootstrap_db brings the .db file from remote, if required. If the .db file already exists, then
/// it does nothing. Calling this function multiple times is safe.
/// However, make sure there are no existing active connections to the db file as this method can
/// replace it
pub async fn bootstrap_db(sync_ctx: &mut SyncContext) -> Result<()> {
// todo: we are checking with the remote server only during initialisation. ideally,
// we need to do this when we notice a large gap in generations, when bootstrapping is cheaper
Expand Down
Loading