Skip to main content

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}