Skip to content

Commit f8954db

Browse files
authored
Merge pull request #1878 from tursodatabase/improve-wal-sync
Improve WAL sync logic
2 parents c8a5006 + 19e7800 commit f8954db

File tree

3 files changed

+32
-80
lines changed

3 files changed

+32
-80
lines changed

libsql/examples/offline_writes.rs

+3
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

-55
This file was deleted.

libsql/src/local/database.rs

+29-25
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)