1use crate::{
10 InitialPeersConfig,
11 error::{Error, Result},
12};
13use std::{
14 path::{Path, PathBuf},
15 time::Duration,
16};
17
18const ADDR_EXPIRY_DURATION: Duration = Duration::from_secs(24 * 60 * 60); const MAX_PEERS: usize = 1500;
23
24const MAX_ADDRS_PER_PEER: usize = 3;
26
27const MIN_BOOTSTRAP_CACHE_SAVE_INTERVAL: Duration = Duration::from_secs(30);
29
30const MAX_BOOTSTRAP_CACHE_SAVE_INTERVAL: Duration = Duration::from_secs(3 * 60 * 60);
32
33#[derive(Clone, Debug)]
35pub struct BootstrapCacheConfig {
36 pub addr_expiry_duration: Duration,
38 pub backwards_compatible_writes: bool,
41 pub cache_dir: PathBuf,
43 pub cache_save_scaling_factor: u32,
45 pub disable_cache_writing: bool,
47 pub local: bool,
49 pub max_cache_save_duration: Duration,
51 pub max_peers: usize,
53 pub max_addrs_per_peer: usize,
55 pub min_cache_save_duration: Duration,
57}
58
59impl TryFrom<&InitialPeersConfig> for BootstrapCacheConfig {
60 type Error = Error;
61 fn try_from(config: &InitialPeersConfig) -> Result<Self> {
62 let mut bootstrap_config = BootstrapCacheConfig::empty();
63 bootstrap_config.local = config.local;
64 let cache_dir = if let Some(cache_dir) = &config.bootstrap_cache_dir {
65 cache_dir.clone()
66 } else {
67 default_cache_dir()?
68 };
69 bootstrap_config.cache_dir = cache_dir;
70 Ok(bootstrap_config)
71 }
72}
73
74impl BootstrapCacheConfig {
75 pub fn new(local: bool) -> Result<Self> {
77 Ok(Self {
78 local,
79 cache_dir: default_cache_dir()?,
80 ..Self::empty()
81 })
82 }
83
84 pub fn empty() -> Self {
86 Self {
87 addr_expiry_duration: ADDR_EXPIRY_DURATION,
88 backwards_compatible_writes: false,
89 max_peers: MAX_PEERS,
90 max_addrs_per_peer: MAX_ADDRS_PER_PEER,
91 cache_dir: PathBuf::new(),
92 disable_cache_writing: false,
93 local: false,
94 min_cache_save_duration: MIN_BOOTSTRAP_CACHE_SAVE_INTERVAL,
95 max_cache_save_duration: MAX_BOOTSTRAP_CACHE_SAVE_INTERVAL,
96 cache_save_scaling_factor: 2,
97 }
98 }
99
100 pub fn with_backwards_compatible_writes(mut self, enable: bool) -> Self {
102 self.backwards_compatible_writes = enable;
103 self
104 }
105
106 pub fn with_local(mut self, enable: bool) -> Self {
108 self.local = enable;
109 self
110 }
111
112 pub fn with_addr_expiry_duration(mut self, duration: Duration) -> Self {
114 self.addr_expiry_duration = duration;
115 self
116 }
117
118 pub fn with_cache_dir<P: AsRef<Path>>(mut self, path: P) -> Self {
120 self.cache_dir = path.as_ref().to_path_buf();
121 self
122 }
123
124 pub fn with_max_peers(mut self, max_peers: usize) -> Self {
126 self.max_peers = max_peers;
127 self
128 }
129
130 pub fn with_addrs_per_peer(mut self, max_addrs: usize) -> Self {
132 self.max_addrs_per_peer = max_addrs;
133 self
134 }
135
136 pub fn with_disable_cache_writing(mut self, disable: bool) -> Self {
138 self.disable_cache_writing = disable;
139 self
140 }
141}
142
143fn default_cache_dir() -> Result<PathBuf> {
145 let dir = dirs_next::data_dir()
146 .ok_or_else(|| Error::CouldNotObtainDataDir)
147 .inspect_err(|err| {
148 error!("Failed to obtain data directory: {err}");
149 })?
150 .join("autonomi")
151 .join("bootstrap_cache");
152
153 std::fs::create_dir_all(&dir).inspect_err(|err| {
154 error!("Failed to create bootstrap cache directory at {dir:?}: {err}");
155 })?;
156
157 Ok(dir)
158}