claw_core/journal.rs
1//! WAL configuration helpers for claw-core.
2//!
3//! This module provides convenience functions for inspecting and tuning the
4//! SQLite Write-Ahead Log (WAL) on an open connection pool. The WAL is
5//! SQLite's high-concurrency journaling mode and is the recommended default
6//! for claw-core deployments.
7
8use sqlx::SqlitePool;
9
10use crate::error::ClawResult;
11
12/// Apply WAL journal mode and set the WAL auto-checkpoint threshold.
13///
14/// This is equivalent to executing:
15///
16/// ```sql
17/// PRAGMA journal_mode = WAL;
18/// PRAGMA wal_autocheckpoint = <checkpoint_pages>;
19/// ```
20///
21/// # Errors
22///
23/// Returns a [`crate::error::ClawError`] if either PRAGMA fails.
24pub async fn configure_wal(pool: &SqlitePool, checkpoint_pages: u32) -> ClawResult<()> {
25 sqlx::query("PRAGMA journal_mode = WAL")
26 .execute(pool)
27 .await?;
28
29 sqlx::query(&format!("PRAGMA wal_autocheckpoint = {checkpoint_pages}"))
30 .execute(pool)
31 .await?;
32
33 tracing::debug!(checkpoint_pages, "WAL configured");
34 Ok(())
35}
36
37/// Trigger an immediate WAL checkpoint, flushing WAL frames into the main
38/// database file.
39///
40/// # Errors
41///
42/// Returns a [`crate::error::ClawError`] if the checkpoint PRAGMA fails.
43pub async fn checkpoint(pool: &SqlitePool) -> ClawResult<()> {
44 sqlx::query("PRAGMA wal_checkpoint(PASSIVE)")
45 .execute(pool)
46 .await?;
47
48 tracing::debug!("WAL checkpoint completed");
49 Ok(())
50}
51
52/// Return the current journal mode string for the database.
53///
54/// # Errors
55///
56/// Returns a [`crate::error::ClawError`] if the PRAGMA query fails.
57pub async fn journal_mode(pool: &SqlitePool) -> ClawResult<String> {
58 let row: (String,) = sqlx::query_as("PRAGMA journal_mode")
59 .fetch_one(pool)
60 .await?;
61 Ok(row.0)
62}
63
64/// The WAL checkpoint mode.
65///
66/// # Example
67///
68/// ```rust
69/// use claw_core::CheckpointMode;
70/// assert_eq!(CheckpointMode::Passive.as_str(), "PASSIVE");
71/// ```
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum CheckpointMode {
74 /// Checkpoint as many frames as possible without waiting for readers.
75 Passive,
76 /// Wait for readers to finish, then checkpoint everything.
77 Full,
78 /// Like [`CheckpointMode::Full`] but also resets the WAL frame counter.
79 Restart,
80 /// Like [`CheckpointMode::Restart`] but also truncates the WAL file.
81 Truncate,
82}
83
84impl CheckpointMode {
85 /// Return the PRAGMA argument string for this mode.
86 ///
87 /// # Example
88 ///
89 /// ```rust
90 /// use claw_core::CheckpointMode;
91 /// assert_eq!(CheckpointMode::Full.as_str(), "FULL");
92 /// ```
93 pub fn as_str(self) -> &'static str {
94 match self {
95 CheckpointMode::Passive => "PASSIVE",
96 CheckpointMode::Full => "FULL",
97 CheckpointMode::Restart => "RESTART",
98 CheckpointMode::Truncate => "TRUNCATE",
99 }
100 }
101}
102
103/// The result of a WAL checkpoint operation.
104///
105/// Returned by checkpoint helpers to report success or failure details.
106#[derive(Debug, Clone)]
107pub struct CheckpointResult {
108 /// The checkpoint mode that was used.
109 pub mode: CheckpointMode,
110 /// Whether the checkpoint completed successfully.
111 pub success: bool,
112}