8000 fix: let wal_checkpoint_threshold reach the never-checkpoint sentinel by adityamukho · Pull Request #7 · project-minigraf/minigraf-swift · GitHub
[go: up one dir, main page]

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
4 changes: 4 additions & 0 deletions Sources/MinigrafKit/MinigrafKit+Iteration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,7 @@ extension MiniGrafError {

/// `validTo` of a fact that is valid forever.
public let validTimeForever: Int64 = Int64.max

/// `walCheckpointThreshold` that never checkpoints: no automatic checkpoint and
/// none when the handle closes. Call `checkpoint()` yourself.
public let walCheckpointNever: Int64 = Int64.max
10 changes: 10 additions & 0 deletions Tests/swift/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,16 @@ do {
check(errorText { _ = try MiniGrafLogWriter.create(path: out, options: OpenOptions()) }.hasPrefix("[STG-043]"), "STG-043")
}

// #322: walCheckpointNever leaves the WAL when the handle closes.
do {
let p = path("never.graph")
do {
let db = try MiniGrafDb.openWithOptions(path: p, options: OpenOptions(walCheckpointThreshold: walCheckpointNever))
_ = try db.execute(datalog: "(transact [[:a :n 1]])")
}
check(FileManager.default.fileExists(atPath: p + ".wal"), "WAL kept on close")
}

try? FileManager.default.removeItem(at: dir)
if failures > 0 {
print("\(failures) check(s) failed")
Expand Down
53 changes: 50 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,9 @@ pub struct OpenOptions {
/// Open even when the filesystem cannot lock files. Default false.
#[uniffi(default)]
pub allow_unlocked: Option<bool>,
/// WAL entries before an automatic checkpoint. Default 1000; the maximum
/// value also suppresses the checkpoint on close.
/// WAL entries before an automatic checkpoint. Default 1000. The maximum
/// (i64::MAX, 9223372036854775807) means never: no automatic checkpoint
/// and no checkpoint when the handle closes; call `checkpoint()` yourself.
#[uniffi(default)]
pub wal_checkpoint_threshold: Option<i64>,
/// Facts a recursive rule may derive per iteration. Default 1,000,000.
Expand All @@ -146,7 +147,14 @@ impl OpenOptions {
o = o.allow_unlocked(v);
}
if let Some(v) = self.wal_checkpoint_threshold {
o = o.wal_checkpoint_threshold(to_usize(v, "wal_checkpoint_threshold")?);
// i64::MAX stands for core's usize::MAX sentinel, which is out of
// reach of a signed count.
let n = if v == i64::MAX {
usize::MAX
} else {
to_usize(v, "wal_checkpoint_threshold")?
};
o = o.wal_checkpoint_threshold(n);
}
if let Some(v) = self.max_derived_facts {
o = o.max_derived_facts(to_usize(v, "max_derived_facts")?);
Expand Down Expand Up @@ -867,6 +875,45 @@ mod tests {
assert!(msg(err(cursor.next_batch(-1))).starts_with("[API-017]"));
}

#[test]
fn max_wal_checkpoint_threshold_suppresses_the_close_checkpoint() {
let dir = std::env::temp_dir().join(format!("minigraf_ffi_never_{}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).expect("dir");
let path = dir.join("db.graph");
let wal = dir.join("db.graph.wal");
let options = |threshold| OpenOptions {
wal_checkpoint_threshold: Some(threshold),
..OpenOptions::default()
};

let db =
MiniGrafDb::open_with_options(path.to_str().expect("utf8").into(), options(i64::MAX))
.expect("open");
db.execute("(transact [[:a :n 1]])".into())
.expect("transact");
drop(db);
assert!(
wal.exists(),
"i64::MAX must suppress the close-time checkpoint"
);

// One below the maximum is an ordinary threshold: closing checkpoints.
let path2 = dir.join("db2.graph");
let wal2 = dir.join("db2.graph.wal");
let db = MiniGrafDb::open_with_options(
path2.to_str().expect("utf8").into(),
options(i64::MAX - 1),
)
.expect("open second");
db.execute("(transact [[:a :n 1]])".into())
.expect("transact");
assert!(wal2.exists(), "the write is in the WAL before close");
drop(db);
assert!(!wal2.exists(), "an ordinary threshold checkpoints on close");
let _ = std::fs::remove_dir_all(&dir);
}

#[test]
fn cursor_batches_and_closes() {
let db = MiniGrafDb::open_in_memory().expect("open");
Expand Down
Loading
0