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}