Skip to content

Commit 7a2f2a6

Browse files
committed
refactor: [torrust#852] extract Core configuration type
1 parent 7519ecc commit 7a2f2a6

File tree

11 files changed

+131
-115
lines changed

11 files changed

+131
-115
lines changed

packages/configuration/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ pub struct TslConfig {
172172
pub ssl_key_path: Option<Utf8PathBuf>,
173173
}
174174

175-
#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
175+
#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Clone)]
176176
#[serde(rename_all = "lowercase")]
177177
pub enum LogLevel {
178178
/// A level lower than all log levels.

packages/configuration/src/v1/core.rs

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
use std::net::{IpAddr, Ipv4Addr};
2+
3+
use serde::{Deserialize, Serialize};
4+
use torrust_tracker_primitives::{DatabaseDriver, TrackerMode};
5+
6+
use crate::{AnnouncePolicy, LogLevel};
7+
8+
#[allow(clippy::struct_excessive_bools)]
9+
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
10+
pub struct Core {
11+
/// Logging level. Possible values are: `Off`, `Error`, `Warn`, `Info`,
12+
/// `Debug` and `Trace`. Default is `Info`.
13+
pub log_level: Option<LogLevel>,
14+
/// Tracker mode. See [`TrackerMode`] for more information.
15+
pub mode: TrackerMode,
16+
17+
// Database configuration
18+
/// Database driver. Possible values are: `Sqlite3`, and `MySQL`.
19+
pub db_driver: DatabaseDriver,
20+
/// Database connection string. The format depends on the database driver.
21+
/// For `Sqlite3`, the format is `path/to/database.db`, for example:
22+
/// `./storage/tracker/lib/database/sqlite3.db`.
23+
/// For `Mysql`, the format is `mysql://db_user:db_user_password:port/db_name`, for
24+
/// example: `root:password@localhost:3306/torrust`.
25+
pub db_path: String,
26+
27+
/// See [`AnnouncePolicy::interval`]
28+
pub announce_interval: u32,
29+
30+
/// See [`AnnouncePolicy::interval_min`]
31+
pub min_announce_interval: u32,
32+
/// Weather the tracker is behind a reverse proxy or not.
33+
/// If the tracker is behind a reverse proxy, the `X-Forwarded-For` header
34+
/// sent from the proxy will be used to get the client's IP address.
35+
pub on_reverse_proxy: bool,
36+
/// The external IP address of the tracker. If the client is using a
37+
/// loopback IP address, this IP address will be used instead. If the peer
38+
/// is using a loopback IP address, the tracker assumes that the peer is
39+
/// in the same network as the tracker and will use the tracker's IP
40+
/// address instead.
41+
pub external_ip: Option<IpAddr>,
42+
/// Weather the tracker should collect statistics about tracker usage.
43+
/// If enabled, the tracker will collect statistics like the number of
44+
/// connections handled, the number of announce requests handled, etc.
45+
/// Refer to the [`Tracker`](https://docs.rs/torrust-tracker) for more
46+
/// information about the collected metrics.
47+
pub tracker_usage_statistics: bool,
48+
/// If enabled the tracker will persist the number of completed downloads.
49+
/// That's how many times a torrent has been downloaded completely.
50+
pub persistent_torrent_completed_stat: bool,
51+
52+
// Cleanup job configuration
53+
/// Maximum time in seconds that a peer can be inactive before being
54+
/// considered an inactive peer. If a peer is inactive for more than this
55+
/// time, it will be removed from the torrent peer list.
56+
pub max_peer_timeout: u32,
57+
/// Interval in seconds that the cleanup job will run to remove inactive
58+
/// peers from the torrent peer list.
59+
pub inactive_peer_cleanup_interval: u64,
60+
/// If enabled, the tracker will remove torrents that have no peers.
61+
/// The clean up torrent job runs every `inactive_peer_cleanup_interval`
62+
/// seconds and it removes inactive peers. Eventually, the peer list of a
63+
/// torrent could be empty and the torrent will be removed if this option is
64+
/// enabled.
65+
pub remove_peerless_torrents: bool,
66+
}
67+
68+
impl Default for Core {
69+
fn default() -> Self {
70+
let announce_policy = AnnouncePolicy::default();
71+
72+
Self {
73+
log_level: Some(LogLevel::Info),
74+
mode: TrackerMode::Public,
75+
db_driver: DatabaseDriver::Sqlite3,
76+
db_path: String::from("./storage/tracker/lib/database/sqlite3.db"),
77+
announce_interval: announce_policy.interval,
78+
min_announce_interval: announce_policy.interval_min,
79+
max_peer_timeout: 900,
80+
on_reverse_proxy: false,
81+
external_ip: Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))),
82+
tracker_usage_statistics: true,
83+
persistent_torrent_completed_stat: false,
84+
inactive_peer_cleanup_interval: 600,
85+
remove_peerless_torrents: true,
86+
}
87+
}
88+
}

packages/configuration/src/v1/mod.rs

+14-85
Original file line numberDiff line numberDiff line change
@@ -230,86 +230,32 @@
230230
//! [health_check_api]
231231
//! bind_address = "127.0.0.1:1313"
232232
//!```
233+
pub mod core;
233234
pub mod health_check_api;
234235
pub mod http_tracker;
235236
pub mod tracker_api;
236237
pub mod udp_tracker;
237238

238239
use std::fs;
239-
use std::net::{IpAddr, Ipv4Addr};
240+
use std::net::IpAddr;
240241

241242
use figment::providers::{Env, Format, Serialized, Toml};
242243
use figment::Figment;
243244
use serde::{Deserialize, Serialize};
244-
use torrust_tracker_primitives::{DatabaseDriver, TrackerMode};
245245

246+
use self::core::Core;
246247
use self::health_check_api::HealthCheckApi;
247248
use self::http_tracker::HttpTracker;
248249
use self::tracker_api::HttpApi;
249250
use self::udp_tracker::UdpTracker;
250-
use crate::{AnnouncePolicy, Error, Info, LogLevel};
251+
use crate::{Error, Info};
251252

252253
/// Core configuration for the tracker.
253-
#[allow(clippy::struct_excessive_bools)]
254254
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
255255
pub struct Configuration {
256-
/// Logging level. Possible values are: `Off`, `Error`, `Warn`, `Info`,
257-
/// `Debug` and `Trace`. Default is `Info`.
258-
pub log_level: Option<LogLevel>,
259-
/// Tracker mode. See [`TrackerMode`] for more information.
260-
pub mode: TrackerMode,
261-
262-
// Database configuration
263-
/// Database driver. Possible values are: `Sqlite3`, and `MySQL`.
264-
pub db_driver: DatabaseDriver,
265-
/// Database connection string. The format depends on the database driver.
266-
/// For `Sqlite3`, the format is `path/to/database.db`, for example:
267-
/// `./storage/tracker/lib/database/sqlite3.db`.
268-
/// For `Mysql`, the format is `mysql://db_user:db_user_password:port/db_name`, for
269-
/// example: `root:password@localhost:3306/torrust`.
270-
pub db_path: String,
271-
272-
/// See [`AnnouncePolicy::interval`]
273-
pub announce_interval: u32,
274-
275-
/// See [`AnnouncePolicy::interval_min`]
276-
pub min_announce_interval: u32,
277-
/// Weather the tracker is behind a reverse proxy or not.
278-
/// If the tracker is behind a reverse proxy, the `X-Forwarded-For` header
279-
/// sent from the proxy will be used to get the client's IP address.
280-
pub on_reverse_proxy: bool,
281-
/// The external IP address of the tracker. If the client is using a
282-
/// loopback IP address, this IP address will be used instead. If the peer
283-
/// is using a loopback IP address, the tracker assumes that the peer is
284-
/// in the same network as the tracker and will use the tracker's IP
285-
/// address instead.
286-
pub external_ip: Option<IpAddr>,
287-
/// Weather the tracker should collect statistics about tracker usage.
288-
/// If enabled, the tracker will collect statistics like the number of
289-
/// connections handled, the number of announce requests handled, etc.
290-
/// Refer to the [`Tracker`](https://docs.rs/torrust-tracker) for more
291-
/// information about the collected metrics.
292-
pub tracker_usage_statistics: bool,
293-
/// If enabled the tracker will persist the number of completed downloads.
294-
/// That's how many times a torrent has been downloaded completely.
295-
pub persistent_torrent_completed_stat: bool,
296-
297-
// Cleanup job configuration
298-
/// Maximum time in seconds that a peer can be inactive before being
299-
/// considered an inactive peer. If a peer is inactive for more than this
300-
/// time, it will be removed from the torrent peer list.
301-
pub max_peer_timeout: u32,
302-
/// Interval in seconds that the cleanup job will run to remove inactive
303-
/// peers from the torrent peer list.
304-
pub inactive_peer_cleanup_interval: u64,
305-
/// If enabled, the tracker will remove torrents that have no peers.
306-
/// The clean up torrent job runs every `inactive_peer_cleanup_interval`
307-
/// seconds and it removes inactive peers. Eventually, the peer list of a
308-
/// torrent could be empty and the torrent will be removed if this option is
309-
/// enabled.
310-
pub remove_peerless_torrents: bool,
311-
312-
// Server jobs configuration
256+
/// Core configuration.
257+
#[serde(flatten)]
258+
pub core: Core,
313259
/// The list of UDP trackers the tracker is running. Each UDP tracker
314260
/// represents a UDP server that the tracker is running and it has its own
315261
/// configuration.
@@ -326,30 +272,13 @@ pub struct Configuration {
326272

327273
impl Default for Configuration {
328274
fn default() -> Self {
329-
let announce_policy = AnnouncePolicy::default();
330-
331-
let mut configuration = Configuration {
332-
log_level: Some(LogLevel::Info),
333-
mode: TrackerMode::Public,
334-
db_driver: DatabaseDriver::Sqlite3,
335-
db_path: String::from("./storage/tracker/lib/database/sqlite3.db"),
336-
announce_interval: announce_policy.interval,
337-
min_announce_interval: announce_policy.interval_min,
338-
max_peer_timeout: 900,
339-
on_reverse_proxy: false,
340-
external_ip: Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))),
341-
tracker_usage_statistics: true,
342-
persistent_torrent_completed_stat: false,
343-
inactive_peer_cleanup_interval: 600,
344-
remove_peerless_torrents: true,
345-
udp_trackers: Vec::new(),
346-
http_trackers: Vec::new(),
275+
Self {
276+
core: Core::default(),
277+
udp_trackers: vec![UdpTracker::default()],
278+
http_trackers: vec![HttpTracker::default()],
347279
http_api: HttpApi::default(),
348280
health_check_api: HealthCheckApi::default(),
349-
};
350-
configuration.udp_trackers.push(UdpTracker::default());
351-
configuration.http_trackers.push(HttpTracker::default());
352-
configuration
281+
}
353282
}
354283
}
355284

@@ -362,7 +291,7 @@ impl Configuration {
362291
/// and `None` otherwise.
363292
#[must_use]
364293
pub fn get_ext_ip(&self) -> Option<IpAddr> {
365-
self.external_ip.as_ref().map(|external_ip| *external_ip)
294+
self.core.external_ip.as_ref().map(|external_ip| *external_ip)
366295
}
367296

368297
/// Saves the default configuration at the given path.
@@ -490,7 +419,7 @@ mod tests {
490419
fn configuration_should_contain_the_external_ip() {
491420
let configuration = Configuration::default();
492421

493-
assert_eq!(configuration.external_ip, Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))));
422+
assert_eq!(configuration.core.external_ip, Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))));
494423
}
495424

496425
#[test]

packages/test-helpers/src/configuration.rs

+11-12
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@ pub fn ephemeral() -> Configuration {
2727
// todo: disable services that are not needed.
2828
// For example: a test for the UDP tracker should disable the API and HTTP tracker.
2929

30-
let mut config = Configuration {
31-
log_level: Some(LogLevel::Off), // Change to `debug` for tests debugging
32-
..Default::default()
33-
};
30+
let mut config = Configuration::default();
31+
32+
config.core.log_level = Some(LogLevel::Off); // Change to `debug` for tests debugging
3433

3534
// Ephemeral socket address for API
3635
let api_port = 0u16;
@@ -55,7 +54,7 @@ pub fn ephemeral() -> Configuration {
5554
let temp_directory = env::temp_dir();
5655
let random_db_id = random::string(16);
5756
let temp_file = temp_directory.join(format!("data_{random_db_id}.db"));
58-
temp_file.to_str().unwrap().clone_into(&mut config.db_path);
57+
temp_file.to_str().unwrap().clone_into(&mut config.core.db_path);
5958

6059
config
6160
}
@@ -65,7 +64,7 @@ pub fn ephemeral() -> Configuration {
6564
pub fn ephemeral_with_reverse_proxy() -> Configuration {
6665
let mut cfg = ephemeral();
6766

68-
cfg.on_reverse_proxy = true;
67+
cfg.core.on_reverse_proxy = true;
6968

7069
cfg
7170
}
@@ -75,7 +74,7 @@ pub fn ephemeral_with_reverse_proxy() -> Configuration {
7574
pub fn ephemeral_without_reverse_proxy() -> Configuration {
7675
let mut cfg = ephemeral();
7776

78-
cfg.on_reverse_proxy = false;
77+
cfg.core.on_reverse_proxy = false;
7978

8079
cfg
8180
}
@@ -85,7 +84,7 @@ pub fn ephemeral_without_reverse_proxy() -> Configuration {
8584
pub fn ephemeral_mode_public() -> Configuration {
8685
let mut cfg = ephemeral();
8786

88-
cfg.mode = TrackerMode::Public;
87+
cfg.core.mode = TrackerMode::Public;
8988

9089
cfg
9190
}
@@ -95,7 +94,7 @@ pub fn ephemeral_mode_public() -> Configuration {
9594
pub fn ephemeral_mode_private() -> Configuration {
9695
let mut cfg = ephemeral();
9796

98-
cfg.mode = TrackerMode::Private;
97+
cfg.core.mode = TrackerMode::Private;
9998

10099
cfg
101100
}
@@ -105,7 +104,7 @@ pub fn ephemeral_mode_private() -> Configuration {
105104
pub fn ephemeral_mode_whitelisted() -> Configuration {
106105
let mut cfg = ephemeral();
107106

108-
cfg.mode = TrackerMode::Listed;
107+
cfg.core.mode = TrackerMode::Listed;
109108

110109
cfg
111110
}
@@ -115,7 +114,7 @@ pub fn ephemeral_mode_whitelisted() -> Configuration {
115114
pub fn ephemeral_mode_private_whitelisted() -> Configuration {
116115
let mut cfg = ephemeral();
117116

118-
cfg.mode = TrackerMode::PrivateListed;
117+
cfg.core.mode = TrackerMode::PrivateListed;
119118

120119
cfg
121120
}
@@ -125,7 +124,7 @@ pub fn ephemeral_mode_private_whitelisted() -> Configuration {
125124
pub fn ephemeral_with_external_ip(ip: IpAddr) -> Configuration {
126125
let mut cfg = ephemeral();
127126

128-
cfg.external_ip = Some(ip);
127+
cfg.core.external_ip = Some(ip);
129128

130129
cfg
131130
}

src/app.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub async fn start(config: &Configuration, tracker: Arc<core::Tracker>) -> Vec<J
6767
if tracker.is_private() {
6868
warn!(
6969
"Could not start UDP tracker on: {} while in {:?}. UDP is not safe for private trackers!",
70-
udp_tracker_config.bind_address, config.mode
70+
udp_tracker_config.bind_address, config.core.mode
7171
);
7272
} else {
7373
jobs.push(udp_tracker::start_job(udp_tracker_config, tracker.clone(), registar.give_form()).await);
@@ -107,8 +107,8 @@ pub async fn start(config: &Configuration, tracker: Arc<core::Tracker>) -> Vec<J
107107
}
108108

109109
// Start runners to remove torrents without peers, every interval
110-
if config.inactive_peer_cleanup_interval > 0 {
111-
jobs.push(torrent_cleanup::start_job(config, &tracker));
110+
if config.core.inactive_peer_cleanup_interval > 0 {
111+
jobs.push(torrent_cleanup::start_job(&config.core, &tracker));
112112
}
113113

114114
// Start Health Check API

src/bootstrap/jobs/torrent_cleanup.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::sync::Arc;
1515
use chrono::Utc;
1616
use log::info;
1717
use tokio::task::JoinHandle;
18-
use torrust_tracker_configuration::Configuration;
18+
use torrust_tracker_configuration::v1::core::Core;
1919

2020
use crate::core;
2121

@@ -25,7 +25,7 @@ use crate::core;
2525
///
2626
/// Refer to [`torrust-tracker-configuration documentation`](https://docs.rs/torrust-tracker-configuration) for more info about that option.
2727
#[must_use]
28-
pub fn start_job(config: &Configuration, tracker: &Arc<core::Tracker>) -> JoinHandle<()> {
28+
pub fn start_job(config: &Core, tracker: &Arc<core::Tracker>) -> JoinHandle<()> {
2929
let weak_tracker = std::sync::Arc::downgrade(tracker);
3030
let interval = config.inactive_peer_cleanup_interval;
3131

src/bootstrap/logging.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ static INIT: Once = Once::new();
1919

2020
/// It redirects the log info to the standard output with the log level defined in the configuration
2121
pub fn setup(cfg: &Configuration) {
22-
let level = config_level_or_default(&cfg.log_level);
22+
let level = config_level_or_default(&cfg.core.log_level);
2323

2424
if level == log::LevelFilter::Off {
2525
return;

0 commit comments

Comments
 (0)