Skip to content

Commit 907e1eb

Browse files
committed
libsql: Fix SyncContext::new() metadata reading
If we fail to read the metadata file, we must return an error. Resetting the metadata leads to inconsistent state because you have no way to tell what the database represents.
1 parent 8f7d444 commit 907e1eb

File tree

2 files changed

+23
-12
lines changed

2 files changed

+23
-12
lines changed

libsql/src/sync.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,10 @@ impl SyncContext {
169169
initial_server_sync: false,
170170
remote_encryption,
171171
};
172-
173-
if let Err(e) = me.read_metadata().await {
174-
tracing::error!(
175-
"failed to read sync metadata file, resetting back to defaults: {}",
176-
e
177-
);
172+
me.read_metadata().await?;
173+
if me.durable_generation == 0 {
174+
return Err(SyncError::InvalidLocalState("generation is 0".to_string()).into());
178175
}
179-
180176
Ok(me)
181177
}
182178

libsql/src/sync/test.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ async fn test_sync_context_push_frame() {
1414
let server = MockServer::start();
1515
let temp_dir = tempdir().unwrap();
1616
let db_path = temp_dir.path().join("test.db");
17+
gen_metadata_file(&db_path, 3278479626, 0, 0, 1);
1718

1819
let sync_ctx = SyncContext::new(
1920
server.connector(),
@@ -44,6 +45,7 @@ async fn test_sync_context_with_auth() {
4445
let server = MockServer::start();
4546
let temp_dir = tempdir().unwrap();
4647
let db_path = temp_dir.path().join("test.db");
48+
gen_metadata_file(&db_path, 3278479626, 0, 0, 1);
4749

4850
let sync_ctx = SyncContext::new(
4951
server.connector(),
@@ -69,6 +71,7 @@ async fn test_sync_context_multiple_frames() {
6971
let server = MockServer::start();
7072
let temp_dir = tempdir().unwrap();
7173
let db_path = temp_dir.path().join("test.db");
74+
gen_metadata_file(&db_path, 3278479626, 0, 0, 1);
7275

7376
let sync_ctx = SyncContext::new(
7477
server.connector(),
@@ -98,6 +101,7 @@ async fn test_sync_context_corrupted_metadata() {
98101
let server = MockServer::start();
99102
let temp_dir = tempdir().unwrap();
100103
let db_path = temp_dir.path().join("test.db");
104+
gen_metadata_file(&db_path, 3278479626, 0, 0, 1);
101105

102106
// Create initial sync context and push a frame
103107
let sync_ctx = SyncContext::new(
@@ -129,12 +133,9 @@ async fn test_sync_context_corrupted_metadata() {
129133
None,
130134
None,
131135
)
132-
.await
133-
.unwrap();
136+
.await;
134137

135-
// Verify that the context was reset to default values
136-
assert_eq!(sync_ctx.durable_frame_num(), 0);
137-
assert_eq!(sync_ctx.durable_generation(), 0);
138+
assert!(sync_ctx.is_err());
138139
}
139140

140141
#[tokio::test]
@@ -144,6 +145,7 @@ async fn test_sync_restarts_with_lower_max_frame_no() {
144145
let server = MockServer::start();
145146
let temp_dir = tempdir().unwrap();
146147
let db_path = temp_dir.path().join("test.db");
148+
gen_metadata_file(&db_path, 3278479626, 0, 0, 1);
147149

148150
// Create initial sync context and push a frame
149151
let sync_ctx = SyncContext::new(
@@ -211,6 +213,7 @@ async fn test_sync_context_retry_on_error() {
211213
let server = MockServer::start();
212214
let temp_dir = tempdir().unwrap();
213215
let db_path = temp_dir.path().join("test.db");
216+
gen_metadata_file(&db_path, 3278479626, 0, 0, 1);
214217

215218
let sync_ctx = SyncContext::new(
216219
server.connector(),
@@ -475,3 +478,15 @@ impl hyper::client::connect::Connection for MockConnection {
475478
hyper::client::connect::Connected::new()
476479
}
477480
}
481+
482+
fn gen_metadata_file(db_path: &Path, hash: u32, version: u32, durable_frame_num: u32, generation: u32) {
483+
let metadata_path = format!("{}-info", db_path.to_str().unwrap());
484+
std::fs::write(
485+
&metadata_path,
486+
format!(
487+
"{{\"hash\": {hash}, \"version\": {version}, \"durable_frame_num\": {durable_frame_num}, \"generation\": {generation}}}"
488+
)
489+
.as_bytes(),
490+
)
491+
.unwrap();
492+
}

0 commit comments

Comments
 (0)