Skip to content

Commit 19e7800

Browse files
committed
libsql: Improve WAL sync logic
This improves the WAL sync to follow this logic: - If there are no local writes, attempt to pull. We know there are no local writes if the cached remote max frame number is greater than or equal to local max frame number. - If there are local writes, attempt to push. We know there are local writes if the cached remote max number is less than lcoal max frame number. This also removes the `offline_writes_pull.rs` example and augments `offline_writes.rs` to sync before attempting to write.
1 parent 6ed1690 commit 19e7800

File tree

3 files changed

+32
-80
lines changed

3 files changed

+32
-80
lines changed

libsql/examples/offline_writes.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ async fn main() {
3939

4040
let conn = db.connect().unwrap();
4141

42+
println!("Syncing database from remote...");
43+
db.sync().await.unwrap();
44+
4245
conn.execute(
4346
r#"
4447
CREATE TABLE IF NOT EXISTS guest_book_entries (

libsql/examples/offline_writes_pull.rs

Lines changed: 0 additions & 55 deletions
This file was deleted.

libsql/src/local/database.rs

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -391,29 +391,36 @@ impl Database {
391391
use crate::sync::SyncError;
392392
use crate::Error;
393393

394-
match self.try_push().await {
395-
Ok(rep) => Ok(rep),
396-
Err(Error::Sync(err)) => {
397-
// Retry the sync because we are ahead of the server and we need to push some older
398-
// frames.
399-
if let Some(SyncError::InvalidPushFrameNoLow(_, _)) =
400-
err.downcast_ref::<SyncError>()
401-
{
402-
tracing::debug!("got InvalidPushFrameNo, retrying push");
403-
self.try_push().await
404-
} else {
405-
Err(Error::Sync(err))
394+
let mut sync_ctx = self.sync_ctx.as_ref().unwrap().lock().await;
395+
let conn = self.connect()?;
396+
397+
let durable_frame_no = sync_ctx.durable_frame_num();
398+
let max_frame_no = conn.wal_frame_count();
399+
400+
if max_frame_no > durable_frame_no {
401+
match self.try_push(&mut sync_ctx, &conn).await {
402+
Ok(rep) => Ok(rep),
403+
Err(Error::Sync(err)) => {
404+
// Retry the sync because we are ahead of the server and we need to push some older
405+
// frames.
406+
if let Some(SyncError::InvalidPushFrameNoLow(_, _)) =
407+
err.downcast_ref::<SyncError>()
408+
{
409+
tracing::debug!("got InvalidPushFrameNo, retrying push");
410+
self.try_push(&mut sync_ctx, &conn).await
411+
} else {
412+
Err(Error::Sync(err))
413+
}
406414
}
415+
Err(e) => Err(e),
407416
}
408-
Err(e) => Err(e),
417+
} else {
418+
self.try_pull(&mut sync_ctx, &conn).await
409419
}
410420
}
411421

412422
#[cfg(feature = "sync")]
413-
async fn try_push(&self) -> Result<crate::database::Replicated> {
414-
let mut sync_ctx = self.sync_ctx.as_ref().unwrap().lock().await;
415-
let conn = self.connect()?;
416-
423+
async fn try_push(&self, sync_ctx: &mut SyncContext, conn: &Connection) -> Result<crate::database::Replicated> {
417424
let page_size = {
418425
let rows = conn
419426
.query("PRAGMA page_size", crate::params::Params::None)?
@@ -424,9 +431,11 @@ impl Database {
424431
};
425432

426433
let max_frame_no = conn.wal_frame_count();
427-
428434
if max_frame_no == 0 {
429-
return self.try_pull(&mut sync_ctx).await;
435+
return Ok(crate::database::Replicated {
436+
frame_no: None,
437+
frames_synced: 0,
438+
});
430439
}
431440

432441
let generation = sync_ctx.generation(); // TODO: Probe from WAL.
@@ -452,10 +461,6 @@ impl Database {
452461

453462
sync_ctx.write_metadata().await?;
454463

455-
if start_frame_no > end_frame_no {
456-
return self.try_pull(&mut sync_ctx).await;
457-
}
458-
459464
// TODO(lucio): this can underflow if the server previously returned a higher max_frame_no
460465
// than what we have stored here.
461466
let frame_count = end_frame_no - start_frame_no + 1;
@@ -466,10 +471,9 @@ impl Database {
466471
}
467472

468473
#[cfg(feature = "sync")]
469-
async fn try_pull(&self, sync_ctx: &mut SyncContext) -> Result<crate::database::Replicated> {
474+
async fn try_pull(&self, sync_ctx: &mut SyncContext, conn: &Connection) -> Result<crate::database::Replicated> {
470475
let generation = sync_ctx.generation();
471476
let mut frame_no = sync_ctx.durable_frame_num() + 1;
472-
let conn = self.connect()?;
473477
conn.wal_insert_begin()?;
474478

475479
let mut err = None;

0 commit comments

Comments
 (0)