cuprate_database/config/
sync_mode.rs

1//! Database [`Env`](crate::Env) configuration.
2//!
3//! This module contains the main [`Config`]uration struct
4//! for the database [`Env`](crate::Env)ironment, and data
5//! structures related to any configuration setting.
6//!
7//! These configurations are processed at runtime, meaning
8//! the `Env` can/will dynamically adjust its behavior
9//! based on these values.
10
11//---------------------------------------------------------------------------------------------------- Import
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14
15//---------------------------------------------------------------------------------------------------- SyncMode
16/// Disk synchronization mode.
17///
18/// This controls how/when the database syncs its data to disk.
19///
20/// Regardless of the variant chosen, dropping [`Env`](crate::Env)
21/// will always cause it to fully sync to disk.
22#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24pub enum SyncMode {
25    /// Use [`SyncMode::Fast`] until fully synced,
26    /// then use [`SyncMode::Safe`].
27    ///
28    /// # TODO
29    /// This is not implemented internally and has the same behavior as [`SyncMode::Fast`].
30    //
31    // # SOMEDAY: how to implement this?
32    // ref: <https://github.com/monero-project/monero/issues/1463>
33    // monerod-solution: <https://github.com/monero-project/monero/pull/1506>
34    // cuprate-issue: <https://github.com/Cuprate/cuprate/issues/78>
35    //
36    // We could:
37    // ```rust,ignore
38    // if current_db_block <= top_block.saturating_sub(N) {
39    //     // don't sync()
40    // } else {
41    //     // sync()
42    // }
43    // ```
44    // where N is some threshold we pick that is _close_ enough
45    // to being synced where we want to start being safer.
46    //
47    // Essentially, when we are in a certain % range of being finished,
48    // switch to safe mode, until then, go fast.
49    FastThenSafe,
50
51    /// Fully sync to disk per transaction.
52    ///
53    /// Every database transaction commit will
54    /// fully sync all data to disk, _synchronously_,
55    /// so the database (writer) halts until synced.
56    ///
57    /// This is expected to be very slow.
58    ///
59    /// This maps to:
60    /// - LMDB without any special sync flags
61    /// - [`redb::Durability::Immediate`](https://docs.rs/redb/1.5.0/redb/enum.Durability.html#variant.Immediate)
62    Safe,
63
64    #[default]
65    /// Only flush at database shutdown.
66    ///
67    /// This is the fastest, yet unsafest option.
68    ///
69    /// It will cause the database to never _actively_ sync,
70    /// letting the OS decide when to flush data to disk[^1].
71    ///
72    /// This maps to:
73    /// - [`MDB_NOSYNC | MDB_WRITEMAP | MDB_MAPASYNC`](https://github.com/monero-project/monero/blob/90359e31fd657251cb357ecba02c4de2442d1b5c/src/blockchain_db/lmdb/db_lmdb.cpp#L1444)
74    /// - [`redb::Durability::Eventual`](https://docs.rs/redb/1.5.0/redb/enum.Durability.html#variant.Eventual)
75    ///
76    /// # Default
77    /// This is the default [`SyncMode`].
78    /// ```rust
79    /// use cuprate_database::config::SyncMode;
80    ///
81    /// assert_eq!(SyncMode::default(), SyncMode::Fast);
82    /// ```
83    ///
84    /// # Corruption
85    /// In the case of a system crash, the database
86    /// may become corrupted when using this option.
87    ///
88    /// [^1]: Semantically, this variant would actually map to
89    /// [`redb::Durability::None`](https://docs.rs/redb/1.5.0/redb/enum.Durability.html#variant.None),
90    /// however due to [`#149`](https://github.com/Cuprate/cuprate/issues/149),
91    /// this is not possible. As such, when using the `redb` backend,
92    /// transaction writes "should be persistent some time after `WriteTransaction::commit` returns."
93    Fast,
94}