cuprate_txpool/config.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
//! The transaction pool [`Config`].
use std::{borrow::Cow, path::Path};
use cuprate_database::{
config::{Config as DbConfig, SyncMode},
resize::ResizeAlgorithm,
};
use cuprate_database_service::ReaderThreads;
use cuprate_helper::fs::CUPRATE_TXPOOL_DIR;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// The default transaction pool weight limit.
const DEFAULT_TXPOOL_WEIGHT_LIMIT: usize = 600 * 1024 * 1024;
//---------------------------------------------------------------------------------------------------- ConfigBuilder
/// Builder for [`Config`].
///
// SOMEDAY: there's are many more options to add in the future.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ConfigBuilder {
/// [`Config::db_directory`].
db_directory: Option<Cow<'static, Path>>,
/// [`Config::cuprate_database_config`].
db_config: cuprate_database::config::ConfigBuilder,
/// [`Config::reader_threads`].
reader_threads: Option<ReaderThreads>,
/// [`Config::max_txpool_weight`].
max_txpool_weight: Option<usize>,
}
impl ConfigBuilder {
/// Create a new [`ConfigBuilder`].
///
/// [`ConfigBuilder::build`] can be called immediately
/// after this function to use default values.
pub fn new() -> Self {
Self {
db_directory: None,
db_config: cuprate_database::config::ConfigBuilder::new(Cow::Borrowed(
&*CUPRATE_TXPOOL_DIR,
)),
reader_threads: None,
max_txpool_weight: None,
}
}
/// Build into a [`Config`].
///
/// # Default values
/// If [`ConfigBuilder::db_directory`] was not called,
/// the default [`CUPRATE_TXPOOL_DIR`] will be used.
///
/// For all other values, [`Default::default`] is used.
pub fn build(self) -> Config {
// INVARIANT: all PATH safety checks are done
// in `helper::fs`. No need to do them here.
let db_directory = self
.db_directory
.unwrap_or_else(|| Cow::Borrowed(&*CUPRATE_TXPOOL_DIR));
let reader_threads = self.reader_threads.unwrap_or_default();
let max_txpool_weight = self
.max_txpool_weight
.unwrap_or(DEFAULT_TXPOOL_WEIGHT_LIMIT);
let db_config = self
.db_config
.db_directory(db_directory)
.reader_threads(reader_threads.as_threads())
.build();
Config {
db_config,
reader_threads,
max_txpool_weight,
}
}
/// Sets a new maximum weight for the transaction pool.
#[must_use]
pub const fn max_txpool_weight(mut self, max_txpool_weight: usize) -> Self {
self.max_txpool_weight = Some(max_txpool_weight);
self
}
/// Set a custom database directory (and file) [`Path`].
#[must_use]
pub fn db_directory(mut self, db_directory: Cow<'static, Path>) -> Self {
self.db_directory = Some(db_directory);
self
}
/// Calls [`cuprate_database::config::ConfigBuilder::sync_mode`].
#[must_use]
pub fn sync_mode(mut self, sync_mode: SyncMode) -> Self {
self.db_config = self.db_config.sync_mode(sync_mode);
self
}
/// Calls [`cuprate_database::config::ConfigBuilder::resize_algorithm`].
#[must_use]
pub fn resize_algorithm(mut self, resize_algorithm: ResizeAlgorithm) -> Self {
self.db_config = self.db_config.resize_algorithm(resize_algorithm);
self
}
/// Set a custom [`ReaderThreads`].
#[must_use]
pub const fn reader_threads(mut self, reader_threads: ReaderThreads) -> Self {
self.reader_threads = Some(reader_threads);
self
}
/// Tune the [`ConfigBuilder`] for the highest performing,
/// but also most resource-intensive & maybe risky settings.
///
/// Good default for testing, and resource-available machines.
#[must_use]
pub fn fast(mut self) -> Self {
self.db_config =
cuprate_database::config::ConfigBuilder::new(Cow::Borrowed(&*CUPRATE_TXPOOL_DIR))
.fast();
self.reader_threads = Some(ReaderThreads::OnePerThread);
self
}
/// Tune the [`ConfigBuilder`] for the lowest performing,
/// but also least resource-intensive settings.
///
/// Good default for resource-limited machines, e.g. a cheap VPS.
#[must_use]
pub fn low_power(mut self) -> Self {
self.db_config =
cuprate_database::config::ConfigBuilder::new(Cow::Borrowed(&*CUPRATE_TXPOOL_DIR))
.low_power();
self.reader_threads = Some(ReaderThreads::One);
self
}
}
impl Default for ConfigBuilder {
fn default() -> Self {
let db_directory = Cow::Borrowed(CUPRATE_TXPOOL_DIR.as_path());
Self {
db_directory: Some(db_directory.clone()),
db_config: cuprate_database::config::ConfigBuilder::new(db_directory),
reader_threads: Some(ReaderThreads::default()),
max_txpool_weight: Some(DEFAULT_TXPOOL_WEIGHT_LIMIT),
}
}
}
//---------------------------------------------------------------------------------------------------- Config
/// `cuprate_txpool` configuration.
///
/// This is a configuration built on-top of [`DbConfig`].
///
/// It contains configuration specific to this crate, plus the database config.
///
/// For construction, either use [`ConfigBuilder`] or [`Config::default`].
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Config {
/// The database configuration.
pub db_config: DbConfig,
/// Database reader thread count.
pub reader_threads: ReaderThreads,
/// The maximum weight of the transaction pool, after which we will start dropping transactions.
// TODO: enforce this max size.
pub max_txpool_weight: usize,
}
impl Config {
/// Create a new [`Config`] with sane default settings.
///
/// The [`DbConfig::db_directory`]
/// will be set to [`CUPRATE_TXPOOL_DIR`].
///
/// All other values will be [`Default::default`].
///
/// Same as [`Config::default`].
///
/// ```rust
/// use cuprate_database::{
/// config::SyncMode,
/// resize::ResizeAlgorithm,
/// DATABASE_DATA_FILENAME,
/// };
/// use cuprate_database_service::ReaderThreads;
/// use cuprate_helper::fs::*;
///
/// use cuprate_txpool::Config;
///
/// let config = Config::new();
///
/// assert_eq!(config.db_config.db_directory(), &*CUPRATE_TXPOOL_DIR);
/// assert!(config.db_config.db_file().starts_with(&*CUPRATE_TXPOOL_DIR));
/// assert!(config.db_config.db_file().ends_with(DATABASE_DATA_FILENAME));
/// assert_eq!(config.db_config.sync_mode, SyncMode::default());
/// assert_eq!(config.db_config.resize_algorithm, ResizeAlgorithm::default());
/// assert_eq!(config.reader_threads, ReaderThreads::default());
/// ```
pub fn new() -> Self {
Self {
db_config: DbConfig::new(Cow::Borrowed(&*CUPRATE_TXPOOL_DIR)),
reader_threads: ReaderThreads::default(),
max_txpool_weight: 0,
}
}
}
impl Default for Config {
/// Same as [`Config::new`].
///
/// ```rust
/// # use cuprate_txpool::Config;
/// assert_eq!(Config::default(), Config::new());
/// ```
fn default() -> Self {
Self::new()
}
}