From 03ef7f6178ae9c25f4fca925741c9d48bf809886 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Thu, 23 Jan 2025 16:23:28 +0000 Subject: [PATCH 01/11] refactor: [1201] extract InMemoryTorrentRepository --- src/core/mod.rs | 33 +++----- src/core/services/torrent.rs | 1 - src/core/torrent/mod.rs | 2 + src/core/torrent/repository/in_memory.rs | 103 +++++++++++++++++++++++ src/core/torrent/repository/mod.rs | 1 + 5 files changed, 116 insertions(+), 24 deletions(-) create mode 100644 src/core/torrent/repository/in_memory.rs create mode 100644 src/core/torrent/repository/mod.rs diff --git a/src/core/mod.rs b/src/core/mod.rs index 26ef69bfa..fd25a0506 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -449,22 +449,19 @@ pub mod whitelist; pub mod peer_tests; -use std::cmp::max; use std::net::IpAddr; use std::sync::Arc; use std::time::Duration; use bittorrent_primitives::info_hash::InfoHash; +use torrent::repository::in_memory::InMemoryTorrentRepository; use torrust_tracker_clock::clock::Time; use torrust_tracker_configuration::{AnnouncePolicy, Core, TORRENT_PEERS_LIMIT}; use torrust_tracker_primitives::core::{AnnounceData, ScrapeData}; use torrust_tracker_primitives::peer; use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; -use torrust_tracker_torrent_repository::entry::EntrySync; -use torrust_tracker_torrent_repository::repository::Repository; -use self::torrent::Torrents; use crate::core::databases::Database; use crate::CurrentClock; @@ -489,7 +486,7 @@ pub struct Tracker { pub whitelist_authorization: Arc<whitelist::authorization::Authorization>, /// The in-memory torrents repository. - torrents: Arc<Torrents>, + torrents: Arc<InMemoryTorrentRepository>, } /// How many peers the peer announcing wants in the announce response. @@ -549,7 +546,7 @@ impl Tracker { config: config.clone(), database: database.clone(), whitelist_authorization: whitelist_authorization.clone(), - torrents: Arc::default(), + torrents: Arc::new(InMemoryTorrentRepository::default()), }) } @@ -656,10 +653,7 @@ impl Tracker { /// It returns the data for a `scrape` response. fn get_swarm_metadata(&self, info_hash: &InfoHash) -> SwarmMetadata { - match self.torrents.get(info_hash) { - Some(torrent_entry) => torrent_entry.get_swarm_metadata(), - None => SwarmMetadata::default(), - } + self.torrents.get_swarm_metadata(info_hash) } /// It loads the torrents from database into memory. It only loads the torrent entry list with the number of seeders for each torrent. @@ -684,10 +678,7 @@ impl Tracker { /// /// It filters out the client making the request. fn get_peers_for(&self, info_hash: &InfoHash, peer: &peer::Peer, limit: usize) -> Vec<Arc<peer::Peer>> { - match self.torrents.get(info_hash) { - None => vec![], - Some(entry) => entry.get_peers_for_client(&peer.peer_addr, Some(max(limit, TORRENT_PEERS_LIMIT))), - } + self.torrents.get_peers_for(info_hash, peer, limit) } /// # Context: Tracker @@ -695,10 +686,7 @@ impl Tracker { /// Get torrent peers for a given torrent. #[must_use] pub fn get_torrent_peers(&self, info_hash: &InfoHash) -> Vec<Arc<peer::Peer>> { - match self.torrents.get(info_hash) { - None => vec![], - Some(entry) => entry.get_peers(Some(TORRENT_PEERS_LIMIT)), - } + self.torrents.get_torrent_peers(info_hash) } /// It updates the torrent entry in memory, it also stores in the database @@ -708,14 +696,14 @@ impl Tracker { /// # Context: Tracker #[must_use] pub fn upsert_peer_and_get_stats(&self, info_hash: &InfoHash, peer: &peer::Peer) -> SwarmMetadata { - let swarm_metadata_before = match self.torrents.get_swarm_metadata(info_hash) { + let swarm_metadata_before = match self.torrents.get_opt_swarm_metadata(info_hash) { Some(swarm_metadata) => swarm_metadata, None => SwarmMetadata::zeroed(), }; self.torrents.upsert_peer(info_hash, peer); - let swarm_metadata_after = match self.torrents.get_swarm_metadata(info_hash) { + let swarm_metadata_after = match self.torrents.get_opt_swarm_metadata(info_hash) { Some(swarm_metadata) => swarm_metadata, None => SwarmMetadata::zeroed(), }; @@ -748,7 +736,7 @@ impl Tracker { /// Panics if unable to get the torrent metrics. #[must_use] pub fn get_torrents_metrics(&self) -> TorrentsMetrics { - self.torrents.get_metrics() + self.torrents.get_torrents_metrics() } /// Remove inactive peers and (optionally) peerless torrents. @@ -1492,7 +1480,6 @@ mod tests { use aquatic_udp_protocol::AnnounceEvent; use torrust_tracker_torrent_repository::entry::EntrySync; - use torrust_tracker_torrent_repository::repository::Repository; use crate::core::tests::the_tracker::{sample_info_hash, sample_peer, tracker_persisting_torrents_in_database}; @@ -1513,7 +1500,7 @@ mod tests { assert_eq!(swarm_stats.downloaded, 1); // Remove the newly updated torrent from memory - tracker.torrents.remove(&info_hash); + let _unused = tracker.torrents.remove(&info_hash); tracker.load_torrents_from_database().unwrap(); diff --git a/src/core/services/torrent.rs b/src/core/services/torrent.rs index 9b7254098..7f99451eb 100644 --- a/src/core/services/torrent.rs +++ b/src/core/services/torrent.rs @@ -10,7 +10,6 @@ use bittorrent_primitives::info_hash::InfoHash; use torrust_tracker_primitives::pagination::Pagination; use torrust_tracker_primitives::peer; use torrust_tracker_torrent_repository::entry::EntrySync; -use torrust_tracker_torrent_repository::repository::Repository; use crate::core::Tracker; diff --git a/src/core/torrent/mod.rs b/src/core/torrent/mod.rs index 38311864b..3e3e065f2 100644 --- a/src/core/torrent/mod.rs +++ b/src/core/torrent/mod.rs @@ -25,6 +25,8 @@ //! - The number of peers that have NOT completed downloading the torrent and are still active, that means they are actively participating in the network. //! Peer that don not have a full copy of the torrent data are called "leechers". //! +pub mod repository; + use torrust_tracker_torrent_repository::TorrentsSkipMapMutexStd; pub type Torrents = TorrentsSkipMapMutexStd; // Currently Used diff --git a/src/core/torrent/repository/in_memory.rs b/src/core/torrent/repository/in_memory.rs new file mode 100644 index 000000000..6b1902d95 --- /dev/null +++ b/src/core/torrent/repository/in_memory.rs @@ -0,0 +1,103 @@ +use std::cmp::max; +use std::sync::Arc; + +use bittorrent_primitives::info_hash::InfoHash; +use torrust_tracker_configuration::{TrackerPolicy, TORRENT_PEERS_LIMIT}; +use torrust_tracker_primitives::pagination::Pagination; +use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; +use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; +use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch, PersistentTorrents}; +use torrust_tracker_torrent_repository::entry::EntrySync; +use torrust_tracker_torrent_repository::repository::Repository; +use torrust_tracker_torrent_repository::EntryMutexStd; + +use crate::core::torrent::Torrents; + +/// The in-memory torrents repository. +/// +/// There are many implementations of the repository trait. We tried with +/// different types of data structures, but the best performance was with +/// the one we use for production. We kept the other implementations for +/// reference. +#[derive(Debug, Default)] +pub struct InMemoryTorrentRepository { + /// The in-memory torrents repository implementation. + torrents: Arc<Torrents>, +} + +impl InMemoryTorrentRepository { + /// It inserts (or updates if it's already in the list) the peer in the + /// torrent entry. + pub fn upsert_peer(&self, info_hash: &InfoHash, peer: &peer::Peer) { + self.torrents.upsert_peer(info_hash, peer); + } + + #[must_use] + pub fn remove(&self, key: &InfoHash) -> Option<EntryMutexStd> { + self.torrents.remove(key) + } + + pub fn remove_inactive_peers(&self, current_cutoff: DurationSinceUnixEpoch) { + self.torrents.remove_inactive_peers(current_cutoff); + } + + pub fn remove_peerless_torrents(&self, policy: &TrackerPolicy) { + self.torrents.remove_peerless_torrents(policy); + } + + #[must_use] + pub fn get(&self, key: &InfoHash) -> Option<EntryMutexStd> { + self.torrents.get(key) + } + + #[must_use] + pub fn get_paginated(&self, pagination: Option<&Pagination>) -> Vec<(InfoHash, EntryMutexStd)> { + self.torrents.get_paginated(pagination) + } + + /// It returns the data for a `scrape` response or empty if the torrent is + /// not found. + #[must_use] + pub fn get_swarm_metadata(&self, info_hash: &InfoHash) -> SwarmMetadata { + match self.torrents.get(info_hash) { + Some(torrent_entry) => torrent_entry.get_swarm_metadata(), + None => SwarmMetadata::default(), + } + } + + /// It returns the data for a `scrape` response if the torrent is found. + #[must_use] + pub fn get_opt_swarm_metadata(&self, info_hash: &InfoHash) -> Option<SwarmMetadata> { + self.torrents.get_swarm_metadata(info_hash) + } + + /// Get torrent peers for a given torrent and client. + /// + /// It filters out the client making the request. + #[must_use] + pub fn get_peers_for(&self, info_hash: &InfoHash, peer: &peer::Peer, limit: usize) -> Vec<Arc<peer::Peer>> { + match self.torrents.get(info_hash) { + None => vec![], + Some(entry) => entry.get_peers_for_client(&peer.peer_addr, Some(max(limit, TORRENT_PEERS_LIMIT))), + } + } + + /// Get torrent peers for a given torrent. + #[must_use] + pub fn get_torrent_peers(&self, info_hash: &InfoHash) -> Vec<Arc<peer::Peer>> { + match self.torrents.get(info_hash) { + None => vec![], + Some(entry) => entry.get_peers(Some(TORRENT_PEERS_LIMIT)), + } + } + + /// It calculates and returns the general [`TorrentsMetrics`]. + #[must_use] + pub fn get_torrents_metrics(&self) -> TorrentsMetrics { + self.torrents.get_metrics() + } + + pub fn import_persistent(&self, persistent_torrents: &PersistentTorrents) { + self.torrents.import_persistent(persistent_torrents); + } +} diff --git a/src/core/torrent/repository/mod.rs b/src/core/torrent/repository/mod.rs new file mode 100644 index 000000000..fa2e12699 --- /dev/null +++ b/src/core/torrent/repository/mod.rs @@ -0,0 +1 @@ +pub mod in_memory; From 9b5f776c28483e17d5dfa39f4026faacf7aa6546 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Thu, 23 Jan 2025 16:50:56 +0000 Subject: [PATCH 02/11] refactor: [#1201] exatrct DatabasePersistentTorrentRepository --- src/core/mod.rs | 11 ++++-- src/core/torrent/repository/mod.rs | 1 + src/core/torrent/repository/persisted.rs | 44 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/core/torrent/repository/persisted.rs diff --git a/src/core/mod.rs b/src/core/mod.rs index fd25a0506..4cb4a04ef 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -455,6 +455,7 @@ use std::time::Duration; use bittorrent_primitives::info_hash::InfoHash; use torrent::repository::in_memory::InMemoryTorrentRepository; +use torrent::repository::persisted::DatabasePersistentTorrentRepository; use torrust_tracker_clock::clock::Time; use torrust_tracker_configuration::{AnnouncePolicy, Core, TORRENT_PEERS_LIMIT}; use torrust_tracker_primitives::core::{AnnounceData, ScrapeData}; @@ -487,6 +488,9 @@ pub struct Tracker { /// The in-memory torrents repository. torrents: Arc<InMemoryTorrentRepository>, + + /// The persistent torrents repository. + db_torrent_repository: Arc<DatabasePersistentTorrentRepository>, } /// How many peers the peer announcing wants in the announce response. @@ -547,6 +551,7 @@ impl Tracker { database: database.clone(), whitelist_authorization: whitelist_authorization.clone(), torrents: Arc::new(InMemoryTorrentRepository::default()), + db_torrent_repository: Arc::new(DatabasePersistentTorrentRepository::new(database)), }) } @@ -665,7 +670,7 @@ impl Tracker { /// /// Will return a `database::Error` if unable to load the list of `persistent_torrents` from the database. pub fn load_torrents_from_database(&self) -> Result<(), databases::error::Error> { - let persistent_torrents = self.database.load_persistent_torrents()?; + let persistent_torrents = self.db_torrent_repository.load_all()?; self.torrents.import_persistent(&persistent_torrents); @@ -723,7 +728,7 @@ impl Tracker { let completed = swarm_metadata.downloaded; let info_hash = *info_hash; - drop(self.database.save_persistent_torrent(&info_hash, completed)); + drop(self.db_torrent_repository.save(&info_hash, completed)); } } @@ -759,7 +764,7 @@ impl Tracker { /// /// Will return `Err` if unable to drop tables. pub fn drop_database_tables(&self) -> Result<(), databases::error::Error> { - // todo: this is only used for testing. WE have to pass the database + // todo: this is only used for testing. We have to pass the database // reference directly to the tests instead of via the tracker. self.database.drop_database_tables() } diff --git a/src/core/torrent/repository/mod.rs b/src/core/torrent/repository/mod.rs index fa2e12699..51723b68d 100644 --- a/src/core/torrent/repository/mod.rs +++ b/src/core/torrent/repository/mod.rs @@ -1 +1,2 @@ pub mod in_memory; +pub mod persisted; diff --git a/src/core/torrent/repository/persisted.rs b/src/core/torrent/repository/persisted.rs new file mode 100644 index 000000000..86a3db0e3 --- /dev/null +++ b/src/core/torrent/repository/persisted.rs @@ -0,0 +1,44 @@ +use std::sync::Arc; + +use bittorrent_primitives::info_hash::InfoHash; +use torrust_tracker_primitives::PersistentTorrents; + +use crate::core::databases::error::Error; +use crate::core::databases::Database; + +/// Torrent repository implementation that persists the torrents in a database. +/// +/// Not all the torrent in-memory data is persisted. For now only some of the +/// torrent metrics are persisted. +pub struct DatabasePersistentTorrentRepository { + /// A database driver implementation: [`Sqlite3`](crate::core::databases::sqlite) + /// or [`MySQL`](crate::core::databases::mysql) + database: Arc<Box<dyn Database>>, +} + +impl DatabasePersistentTorrentRepository { + #[must_use] + pub fn new(database: &Arc<Box<dyn Database>>) -> DatabasePersistentTorrentRepository { + Self { + database: database.clone(), + } + } + + /// It loads the persistent torrents from the database. + /// + /// # Errors + /// + /// Will return a database `Err` if unable to load. + pub fn load_all(&self) -> Result<PersistentTorrents, Error> { + self.database.load_persistent_torrents() + } + + /// It saves the persistent torrent into the database. + /// + /// # Errors + /// + /// Will return a database `Err` if unable to save. + pub fn save(&self, info_hash: &InfoHash, downloaded: u32) -> Result<(), Error> { + self.database.save_persistent_torrent(info_hash, downloaded) + } +} From f4dcb51f1f5eaa6e2a34c441d2b4d816807f56bd Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Thu, 23 Jan 2025 16:52:55 +0000 Subject: [PATCH 03/11] refactor: [#1201] rename tracker field --- src/core/mod.rs | 32 ++++++++++++++++++-------------- src/core/services/torrent.rs | 10 +++++++--- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/core/mod.rs b/src/core/mod.rs index 4cb4a04ef..c9a7e9dc3 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -487,7 +487,7 @@ pub struct Tracker { pub whitelist_authorization: Arc<whitelist::authorization::Authorization>, /// The in-memory torrents repository. - torrents: Arc<InMemoryTorrentRepository>, + in_memory_torrent_repository: Arc<InMemoryTorrentRepository>, /// The persistent torrents repository. db_torrent_repository: Arc<DatabasePersistentTorrentRepository>, @@ -550,7 +550,7 @@ impl Tracker { config: config.clone(), database: database.clone(), whitelist_authorization: whitelist_authorization.clone(), - torrents: Arc::new(InMemoryTorrentRepository::default()), + in_memory_torrent_repository: Arc::new(InMemoryTorrentRepository::default()), db_torrent_repository: Arc::new(DatabasePersistentTorrentRepository::new(database)), }) } @@ -658,7 +658,7 @@ impl Tracker { /// It returns the data for a `scrape` response. fn get_swarm_metadata(&self, info_hash: &InfoHash) -> SwarmMetadata { - self.torrents.get_swarm_metadata(info_hash) + self.in_memory_torrent_repository.get_swarm_metadata(info_hash) } /// It loads the torrents from database into memory. It only loads the torrent entry list with the number of seeders for each torrent. @@ -672,7 +672,7 @@ impl Tracker { pub fn load_torrents_from_database(&self) -> Result<(), databases::error::Error> { let persistent_torrents = self.db_torrent_repository.load_all()?; - self.torrents.import_persistent(&persistent_torrents); + self.in_memory_torrent_repository.import_persistent(&persistent_torrents); Ok(()) } @@ -683,7 +683,7 @@ impl Tracker { /// /// It filters out the client making the request. fn get_peers_for(&self, info_hash: &InfoHash, peer: &peer::Peer, limit: usize) -> Vec<Arc<peer::Peer>> { - self.torrents.get_peers_for(info_hash, peer, limit) + self.in_memory_torrent_repository.get_peers_for(info_hash, peer, limit) } /// # Context: Tracker @@ -691,7 +691,7 @@ impl Tracker { /// Get torrent peers for a given torrent. #[must_use] pub fn get_torrent_peers(&self, info_hash: &InfoHash) -> Vec<Arc<peer::Peer>> { - self.torrents.get_torrent_peers(info_hash) + self.in_memory_torrent_repository.get_torrent_peers(info_hash) } /// It updates the torrent entry in memory, it also stores in the database @@ -701,14 +701,14 @@ impl Tracker { /// # Context: Tracker #[must_use] pub fn upsert_peer_and_get_stats(&self, info_hash: &InfoHash, peer: &peer::Peer) -> SwarmMetadata { - let swarm_metadata_before = match self.torrents.get_opt_swarm_metadata(info_hash) { + let swarm_metadata_before = match self.in_memory_torrent_repository.get_opt_swarm_metadata(info_hash) { Some(swarm_metadata) => swarm_metadata, None => SwarmMetadata::zeroed(), }; - self.torrents.upsert_peer(info_hash, peer); + self.in_memory_torrent_repository.upsert_peer(info_hash, peer); - let swarm_metadata_after = match self.torrents.get_opt_swarm_metadata(info_hash) { + let swarm_metadata_after = match self.in_memory_torrent_repository.get_opt_swarm_metadata(info_hash) { Some(swarm_metadata) => swarm_metadata, None => SwarmMetadata::zeroed(), }; @@ -741,7 +741,7 @@ impl Tracker { /// Panics if unable to get the torrent metrics. #[must_use] pub fn get_torrents_metrics(&self) -> TorrentsMetrics { - self.torrents.get_torrents_metrics() + self.in_memory_torrent_repository.get_torrents_metrics() } /// Remove inactive peers and (optionally) peerless torrents. @@ -751,10 +751,11 @@ impl Tracker { let current_cutoff = CurrentClock::now_sub(&Duration::from_secs(u64::from(self.config.tracker_policy.max_peer_timeout))) .unwrap_or_default(); - self.torrents.remove_inactive_peers(current_cutoff); + self.in_memory_torrent_repository.remove_inactive_peers(current_cutoff); if self.config.tracker_policy.remove_peerless_torrents { - self.torrents.remove_peerless_torrents(&self.config.tracker_policy); + self.in_memory_torrent_repository + .remove_peerless_torrents(&self.config.tracker_policy); } } @@ -1505,11 +1506,14 @@ mod tests { assert_eq!(swarm_stats.downloaded, 1); // Remove the newly updated torrent from memory - let _unused = tracker.torrents.remove(&info_hash); + let _unused = tracker.in_memory_torrent_repository.remove(&info_hash); tracker.load_torrents_from_database().unwrap(); - let torrent_entry = tracker.torrents.get(&info_hash).expect("it should be able to get entry"); + let torrent_entry = tracker + .in_memory_torrent_repository + .get(&info_hash) + .expect("it should be able to get entry"); // It persists the number of completed peers. assert_eq!(torrent_entry.get_swarm_metadata().downloaded, 1); diff --git a/src/core/services/torrent.rs b/src/core/services/torrent.rs index 7f99451eb..032b526dd 100644 --- a/src/core/services/torrent.rs +++ b/src/core/services/torrent.rs @@ -45,7 +45,7 @@ pub struct BasicInfo { /// It returns all the information the tracker has about one torrent in a [Info] struct. pub async fn get_torrent_info(tracker: Arc<Tracker>, info_hash: &InfoHash) -> Option<Info> { - let torrent_entry_option = tracker.torrents.get(info_hash); + let torrent_entry_option = tracker.in_memory_torrent_repository.get(info_hash); let torrent_entry = torrent_entry_option?; @@ -68,7 +68,7 @@ pub async fn get_torrent_info(tracker: Arc<Tracker>, info_hash: &InfoHash) -> Op pub async fn get_torrents_page(tracker: Arc<Tracker>, pagination: Option<&Pagination>) -> Vec<BasicInfo> { let mut basic_infos: Vec<BasicInfo> = vec![]; - for (info_hash, torrent_entry) in tracker.torrents.get_paginated(pagination) { + for (info_hash, torrent_entry) in tracker.in_memory_torrent_repository.get_paginated(pagination) { let stats = torrent_entry.get_swarm_metadata(); basic_infos.push(BasicInfo { @@ -87,7 +87,11 @@ pub async fn get_torrents(tracker: Arc<Tracker>, info_hashes: &[InfoHash]) -> Ve let mut basic_infos: Vec<BasicInfo> = vec![]; for info_hash in info_hashes { - if let Some(stats) = tracker.torrents.get(info_hash).map(|t| t.get_swarm_metadata()) { + if let Some(stats) = tracker + .in_memory_torrent_repository + .get(info_hash) + .map(|t| t.get_swarm_metadata()) + { basic_infos.push(BasicInfo { info_hash: *info_hash, seeders: u64::from(stats.complete), From 6332261af8a6a5e5d6de235283187d3440325133 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Thu, 23 Jan 2025 17:12:26 +0000 Subject: [PATCH 04/11] refactor: [#1201] extract TorrentsManager --- src/core/mod.rs | 35 ++++++++++---------- src/core/torrent/manager.rs | 64 +++++++++++++++++++++++++++++++++++++ src/core/torrent/mod.rs | 1 + 3 files changed, 81 insertions(+), 19 deletions(-) create mode 100644 src/core/torrent/manager.rs diff --git a/src/core/mod.rs b/src/core/mod.rs index c9a7e9dc3..61f194f3d 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -451,12 +451,11 @@ pub mod peer_tests; use std::net::IpAddr; use std::sync::Arc; -use std::time::Duration; use bittorrent_primitives::info_hash::InfoHash; +use torrent::manager::TorrentsManager; use torrent::repository::in_memory::InMemoryTorrentRepository; use torrent::repository::persisted::DatabasePersistentTorrentRepository; -use torrust_tracker_clock::clock::Time; use torrust_tracker_configuration::{AnnouncePolicy, Core, TORRENT_PEERS_LIMIT}; use torrust_tracker_primitives::core::{AnnounceData, ScrapeData}; use torrust_tracker_primitives::peer; @@ -464,7 +463,6 @@ use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; use crate::core::databases::Database; -use crate::CurrentClock; /// The domain layer tracker service. /// @@ -491,6 +489,9 @@ pub struct Tracker { /// The persistent torrents repository. db_torrent_repository: Arc<DatabasePersistentTorrentRepository>, + + /// The service to run torrents tasks. + torrents_manager: Arc<TorrentsManager>, } /// How many peers the peer announcing wants in the announce response. @@ -546,12 +547,20 @@ impl Tracker { database: &Arc<Box<dyn Database>>, whitelist_authorization: &Arc<whitelist::authorization::Authorization>, ) -> Result<Tracker, databases::error::Error> { + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(database)); + Ok(Tracker { config: config.clone(), database: database.clone(), whitelist_authorization: whitelist_authorization.clone(), - in_memory_torrent_repository: Arc::new(InMemoryTorrentRepository::default()), - db_torrent_repository: Arc::new(DatabasePersistentTorrentRepository::new(database)), + in_memory_torrent_repository: in_memory_torrent_repository.clone(), + db_torrent_repository: db_torrent_repository.clone(), + torrents_manager: Arc::new(TorrentsManager::new( + config, + &in_memory_torrent_repository, + &db_torrent_repository, + )), }) } @@ -670,11 +679,7 @@ impl Tracker { /// /// Will return a `database::Error` if unable to load the list of `persistent_torrents` from the database. pub fn load_torrents_from_database(&self) -> Result<(), databases::error::Error> { - let persistent_torrents = self.db_torrent_repository.load_all()?; - - self.in_memory_torrent_repository.import_persistent(&persistent_torrents); - - Ok(()) + self.torrents_manager.load_torrents_from_database() } /// # Context: Tracker @@ -748,15 +753,7 @@ impl Tracker { /// /// # Context: Tracker pub fn cleanup_torrents(&self) { - let current_cutoff = CurrentClock::now_sub(&Duration::from_secs(u64::from(self.config.tracker_policy.max_peer_timeout))) - .unwrap_or_default(); - - self.in_memory_torrent_repository.remove_inactive_peers(current_cutoff); - - if self.config.tracker_policy.remove_peerless_torrents { - self.in_memory_torrent_repository - .remove_peerless_torrents(&self.config.tracker_policy); - } + self.torrents_manager.cleanup_torrents(); } /// It drops the database tables. diff --git a/src/core/torrent/manager.rs b/src/core/torrent/manager.rs new file mode 100644 index 000000000..261376755 --- /dev/null +++ b/src/core/torrent/manager.rs @@ -0,0 +1,64 @@ +use std::sync::Arc; +use std::time::Duration; + +use torrust_tracker_clock::clock::Time; +use torrust_tracker_configuration::Core; + +use super::repository::in_memory::InMemoryTorrentRepository; +use super::repository::persisted::DatabasePersistentTorrentRepository; +use crate::core::databases; +use crate::CurrentClock; + +pub struct TorrentsManager { + /// The tracker configuration. + config: Core, + + /// The in-memory torrents repository. + in_memory_torrent_repository: Arc<InMemoryTorrentRepository>, + + /// The persistent torrents repository. + db_torrent_repository: Arc<DatabasePersistentTorrentRepository>, +} + +impl TorrentsManager { + #[must_use] + pub fn new( + config: &Core, + in_memory_torrent_repository: &Arc<InMemoryTorrentRepository>, + db_torrent_repository: &Arc<DatabasePersistentTorrentRepository>, + ) -> Self { + Self { + config: config.clone(), + in_memory_torrent_repository: in_memory_torrent_repository.clone(), + db_torrent_repository: db_torrent_repository.clone(), + } + } + + /// It loads the torrents from database into memory. It only loads the + /// torrent entry list with the number of seeders for each torrent. Peers + /// data is not persisted. + /// + /// # Errors + /// + /// Will return a `database::Error` if unable to load the list of `persistent_torrents` from the database. + pub fn load_torrents_from_database(&self) -> Result<(), databases::error::Error> { + let persistent_torrents = self.db_torrent_repository.load_all()?; + + self.in_memory_torrent_repository.import_persistent(&persistent_torrents); + + Ok(()) + } + + /// Remove inactive peers and (optionally) peerless torrents. + pub fn cleanup_torrents(&self) { + let current_cutoff = CurrentClock::now_sub(&Duration::from_secs(u64::from(self.config.tracker_policy.max_peer_timeout))) + .unwrap_or_default(); + + self.in_memory_torrent_repository.remove_inactive_peers(current_cutoff); + + if self.config.tracker_policy.remove_peerless_torrents { + self.in_memory_torrent_repository + .remove_peerless_torrents(&self.config.tracker_policy); + } + } +} diff --git a/src/core/torrent/mod.rs b/src/core/torrent/mod.rs index 3e3e065f2..95a5ff1eb 100644 --- a/src/core/torrent/mod.rs +++ b/src/core/torrent/mod.rs @@ -25,6 +25,7 @@ //! - The number of peers that have NOT completed downloading the torrent and are still active, that means they are actively participating in the network. //! Peer that don not have a full copy of the torrent data are called "leechers". //! +pub mod manager; pub mod repository; use torrust_tracker_torrent_repository::TorrentsSkipMapMutexStd; From 4e3dbae05b8e7999f08bf8035575499c300bd496 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Thu, 23 Jan 2025 17:34:13 +0000 Subject: [PATCH 05/11] refactor: [#1201] inject new extracted sercvies in core tracker --- src/app_test.rs | 23 +++- src/bootstrap/app.rs | 19 ++- src/core/mod.rs | 76 ++++++++--- src/core/services/mod.rs | 15 ++- src/core/services/statistics/mod.rs | 21 +++- src/core/services/torrent.rs | 154 ++++++++++++++++++----- src/servers/http/v1/handlers/announce.rs | 20 ++- src/servers/http/v1/handlers/scrape.rs | 80 ++++++++++-- src/servers/http/v1/services/announce.rs | 43 +++++-- src/servers/http/v1/services/scrape.rs | 45 +++++-- src/servers/udp/handlers.rs | 68 ++++++++-- 11 files changed, 471 insertions(+), 93 deletions(-) diff --git a/src/app_test.rs b/src/app_test.rs index 929a23418..5f189f391 100644 --- a/src/app_test.rs +++ b/src/app_test.rs @@ -9,6 +9,9 @@ use crate::core::authentication::key::repository::persisted::DatabaseKeyReposito use crate::core::authentication::service::{self, AuthenticationService}; use crate::core::databases::Database; use crate::core::services::initialize_database; +use crate::core::torrent::manager::TorrentsManager; +use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; +use crate::core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use crate::core::whitelist; use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; @@ -22,6 +25,9 @@ pub fn initialize_tracker_dependencies( Arc<InMemoryWhitelist>, Arc<whitelist::authorization::Authorization>, Arc<AuthenticationService>, + Arc<InMemoryTorrentRepository>, + Arc<DatabasePersistentTorrentRepository>, + Arc<TorrentsManager>, ) { let database = initialize_database(config); let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); @@ -36,6 +42,21 @@ pub fn initialize_tracker_dependencies( &db_key_repository.clone(), &in_memory_key_repository.clone(), )); + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(&database)); + let torrents_manager = Arc::new(TorrentsManager::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); - (database, in_memory_whitelist, whitelist_authorization, authentication_service) + ( + database, + in_memory_whitelist, + whitelist_authorization, + authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) } diff --git a/src/bootstrap/app.rs b/src/bootstrap/app.rs index a0c7887cf..ea7d7f030 100644 --- a/src/bootstrap/app.rs +++ b/src/bootstrap/app.rs @@ -27,6 +27,9 @@ use crate::core::authentication::key::repository::in_memory::InMemoryKeyReposito use crate::core::authentication::key::repository::persisted::DatabaseKeyRepository; use crate::core::authentication::service; use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist_manager, statistics}; +use crate::core::torrent::manager::TorrentsManager; +use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; +use crate::core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use crate::core::whitelist; use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; use crate::servers::udp::server::banning::BanService; @@ -103,8 +106,22 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { &db_key_repository.clone(), &in_memory_key_repository.clone(), )); + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(&database)); + let torrents_manager = Arc::new(TorrentsManager::new( + &configuration.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); - let tracker = Arc::new(initialize_tracker(configuration, &database, &whitelist_authorization)); + let tracker = Arc::new(initialize_tracker( + configuration, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + )); AppContainer { tracker, diff --git a/src/core/mod.rs b/src/core/mod.rs index 61f194f3d..161607857 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -546,21 +546,17 @@ impl Tracker { config: &Core, database: &Arc<Box<dyn Database>>, whitelist_authorization: &Arc<whitelist::authorization::Authorization>, + in_memory_torrent_repository: &Arc<InMemoryTorrentRepository>, + db_torrent_repository: &Arc<DatabasePersistentTorrentRepository>, + torrents_manager: &Arc<TorrentsManager>, ) -> Result<Tracker, databases::error::Error> { - let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); - let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(database)); - Ok(Tracker { config: config.clone(), database: database.clone(), whitelist_authorization: whitelist_authorization.clone(), in_memory_torrent_repository: in_memory_torrent_repository.clone(), db_torrent_repository: db_torrent_repository.clone(), - torrents_manager: Arc::new(TorrentsManager::new( - config, - &in_memory_torrent_repository, - &db_torrent_repository, - )), + torrents_manager: torrents_manager.clone(), }) } @@ -802,21 +798,49 @@ mod tests { fn public_tracker() -> Tracker { let config = configuration::ephemeral_public(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - initialize_tracker(&config, &database, &whitelist_authorization) + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ) } fn whitelisted_tracker() -> (Tracker, Arc<whitelist::authorization::Authorization>, Arc<WhiteListManager>) { let config = configuration::ephemeral_listed(); - let (database, in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); + let ( + database, + in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); - let tracker = initialize_tracker(&config, &database, &whitelist_authorization); + let tracker = initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ); (tracker, whitelist_authorization, whitelist_manager) } @@ -825,10 +849,24 @@ mod tests { let mut config = configuration::ephemeral_listed(); config.core.tracker_policy.persistent_torrent_completed_stat = true; - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - initialize_tracker(&config, &database, &whitelist_authorization) + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ) } fn sample_info_hash() -> InfoHash { diff --git a/src/core/services/mod.rs b/src/core/services/mod.rs index 611ea24d2..f5d9bd375 100644 --- a/src/core/services/mod.rs +++ b/src/core/services/mod.rs @@ -14,6 +14,9 @@ use torrust_tracker_configuration::v2_0_0::database; use torrust_tracker_configuration::Configuration; use super::databases::{self, Database}; +use super::torrent::manager::TorrentsManager; +use super::torrent::repository::in_memory::InMemoryTorrentRepository; +use super::torrent::repository::persisted::DatabasePersistentTorrentRepository; use super::whitelist; use super::whitelist::manager::WhiteListManager; use super::whitelist::repository::in_memory::InMemoryWhitelist; @@ -30,8 +33,18 @@ pub fn initialize_tracker( config: &Configuration, database: &Arc<Box<dyn Database>>, whitelist_authorization: &Arc<whitelist::authorization::Authorization>, + in_memory_torrent_repository: &Arc<InMemoryTorrentRepository>, + db_torrent_repository: &Arc<DatabasePersistentTorrentRepository>, + torrents_manager: &Arc<TorrentsManager>, ) -> Tracker { - match Tracker::new(&Arc::new(config).core, database, whitelist_authorization) { + match Tracker::new( + &Arc::new(config).core, + database, + whitelist_authorization, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) { Ok(tracker) => tracker, Err(error) => { panic!("{}", error) diff --git a/src/core/services/statistics/mod.rs b/src/core/services/statistics/mod.rs index cc59bcf12..9e4696f48 100644 --- a/src/core/services/statistics/mod.rs +++ b/src/core/services/statistics/mod.rs @@ -132,12 +132,27 @@ mod tests { async fn the_statistics_service_should_return_the_tracker_metrics() { let config = tracker_configuration(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + let (_stats_event_sender, stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_repository = Arc::new(stats_repository); - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); + let tracker = Arc::new(initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + )); let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); diff --git a/src/core/services/torrent.rs b/src/core/services/torrent.rs index 032b526dd..1e3f67eba 100644 --- a/src/core/services/torrent.rs +++ b/src/core/services/torrent.rs @@ -145,10 +145,24 @@ mod tests { async fn should_return_none_if_the_tracker_does_not_have_the_torrent() { let config = tracker_configuration(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - let tracker = initialize_tracker(&config, &database, &whitelist_authorization); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + let tracker = initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ); let tracker = Arc::new(tracker); @@ -165,10 +179,24 @@ mod tests { async fn should_return_the_torrent_info_if_the_tracker_has_the_torrent() { let config = tracker_configuration(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + let tracker = Arc::new(initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + )); let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash = InfoHash::from_str(&hash).unwrap(); @@ -211,10 +239,24 @@ mod tests { async fn should_return_an_empty_result_if_the_tracker_does_not_have_any_torrent() { let config = tracker_configuration(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + let tracker = Arc::new(initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + )); let torrents = get_torrents_page(tracker.clone(), Some(&Pagination::default())).await; @@ -225,10 +267,24 @@ mod tests { async fn should_return_a_summarized_info_for_all_torrents() { let config = tracker_configuration(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + let tracker = Arc::new(initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + )); let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash = InfoHash::from_str(&hash).unwrap(); @@ -252,10 +308,24 @@ mod tests { async fn should_allow_limiting_the_number_of_torrents_in_the_result() { let config = tracker_configuration(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + let tracker = Arc::new(initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + )); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); @@ -277,10 +347,24 @@ mod tests { async fn should_allow_using_pagination_in_the_result() { let config = tracker_configuration(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + let tracker = Arc::new(initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + )); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); @@ -311,10 +395,24 @@ mod tests { async fn should_return_torrents_ordered_by_info_hash() { let config = tracker_configuration(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + let tracker = Arc::new(initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + )); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); diff --git a/src/servers/http/v1/handlers/announce.rs b/src/servers/http/v1/handlers/announce.rs index c42981d4c..b18671422 100644 --- a/src/servers/http/v1/handlers/announce.rs +++ b/src/servers/http/v1/handlers/announce.rs @@ -274,12 +274,26 @@ mod tests { /// Initialize tracker's dependencies and tracker. fn initialize_tracker_and_deps(config: &Configuration) -> TrackerAndDeps { - let (database, _in_memory_whitelist, whitelist_authorization, authentication_service) = - initialize_tracker_dependencies(config); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); - let tracker = Arc::new(initialize_tracker(config, &database, &whitelist_authorization)); + let tracker = Arc::new(initialize_tracker( + config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + )); (tracker, stats_event_sender, whitelist_authorization, authentication_service) } diff --git a/src/servers/http/v1/handlers/scrape.rs b/src/servers/http/v1/handlers/scrape.rs index de4610a61..e619ba120 100644 --- a/src/servers/http/v1/handlers/scrape.rs +++ b/src/servers/http/v1/handlers/scrape.rs @@ -151,13 +151,27 @@ mod tests { ) { let config = configuration::ephemeral_private(); - let (database, _in_memory_whitelist, whitelist_authorization, authentication_service) = - initialize_tracker_dependencies(&config); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); ( - initialize_tracker(&config, &database, &whitelist_authorization), + initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ), stats_event_sender, authentication_service, ) @@ -170,13 +184,27 @@ mod tests { ) { let config = configuration::ephemeral_listed(); - let (database, _in_memory_whitelist, whitelist_authorization, authentication_service) = - initialize_tracker_dependencies(&config); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); ( - initialize_tracker(&config, &database, &whitelist_authorization), + initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ), stats_event_sender, authentication_service, ) @@ -189,13 +217,27 @@ mod tests { ) { let config = configuration::ephemeral_with_reverse_proxy(); - let (database, _in_memory_whitelist, whitelist_authorization, authentication_service) = - initialize_tracker_dependencies(&config); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); ( - initialize_tracker(&config, &database, &whitelist_authorization), + initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ), stats_event_sender, authentication_service, ) @@ -208,13 +250,27 @@ mod tests { ) { let config = configuration::ephemeral_without_reverse_proxy(); - let (database, _in_memory_whitelist, whitelist_authorization, authentication_service) = - initialize_tracker_dependencies(&config); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); ( - initialize_tracker(&config, &database, &whitelist_authorization), + initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ), stats_event_sender, authentication_service, ) diff --git a/src/servers/http/v1/services/announce.rs b/src/servers/http/v1/services/announce.rs index 018348d7e..99724f728 100644 --- a/src/servers/http/v1/services/announce.rs +++ b/src/servers/http/v1/services/announce.rs @@ -73,12 +73,26 @@ mod tests { fn public_tracker() -> (Tracker, Arc<Option<Box<dyn Sender>>>) { let config = configuration::ephemeral_public(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); - let tracker = initialize_tracker(&config, &database, &whitelist_authorization); + let tracker = initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ); (tracker, stats_event_sender) } @@ -132,10 +146,25 @@ mod tests { fn test_tracker_factory() -> Tracker { let config = configuration::ephemeral(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - Tracker::new(&config.core, &database, &whitelist_authorization).unwrap() + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + Tracker::new( + &config.core, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ) + .unwrap() } #[tokio::test] diff --git a/src/servers/http/v1/services/scrape.rs b/src/servers/http/v1/services/scrape.rs index 9ad741234..c9e657d11 100644 --- a/src/servers/http/v1/services/scrape.rs +++ b/src/servers/http/v1/services/scrape.rs @@ -87,10 +87,24 @@ mod tests { fn public_tracker() -> Tracker { let config = configuration::ephemeral_public(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - initialize_tracker(&config, &database, &whitelist_authorization) + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + initialize_tracker( + &config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ) } fn sample_info_hashes() -> Vec<InfoHash> { @@ -116,10 +130,25 @@ mod tests { fn test_tracker_factory() -> Tracker { let config = configuration::ephemeral(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - Tracker::new(&config.core, &database, &whitelist_authorization).unwrap() + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + Tracker::new( + &config.core, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ) + .unwrap() } mod with_real_data { diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index feeca4e40..840b789a1 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -516,13 +516,27 @@ mod tests { } fn initialize_tracker_and_deps(config: &Configuration) -> TrackerAndDeps { - let (database, in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(config); + let ( + database, + in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); - let tracker = Arc::new(initialize_tracker(config, &database, &whitelist_authorization)); + let tracker = Arc::new(initialize_tracker( + config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + )); ( tracker, @@ -630,10 +644,27 @@ mod tests { fn test_tracker_factory() -> (Arc<Tracker>, Arc<whitelist::authorization::Authorization>) { let config = tracker_configuration(); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); - - let tracker = Arc::new(Tracker::new(&config.core, &database, &whitelist_authorization).unwrap()); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); + + let tracker = Arc::new( + Tracker::new( + &config.core, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ) + .unwrap(), + ); (tracker, whitelist_authorization) } @@ -1378,8 +1409,15 @@ mod tests { async fn the_peer_ip_should_be_changed_to_the_external_ip_in_the_tracker_configuration() { let config = Arc::new(TrackerConfigurationBuilder::default().with_external_ip("::126.0.0.1").into()); - let (database, _in_memory_whitelist, whitelist_authorization, _authentication_service) = - initialize_tracker_dependencies(&config); + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(&config); let mut stats_event_sender_mock = statistics::event::sender::MockSender::new(); stats_event_sender_mock @@ -1390,7 +1428,17 @@ mod tests { let stats_event_sender: Arc<Option<Box<dyn statistics::event::sender::Sender>>> = Arc::new(Some(Box::new(stats_event_sender_mock))); - let tracker = Arc::new(core::Tracker::new(&config.core, &database, &whitelist_authorization).unwrap()); + let tracker = Arc::new( + core::Tracker::new( + &config.core, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + ) + .unwrap(), + ); let loopback_ipv4 = Ipv4Addr::new(127, 0, 0, 1); let loopback_ipv6 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); From 6fb632ee841dc2a10421a20ba935585c17099d85 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Thu, 23 Jan 2025 17:48:17 +0000 Subject: [PATCH 06/11] refactor: [#1201] remove duplicate code --- src/core/services/torrent.rs | 148 ++++++----------------- src/servers/http/v1/handlers/announce.rs | 1 + src/servers/udp/handlers.rs | 1 + 3 files changed, 37 insertions(+), 113 deletions(-) diff --git a/src/core/services/torrent.rs b/src/core/services/torrent.rs index 1e3f67eba..f8da88d6f 100644 --- a/src/core/services/torrent.rs +++ b/src/core/services/torrent.rs @@ -107,10 +107,37 @@ pub async fn get_torrents(tracker: Arc<Tracker>, info_hashes: &[InfoHash]) -> Ve #[cfg(test)] mod tests { use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + use std::sync::Arc; use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes, PeerId}; + use torrust_tracker_configuration::Configuration; use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch}; + use crate::app_test::initialize_tracker_dependencies; + use crate::core::services::initialize_tracker; + use crate::core::Tracker; + + fn initialize_tracker_and_deps(config: &Configuration) -> Arc<Tracker> { + let ( + database, + _in_memory_whitelist, + whitelist_authorization, + _authentication_service, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, + ) = initialize_tracker_dependencies(config); + + Arc::new(initialize_tracker( + config, + &database, + &whitelist_authorization, + &in_memory_torrent_repository, + &db_torrent_repository, + &torrents_manager, + )) + } + fn sample_peer() -> peer::Peer { peer::Peer { peer_id: PeerId(*b"-qB00000000000000000"), @@ -134,7 +161,7 @@ mod tests { use crate::app_test::initialize_tracker_dependencies; use crate::core::services::initialize_tracker; - use crate::core::services::torrent::tests::sample_peer; + use crate::core::services::torrent::tests::{initialize_tracker_and_deps, sample_peer}; use crate::core::services::torrent::{get_torrent_info, Info}; pub fn tracker_configuration() -> Configuration { @@ -179,24 +206,7 @@ mod tests { async fn should_return_the_torrent_info_if_the_tracker_has_the_torrent() { let config = tracker_configuration(); - let ( - database, - _in_memory_whitelist, - whitelist_authorization, - _authentication_service, - in_memory_torrent_repository, - db_torrent_repository, - torrents_manager, - ) = initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker( - &config, - &database, - &whitelist_authorization, - &in_memory_torrent_repository, - &db_torrent_repository, - &torrents_manager, - )); + let tracker = initialize_tracker_and_deps(&config); let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash = InfoHash::from_str(&hash).unwrap(); @@ -220,15 +230,12 @@ mod tests { mod searching_for_torrents { use std::str::FromStr; - use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; use torrust_tracker_configuration::Configuration; use torrust_tracker_test_helpers::configuration; - use crate::app_test::initialize_tracker_dependencies; - use crate::core::services::initialize_tracker; - use crate::core::services::torrent::tests::sample_peer; + use crate::core::services::torrent::tests::{initialize_tracker_and_deps, sample_peer}; use crate::core::services::torrent::{get_torrents_page, BasicInfo, Pagination}; pub fn tracker_configuration() -> Configuration { @@ -239,24 +246,7 @@ mod tests { async fn should_return_an_empty_result_if_the_tracker_does_not_have_any_torrent() { let config = tracker_configuration(); - let ( - database, - _in_memory_whitelist, - whitelist_authorization, - _authentication_service, - in_memory_torrent_repository, - db_torrent_repository, - torrents_manager, - ) = initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker( - &config, - &database, - &whitelist_authorization, - &in_memory_torrent_repository, - &db_torrent_repository, - &torrents_manager, - )); + let tracker = initialize_tracker_and_deps(&config); let torrents = get_torrents_page(tracker.clone(), Some(&Pagination::default())).await; @@ -267,24 +257,7 @@ mod tests { async fn should_return_a_summarized_info_for_all_torrents() { let config = tracker_configuration(); - let ( - database, - _in_memory_whitelist, - whitelist_authorization, - _authentication_service, - in_memory_torrent_repository, - db_torrent_repository, - torrents_manager, - ) = initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker( - &config, - &database, - &whitelist_authorization, - &in_memory_torrent_repository, - &db_torrent_repository, - &torrents_manager, - )); + let tracker = initialize_tracker_and_deps(&config); let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash = InfoHash::from_str(&hash).unwrap(); @@ -308,24 +281,7 @@ mod tests { async fn should_allow_limiting_the_number_of_torrents_in_the_result() { let config = tracker_configuration(); - let ( - database, - _in_memory_whitelist, - whitelist_authorization, - _authentication_service, - in_memory_torrent_repository, - db_torrent_repository, - torrents_manager, - ) = initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker( - &config, - &database, - &whitelist_authorization, - &in_memory_torrent_repository, - &db_torrent_repository, - &torrents_manager, - )); + let tracker = initialize_tracker_and_deps(&config); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); @@ -347,24 +303,7 @@ mod tests { async fn should_allow_using_pagination_in_the_result() { let config = tracker_configuration(); - let ( - database, - _in_memory_whitelist, - whitelist_authorization, - _authentication_service, - in_memory_torrent_repository, - db_torrent_repository, - torrents_manager, - ) = initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker( - &config, - &database, - &whitelist_authorization, - &in_memory_torrent_repository, - &db_torrent_repository, - &torrents_manager, - )); + let tracker = initialize_tracker_and_deps(&config); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); @@ -395,24 +334,7 @@ mod tests { async fn should_return_torrents_ordered_by_info_hash() { let config = tracker_configuration(); - let ( - database, - _in_memory_whitelist, - whitelist_authorization, - _authentication_service, - in_memory_torrent_repository, - db_torrent_repository, - torrents_manager, - ) = initialize_tracker_dependencies(&config); - - let tracker = Arc::new(initialize_tracker( - &config, - &database, - &whitelist_authorization, - &in_memory_torrent_repository, - &db_torrent_repository, - &torrents_manager, - )); + let tracker = initialize_tracker_and_deps(&config); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); diff --git a/src/servers/http/v1/handlers/announce.rs b/src/servers/http/v1/handlers/announce.rs index b18671422..b0b54fa0d 100644 --- a/src/servers/http/v1/handlers/announce.rs +++ b/src/servers/http/v1/handlers/announce.rs @@ -283,6 +283,7 @@ mod tests { db_torrent_repository, torrents_manager, ) = initialize_tracker_dependencies(config); + let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index 840b789a1..6abbd95c6 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -525,6 +525,7 @@ mod tests { db_torrent_repository, torrents_manager, ) = initialize_tracker_dependencies(config); + let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); From a4a2d678bb5a2cd3dfa87f05cf9f748e9efbc1bc Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Thu, 23 Jan 2025 17:54:18 +0000 Subject: [PATCH 07/11] refactor: [#1201] remove pub fn from tracker --- src/core/mod.rs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/core/mod.rs b/src/core/mod.rs index 161607857..a1b496c56 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -666,18 +666,6 @@ impl Tracker { self.in_memory_torrent_repository.get_swarm_metadata(info_hash) } - /// It loads the torrents from database into memory. It only loads the torrent entry list with the number of seeders for each torrent. - /// Peers data is not persisted. - /// - /// # Context: Tracker - /// - /// # Errors - /// - /// Will return a `database::Error` if unable to load the list of `persistent_torrents` from the database. - pub fn load_torrents_from_database(&self) -> Result<(), databases::error::Error> { - self.torrents_manager.load_torrents_from_database() - } - /// # Context: Tracker /// /// Get torrent peers for a given torrent and client. @@ -1543,7 +1531,7 @@ mod tests { // Remove the newly updated torrent from memory let _unused = tracker.in_memory_torrent_repository.remove(&info_hash); - tracker.load_torrents_from_database().unwrap(); + tracker.torrents_manager.load_torrents_from_database().unwrap(); let torrent_entry = tracker .in_memory_torrent_repository From bdc3f22a8c5e67a7a67a2589ced713373d227697 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Thu, 23 Jan 2025 18:01:09 +0000 Subject: [PATCH 08/11] refactor: [#1201] add database to app container y environments --- src/bootstrap/app.rs | 1 + src/container.rs | 2 ++ tests/servers/api/environment.rs | 5 +++++ tests/servers/http/environment.rs | 5 +++++ tests/servers/udp/environment.rs | 5 +++++ 5 files changed, 18 insertions(+) diff --git a/src/bootstrap/app.rs b/src/bootstrap/app.rs index ea7d7f030..ea5dc41b6 100644 --- a/src/bootstrap/app.rs +++ b/src/bootstrap/app.rs @@ -124,6 +124,7 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { )); AppContainer { + database, tracker, keys_handler, authentication_service, diff --git a/src/container.rs b/src/container.rs index 14c4b5d7b..d8c95c42b 100644 --- a/src/container.rs +++ b/src/container.rs @@ -4,6 +4,7 @@ use tokio::sync::RwLock; use crate::core::authentication::handler::KeysHandler; use crate::core::authentication::service::AuthenticationService; +use crate::core::databases::Database; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::repository::Repository; use crate::core::whitelist::manager::WhiteListManager; @@ -11,6 +12,7 @@ use crate::core::{whitelist, Tracker}; use crate::servers::udp::server::banning::BanService; pub struct AppContainer { + pub database: Arc<Box<dyn Database>>, pub tracker: Arc<Tracker>, pub keys_handler: Arc<KeysHandler>, pub authentication_service: Arc<AuthenticationService>, diff --git a/tests/servers/api/environment.rs b/tests/servers/api/environment.rs index f014df36f..8967ff830 100644 --- a/tests/servers/api/environment.rs +++ b/tests/servers/api/environment.rs @@ -10,6 +10,7 @@ use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_g use torrust_tracker_lib::bootstrap::jobs::make_rust_tls; use torrust_tracker_lib::core::authentication::handler::KeysHandler; use torrust_tracker_lib::core::authentication::service::AuthenticationService; +use torrust_tracker_lib::core::databases::Database; use torrust_tracker_lib::core::statistics::event::sender::Sender; use torrust_tracker_lib::core::statistics::repository::Repository; use torrust_tracker_lib::core::whitelist::manager::WhiteListManager; @@ -24,6 +25,7 @@ where S: std::fmt::Debug + std::fmt::Display, { pub config: Arc<HttpApi>, + pub database: Arc<Box<dyn Database>>, pub tracker: Arc<Tracker>, pub keys_handler: Arc<KeysHandler>, pub authentication_service: Arc<AuthenticationService>, @@ -61,6 +63,7 @@ impl Environment<Stopped> { Self { config, + database: app_container.database.clone(), tracker: app_container.tracker.clone(), keys_handler: app_container.keys_handler.clone(), authentication_service: app_container.authentication_service.clone(), @@ -78,6 +81,7 @@ impl Environment<Stopped> { Environment { config: self.config, + database: self.database.clone(), tracker: self.tracker.clone(), keys_handler: self.keys_handler.clone(), authentication_service: self.authentication_service.clone(), @@ -112,6 +116,7 @@ impl Environment<Running> { pub async fn stop(self) -> Environment<Stopped> { Environment { config: self.config, + database: self.database, tracker: self.tracker, keys_handler: self.keys_handler, authentication_service: self.authentication_service, diff --git a/tests/servers/http/environment.rs b/tests/servers/http/environment.rs index 81b6a12e2..80c042a21 100644 --- a/tests/servers/http/environment.rs +++ b/tests/servers/http/environment.rs @@ -7,6 +7,7 @@ use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_g use torrust_tracker_lib::bootstrap::jobs::make_rust_tls; use torrust_tracker_lib::core::authentication::handler::KeysHandler; use torrust_tracker_lib::core::authentication::service::AuthenticationService; +use torrust_tracker_lib::core::databases::Database; use torrust_tracker_lib::core::statistics::event::sender::Sender; use torrust_tracker_lib::core::statistics::repository::Repository; use torrust_tracker_lib::core::whitelist::manager::WhiteListManager; @@ -17,6 +18,7 @@ use torrust_tracker_primitives::peer; pub struct Environment<S> { pub config: Arc<HttpTracker>, + pub database: Arc<Box<dyn Database>>, pub tracker: Arc<Tracker>, pub keys_handler: Arc<KeysHandler>, pub authentication_service: Arc<AuthenticationService>, @@ -57,6 +59,7 @@ impl Environment<Stopped> { Self { config, + database: app_container.database.clone(), tracker: app_container.tracker.clone(), keys_handler: app_container.keys_handler.clone(), authentication_service: app_container.authentication_service.clone(), @@ -73,6 +76,7 @@ impl Environment<Stopped> { pub async fn start(self) -> Environment<Running> { Environment { config: self.config, + database: self.database.clone(), tracker: self.tracker.clone(), keys_handler: self.keys_handler.clone(), authentication_service: self.authentication_service.clone(), @@ -104,6 +108,7 @@ impl Environment<Running> { pub async fn stop(self) -> Environment<Stopped> { Environment { config: self.config, + database: self.database, tracker: self.tracker, keys_handler: self.keys_handler, authentication_service: self.authentication_service, diff --git a/tests/servers/udp/environment.rs b/tests/servers/udp/environment.rs index b728509c0..c02e35e6e 100644 --- a/tests/servers/udp/environment.rs +++ b/tests/servers/udp/environment.rs @@ -5,6 +5,7 @@ use bittorrent_primitives::info_hash::InfoHash; use tokio::sync::RwLock; use torrust_tracker_configuration::{Configuration, UdpTracker, DEFAULT_TIMEOUT}; use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_global_services}; +use torrust_tracker_lib::core::databases::Database; use torrust_tracker_lib::core::statistics::event::sender::Sender; use torrust_tracker_lib::core::statistics::repository::Repository; use torrust_tracker_lib::core::{whitelist, Tracker}; @@ -20,6 +21,7 @@ where S: std::fmt::Debug + std::fmt::Display, { pub config: Arc<UdpTracker>, + pub database: Arc<Box<dyn Database>>, pub tracker: Arc<Tracker>, pub whitelist_authorization: Arc<whitelist::authorization::Authorization>, pub stats_event_sender: Arc<Option<Box<dyn Sender>>>, @@ -57,6 +59,7 @@ impl Environment<Stopped> { Self { config, + database: app_container.database.clone(), tracker: app_container.tracker.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), stats_event_sender: app_container.stats_event_sender.clone(), @@ -72,6 +75,7 @@ impl Environment<Stopped> { let cookie_lifetime = self.config.cookie_lifetime; Environment { config: self.config, + database: self.database.clone(), tracker: self.tracker.clone(), whitelist_authorization: self.whitelist_authorization.clone(), stats_event_sender: self.stats_event_sender.clone(), @@ -109,6 +113,7 @@ impl Environment<Running> { Environment { config: self.config, + database: self.database, tracker: self.tracker, whitelist_authorization: self.whitelist_authorization, stats_event_sender: self.stats_event_sender, From b3fcdb4c156feb610ad719afca90ead8912f29db Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Thu, 23 Jan 2025 18:11:47 +0000 Subject: [PATCH 09/11] refactor: [#1201] remove direct dependency on database from tracker --- src/bootstrap/app.rs | 1 - src/core/mod.rs | 26 ++----------------- src/core/services/mod.rs | 2 -- src/core/services/statistics/mod.rs | 3 +-- src/core/services/torrent.rs | 6 ++--- src/servers/http/v1/handlers/announce.rs | 5 ++-- src/servers/http/v1/handlers/scrape.rs | 12 +++------ src/servers/http/v1/services/announce.rs | 6 ++--- src/servers/http/v1/services/scrape.rs | 6 ++--- src/servers/udp/handlers.rs | 9 +++---- tests/servers/api/mod.rs | 11 +++++--- .../api/v1/contract/context/auth_key.rs | 8 +++--- .../api/v1/contract/context/whitelist.rs | 6 ++--- 13 files changed, 32 insertions(+), 69 deletions(-) diff --git a/src/bootstrap/app.rs b/src/bootstrap/app.rs index ea5dc41b6..2340eb0ac 100644 --- a/src/bootstrap/app.rs +++ b/src/bootstrap/app.rs @@ -116,7 +116,6 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { let tracker = Arc::new(initialize_tracker( configuration, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, diff --git a/src/core/mod.rs b/src/core/mod.rs index a1b496c56..18c99d3b9 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -462,8 +462,6 @@ use torrust_tracker_primitives::peer; use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; -use crate::core::databases::Database; - /// The domain layer tracker service. /// /// Its main responsibility is to handle the `announce` and `scrape` requests. @@ -477,10 +475,6 @@ pub struct Tracker { /// The tracker configuration. config: Core, - /// A database driver implementation: [`Sqlite3`](crate::core::databases::sqlite) - /// or [`MySQL`](crate::core::databases::mysql) - database: Arc<Box<dyn Database>>, - /// The service to check is a torrent is whitelisted. pub whitelist_authorization: Arc<whitelist::authorization::Authorization>, @@ -544,7 +538,6 @@ impl Tracker { /// Will return a `databases::error::Error` if unable to connect to database. The `Tracker` is responsible for the persistence. pub fn new( config: &Core, - database: &Arc<Box<dyn Database>>, whitelist_authorization: &Arc<whitelist::authorization::Authorization>, in_memory_torrent_repository: &Arc<InMemoryTorrentRepository>, db_torrent_repository: &Arc<DatabasePersistentTorrentRepository>, @@ -552,7 +545,6 @@ impl Tracker { ) -> Result<Tracker, databases::error::Error> { Ok(Tracker { config: config.clone(), - database: database.clone(), whitelist_authorization: whitelist_authorization.clone(), in_memory_torrent_repository: in_memory_torrent_repository.clone(), db_torrent_repository: db_torrent_repository.clone(), @@ -739,17 +731,6 @@ impl Tracker { pub fn cleanup_torrents(&self) { self.torrents_manager.cleanup_torrents(); } - - /// It drops the database tables. - /// - /// # Errors - /// - /// Will return `Err` if unable to drop tables. - pub fn drop_database_tables(&self) -> Result<(), databases::error::Error> { - // todo: this is only used for testing. We have to pass the database - // reference directly to the tests instead of via the tracker. - self.database.drop_database_tables() - } } #[must_use] @@ -787,7 +768,7 @@ mod tests { let config = configuration::ephemeral_public(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, _authentication_service, @@ -798,7 +779,6 @@ mod tests { initialize_tracker( &config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, @@ -823,7 +803,6 @@ mod tests { let tracker = initialize_tracker( &config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, @@ -838,7 +817,7 @@ mod tests { config.core.tracker_policy.persistent_torrent_completed_stat = true; let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, _authentication_service, @@ -849,7 +828,6 @@ mod tests { initialize_tracker( &config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, diff --git a/src/core/services/mod.rs b/src/core/services/mod.rs index f5d9bd375..3a684ac8f 100644 --- a/src/core/services/mod.rs +++ b/src/core/services/mod.rs @@ -31,7 +31,6 @@ use crate::core::Tracker; #[must_use] pub fn initialize_tracker( config: &Configuration, - database: &Arc<Box<dyn Database>>, whitelist_authorization: &Arc<whitelist::authorization::Authorization>, in_memory_torrent_repository: &Arc<InMemoryTorrentRepository>, db_torrent_repository: &Arc<DatabasePersistentTorrentRepository>, @@ -39,7 +38,6 @@ pub fn initialize_tracker( ) -> Tracker { match Tracker::new( &Arc::new(config).core, - database, whitelist_authorization, in_memory_torrent_repository, db_torrent_repository, diff --git a/src/core/services/statistics/mod.rs b/src/core/services/statistics/mod.rs index 9e4696f48..01e49df71 100644 --- a/src/core/services/statistics/mod.rs +++ b/src/core/services/statistics/mod.rs @@ -133,7 +133,7 @@ mod tests { let config = tracker_configuration(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, _authentication_service, @@ -147,7 +147,6 @@ mod tests { let tracker = Arc::new(initialize_tracker( &config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, diff --git a/src/core/services/torrent.rs b/src/core/services/torrent.rs index f8da88d6f..dc07405ee 100644 --- a/src/core/services/torrent.rs +++ b/src/core/services/torrent.rs @@ -119,7 +119,7 @@ mod tests { fn initialize_tracker_and_deps(config: &Configuration) -> Arc<Tracker> { let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, _authentication_service, @@ -130,7 +130,6 @@ mod tests { Arc::new(initialize_tracker( config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, @@ -173,7 +172,7 @@ mod tests { let config = tracker_configuration(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, _authentication_service, @@ -184,7 +183,6 @@ mod tests { let tracker = initialize_tracker( &config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, diff --git a/src/servers/http/v1/handlers/announce.rs b/src/servers/http/v1/handlers/announce.rs index b0b54fa0d..4088ab73c 100644 --- a/src/servers/http/v1/handlers/announce.rs +++ b/src/servers/http/v1/handlers/announce.rs @@ -275,7 +275,7 @@ mod tests { /// Initialize tracker's dependencies and tracker. fn initialize_tracker_and_deps(config: &Configuration) -> TrackerAndDeps { let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, authentication_service, @@ -283,13 +283,12 @@ mod tests { db_torrent_repository, torrents_manager, ) = initialize_tracker_dependencies(config); - + let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); let tracker = Arc::new(initialize_tracker( config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, diff --git a/src/servers/http/v1/handlers/scrape.rs b/src/servers/http/v1/handlers/scrape.rs index e619ba120..24b1c783d 100644 --- a/src/servers/http/v1/handlers/scrape.rs +++ b/src/servers/http/v1/handlers/scrape.rs @@ -152,7 +152,7 @@ mod tests { let config = configuration::ephemeral_private(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, authentication_service, @@ -166,7 +166,6 @@ mod tests { ( initialize_tracker( &config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, @@ -185,7 +184,7 @@ mod tests { let config = configuration::ephemeral_listed(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, authentication_service, @@ -199,7 +198,6 @@ mod tests { ( initialize_tracker( &config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, @@ -218,7 +216,7 @@ mod tests { let config = configuration::ephemeral_with_reverse_proxy(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, authentication_service, @@ -232,7 +230,6 @@ mod tests { ( initialize_tracker( &config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, @@ -251,7 +248,7 @@ mod tests { let config = configuration::ephemeral_without_reverse_proxy(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, authentication_service, @@ -265,7 +262,6 @@ mod tests { ( initialize_tracker( &config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, diff --git a/src/servers/http/v1/services/announce.rs b/src/servers/http/v1/services/announce.rs index 99724f728..56b2dd1e3 100644 --- a/src/servers/http/v1/services/announce.rs +++ b/src/servers/http/v1/services/announce.rs @@ -74,7 +74,7 @@ mod tests { let config = configuration::ephemeral_public(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, _authentication_service, @@ -87,7 +87,6 @@ mod tests { let tracker = initialize_tracker( &config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, @@ -147,7 +146,7 @@ mod tests { let config = configuration::ephemeral(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, _authentication_service, @@ -158,7 +157,6 @@ mod tests { Tracker::new( &config.core, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, diff --git a/src/servers/http/v1/services/scrape.rs b/src/servers/http/v1/services/scrape.rs index c9e657d11..ea4cb2702 100644 --- a/src/servers/http/v1/services/scrape.rs +++ b/src/servers/http/v1/services/scrape.rs @@ -88,7 +88,7 @@ mod tests { let config = configuration::ephemeral_public(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, _authentication_service, @@ -99,7 +99,6 @@ mod tests { initialize_tracker( &config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, @@ -131,7 +130,7 @@ mod tests { let config = configuration::ephemeral(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, _authentication_service, @@ -142,7 +141,6 @@ mod tests { Tracker::new( &config.core, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index 6abbd95c6..c85efc1fa 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -525,14 +525,13 @@ mod tests { db_torrent_repository, torrents_manager, ) = initialize_tracker_dependencies(config); - + let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); let tracker = Arc::new(initialize_tracker( config, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, @@ -646,7 +645,7 @@ mod tests { let config = tracker_configuration(); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, _authentication_service, @@ -658,7 +657,6 @@ mod tests { let tracker = Arc::new( Tracker::new( &config.core, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, @@ -1411,7 +1409,7 @@ mod tests { let config = Arc::new(TrackerConfigurationBuilder::default().with_external_ip("::126.0.0.1").into()); let ( - database, + _database, _in_memory_whitelist, whitelist_authorization, _authentication_service, @@ -1432,7 +1430,6 @@ mod tests { let tracker = Arc::new( core::Tracker::new( &config.core, - &database, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, diff --git a/tests/servers/api/mod.rs b/tests/servers/api/mod.rs index 278fd869d..92bc19a5f 100644 --- a/tests/servers/api/mod.rs +++ b/tests/servers/api/mod.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use torrust_tracker_lib::core::Tracker; +use torrust_tracker_lib::core::databases::Database; use torrust_tracker_lib::servers::apis::server; pub mod connection_info; @@ -9,12 +9,15 @@ pub mod v1; pub type Started = environment::Environment<server::Running>; -/// It forces a database error by dropping all tables. -/// That makes any query fail. +/// It forces a database error by dropping all tables. That makes all queries +/// fail. +/// /// code-review: +/// /// Alternatively we could: +/// /// - Inject a database mock in the future. /// - Inject directly the database reference passed to the Tracker type. -pub fn force_database_error(tracker: &Arc<Tracker>) { +pub fn force_database_error(tracker: &Arc<Box<dyn Database>>) { tracker.drop_database_tables().unwrap(); } diff --git a/tests/servers/api/v1/contract/context/auth_key.rs b/tests/servers/api/v1/contract/context/auth_key.rs index 73860c9c2..3b7d2d6ba 100644 --- a/tests/servers/api/v1/contract/context/auth_key.rs +++ b/tests/servers/api/v1/contract/context/auth_key.rs @@ -126,7 +126,7 @@ async fn should_fail_when_the_auth_key_cannot_be_generated() { let env = Started::new(&configuration::ephemeral().into()).await; - force_database_error(&env.tracker); + force_database_error(&env.database); let request_id = Uuid::new_v4(); @@ -297,7 +297,7 @@ async fn should_fail_when_the_auth_key_cannot_be_deleted() { .await .unwrap(); - force_database_error(&env.tracker); + force_database_error(&env.database); let request_id = Uuid::new_v4(); @@ -403,7 +403,7 @@ async fn should_fail_when_keys_cannot_be_reloaded() { .await .unwrap(); - force_database_error(&env.tracker); + force_database_error(&env.database); let response = Client::new(env.get_connection_info()) .reload_keys(Some(headers_with_request_id(request_id))) @@ -556,7 +556,7 @@ mod deprecated_generate_key_endpoint { let env = Started::new(&configuration::ephemeral().into()).await; - force_database_error(&env.tracker); + force_database_error(&env.database); let request_id = Uuid::new_v4(); let seconds_valid = 60; diff --git a/tests/servers/api/v1/contract/context/whitelist.rs b/tests/servers/api/v1/contract/context/whitelist.rs index aef1db4f1..78850d3bf 100644 --- a/tests/servers/api/v1/contract/context/whitelist.rs +++ b/tests/servers/api/v1/contract/context/whitelist.rs @@ -111,7 +111,7 @@ async fn should_fail_when_the_torrent_cannot_be_whitelisted() { let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); - force_database_error(&env.tracker); + force_database_error(&env.database); let request_id = Uuid::new_v4(); @@ -239,7 +239,7 @@ async fn should_fail_when_the_torrent_cannot_be_removed_from_the_whitelist() { let info_hash = InfoHash::from_str(&hash).unwrap(); env.whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); - force_database_error(&env.tracker); + force_database_error(&env.database); let request_id = Uuid::new_v4(); @@ -340,7 +340,7 @@ async fn should_fail_when_the_whitelist_cannot_be_reloaded_from_the_database() { let info_hash = InfoHash::from_str(&hash).unwrap(); env.whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); - force_database_error(&env.tracker); + force_database_error(&env.database); let request_id = Uuid::new_v4(); From 3a2e8f0d4c3a1d06d77fd83b7f2d065f250e8390 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Thu, 23 Jan 2025 18:17:37 +0000 Subject: [PATCH 10/11] refactor: [#1201] reorganize methods in tracker Grouping similar methods. --- src/core/mod.rs | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/core/mod.rs b/src/core/mod.rs index 18c99d3b9..d50d2b545 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -653,28 +653,6 @@ impl Tracker { scrape_data } - /// It returns the data for a `scrape` response. - fn get_swarm_metadata(&self, info_hash: &InfoHash) -> SwarmMetadata { - self.in_memory_torrent_repository.get_swarm_metadata(info_hash) - } - - /// # Context: Tracker - /// - /// Get torrent peers for a given torrent and client. - /// - /// It filters out the client making the request. - fn get_peers_for(&self, info_hash: &InfoHash, peer: &peer::Peer, limit: usize) -> Vec<Arc<peer::Peer>> { - self.in_memory_torrent_repository.get_peers_for(info_hash, peer, limit) - } - - /// # Context: Tracker - /// - /// Get torrent peers for a given torrent. - #[must_use] - pub fn get_torrent_peers(&self, info_hash: &InfoHash) -> Vec<Arc<peer::Peer>> { - self.in_memory_torrent_repository.get_torrent_peers(info_hash) - } - /// It updates the torrent entry in memory, it also stores in the database /// the torrent info data which is persistent, and finally return the data /// needed for a `announce` request response. @@ -713,6 +691,28 @@ impl Tracker { } } + /// It returns the data for a `scrape` response. + fn get_swarm_metadata(&self, info_hash: &InfoHash) -> SwarmMetadata { + self.in_memory_torrent_repository.get_swarm_metadata(info_hash) + } + + /// # Context: Tracker + /// + /// Get torrent peers for a given torrent and client. + /// + /// It filters out the client making the request. + fn get_peers_for(&self, info_hash: &InfoHash, peer: &peer::Peer, limit: usize) -> Vec<Arc<peer::Peer>> { + self.in_memory_torrent_repository.get_peers_for(info_hash, peer, limit) + } + + /// # Context: Tracker + /// + /// Get torrent peers for a given torrent. + #[must_use] + pub fn get_torrent_peers(&self, info_hash: &InfoHash) -> Vec<Arc<peer::Peer>> { + self.in_memory_torrent_repository.get_torrent_peers(info_hash) + } + /// It calculates and returns the general `Tracker` /// [`TorrentsMetrics`] /// From 612f7293d5a2190e710852dfd51330248e50c61a Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Thu, 23 Jan 2025 18:28:16 +0000 Subject: [PATCH 11/11] refactor: [#1201] remove tracker dependency on TorrentsManager --- src/app.rs | 2 +- src/bootstrap/app.rs | 4 ++- src/bootstrap/jobs/torrent_cleanup.rs | 12 ++++----- src/container.rs | 6 +++++ src/core/mod.rs | 33 +++++++----------------- src/core/services/mod.rs | 3 --- src/core/services/statistics/mod.rs | 3 +-- src/core/services/torrent.rs | 6 ++--- src/servers/http/v1/handlers/announce.rs | 3 +-- src/servers/http/v1/handlers/scrape.rs | 12 +++------ src/servers/http/v1/services/announce.rs | 6 ++--- src/servers/http/v1/services/scrape.rs | 6 ++--- src/servers/udp/handlers.rs | 9 +++---- 13 files changed, 41 insertions(+), 64 deletions(-) diff --git a/src/app.rs b/src/app.rs index e41f227e7..c71237443 100644 --- a/src/app.rs +++ b/src/app.rs @@ -137,7 +137,7 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< // Start runners to remove torrents without peers, every interval if config.core.inactive_peer_cleanup_interval > 0 { - jobs.push(torrent_cleanup::start_job(&config.core, &app_container.tracker)); + jobs.push(torrent_cleanup::start_job(&config.core, &app_container.torrents_manager)); } // Start Health Check API diff --git a/src/bootstrap/app.rs b/src/bootstrap/app.rs index 2340eb0ac..294b2ca73 100644 --- a/src/bootstrap/app.rs +++ b/src/bootstrap/app.rs @@ -119,7 +119,6 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, )); AppContainer { @@ -132,6 +131,9 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { stats_event_sender, stats_repository, whitelist_manager, + in_memory_torrent_repository, + db_torrent_repository, + torrents_manager, } } diff --git a/src/bootstrap/jobs/torrent_cleanup.rs b/src/bootstrap/jobs/torrent_cleanup.rs index 6abb4f26b..45e6e9e68 100644 --- a/src/bootstrap/jobs/torrent_cleanup.rs +++ b/src/bootstrap/jobs/torrent_cleanup.rs @@ -17,7 +17,7 @@ use tokio::task::JoinHandle; use torrust_tracker_configuration::Core; use tracing::instrument; -use crate::core; +use crate::core::torrent::manager::TorrentsManager; /// It starts a jobs for cleaning up the torrent data in the tracker. /// @@ -25,9 +25,9 @@ use crate::core; /// /// Refer to [`torrust-tracker-configuration documentation`](https://docs.rs/torrust-tracker-configuration) for more info about that option. #[must_use] -#[instrument(skip(config, tracker))] -pub fn start_job(config: &Core, tracker: &Arc<core::Tracker>) -> JoinHandle<()> { - let weak_tracker = std::sync::Arc::downgrade(tracker); +#[instrument(skip(config, torrents_manager))] +pub fn start_job(config: &Core, torrents_manager: &Arc<TorrentsManager>) -> JoinHandle<()> { + let weak_torrents_manager = std::sync::Arc::downgrade(torrents_manager); let interval = config.inactive_peer_cleanup_interval; tokio::spawn(async move { @@ -42,10 +42,10 @@ pub fn start_job(config: &Core, tracker: &Arc<core::Tracker>) -> JoinHandle<()> break; } _ = interval.tick() => { - if let Some(tracker) = weak_tracker.upgrade() { + if let Some(torrents_manager) = weak_torrents_manager.upgrade() { let start_time = Utc::now().time(); tracing::info!("Cleaning up torrents.."); - tracker.cleanup_torrents(); + torrents_manager.cleanup_torrents(); tracing::info!("Cleaned up torrents in: {}ms", (Utc::now().time() - start_time).num_milliseconds()); } else { break; diff --git a/src/container.rs b/src/container.rs index d8c95c42b..8407d0b69 100644 --- a/src/container.rs +++ b/src/container.rs @@ -7,6 +7,9 @@ use crate::core::authentication::service::AuthenticationService; use crate::core::databases::Database; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::repository::Repository; +use crate::core::torrent::manager::TorrentsManager; +use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; +use crate::core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use crate::core::whitelist::manager::WhiteListManager; use crate::core::{whitelist, Tracker}; use crate::servers::udp::server::banning::BanService; @@ -21,4 +24,7 @@ pub struct AppContainer { pub stats_event_sender: Arc<Option<Box<dyn Sender>>>, pub stats_repository: Arc<Repository>, pub whitelist_manager: Arc<WhiteListManager>, + pub in_memory_torrent_repository: Arc<InMemoryTorrentRepository>, + pub db_torrent_repository: Arc<DatabasePersistentTorrentRepository>, + pub torrents_manager: Arc<TorrentsManager>, } diff --git a/src/core/mod.rs b/src/core/mod.rs index d50d2b545..f2483b21e 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -453,7 +453,6 @@ use std::net::IpAddr; use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; -use torrent::manager::TorrentsManager; use torrent::repository::in_memory::InMemoryTorrentRepository; use torrent::repository::persisted::DatabasePersistentTorrentRepository; use torrust_tracker_configuration::{AnnouncePolicy, Core, TORRENT_PEERS_LIMIT}; @@ -483,9 +482,6 @@ pub struct Tracker { /// The persistent torrents repository. db_torrent_repository: Arc<DatabasePersistentTorrentRepository>, - - /// The service to run torrents tasks. - torrents_manager: Arc<TorrentsManager>, } /// How many peers the peer announcing wants in the announce response. @@ -541,14 +537,12 @@ impl Tracker { whitelist_authorization: &Arc<whitelist::authorization::Authorization>, in_memory_torrent_repository: &Arc<InMemoryTorrentRepository>, db_torrent_repository: &Arc<DatabasePersistentTorrentRepository>, - torrents_manager: &Arc<TorrentsManager>, ) -> Result<Tracker, databases::error::Error> { Ok(Tracker { config: config.clone(), whitelist_authorization: whitelist_authorization.clone(), in_memory_torrent_repository: in_memory_torrent_repository.clone(), db_torrent_repository: db_torrent_repository.clone(), - torrents_manager: torrents_manager.clone(), }) } @@ -724,13 +718,6 @@ impl Tracker { pub fn get_torrents_metrics(&self) -> TorrentsMetrics { self.in_memory_torrent_repository.get_torrents_metrics() } - - /// Remove inactive peers and (optionally) peerless torrents. - /// - /// # Context: Tracker - pub fn cleanup_torrents(&self) { - self.torrents_manager.cleanup_torrents(); - } } #[must_use] @@ -761,6 +748,7 @@ mod tests { use crate::app_test::initialize_tracker_dependencies; use crate::core::peer::Peer; use crate::core::services::{initialize_tracker, initialize_whitelist_manager}; + use crate::core::torrent::manager::TorrentsManager; use crate::core::whitelist::manager::WhiteListManager; use crate::core::{whitelist, TorrentsMetrics, Tracker}; @@ -774,7 +762,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); initialize_tracker( @@ -782,7 +770,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ) } @@ -796,7 +783,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); @@ -806,13 +793,12 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ); (tracker, whitelist_authorization, whitelist_manager) } - pub fn tracker_persisting_torrents_in_database() -> Tracker { + pub fn tracker_persisting_torrents_in_database() -> (Tracker, Arc<TorrentsManager>) { let mut config = configuration::ephemeral_listed(); config.core.tracker_policy.persistent_torrent_completed_stat = true; @@ -826,13 +812,14 @@ mod tests { torrents_manager, ) = initialize_tracker_dependencies(&config); - initialize_tracker( + let tracker = initialize_tracker( &config, &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, - ) + ); + + (tracker, torrents_manager) } fn sample_info_hash() -> InfoHash { @@ -1492,7 +1479,7 @@ mod tests { #[tokio::test] async fn it_should_persist_the_number_of_completed_peers_for_all_torrents_into_the_database() { - let tracker = tracker_persisting_torrents_in_database(); + let (tracker, torrents_manager) = tracker_persisting_torrents_in_database(); let info_hash = sample_info_hash(); @@ -1509,7 +1496,7 @@ mod tests { // Remove the newly updated torrent from memory let _unused = tracker.in_memory_torrent_repository.remove(&info_hash); - tracker.torrents_manager.load_torrents_from_database().unwrap(); + torrents_manager.load_torrents_from_database().unwrap(); let torrent_entry = tracker .in_memory_torrent_repository diff --git a/src/core/services/mod.rs b/src/core/services/mod.rs index 3a684ac8f..a9bca2df7 100644 --- a/src/core/services/mod.rs +++ b/src/core/services/mod.rs @@ -14,7 +14,6 @@ use torrust_tracker_configuration::v2_0_0::database; use torrust_tracker_configuration::Configuration; use super::databases::{self, Database}; -use super::torrent::manager::TorrentsManager; use super::torrent::repository::in_memory::InMemoryTorrentRepository; use super::torrent::repository::persisted::DatabasePersistentTorrentRepository; use super::whitelist; @@ -34,14 +33,12 @@ pub fn initialize_tracker( whitelist_authorization: &Arc<whitelist::authorization::Authorization>, in_memory_torrent_repository: &Arc<InMemoryTorrentRepository>, db_torrent_repository: &Arc<DatabasePersistentTorrentRepository>, - torrents_manager: &Arc<TorrentsManager>, ) -> Tracker { match Tracker::new( &Arc::new(config).core, whitelist_authorization, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, ) { Ok(tracker) => tracker, Err(error) => { diff --git a/src/core/services/statistics/mod.rs b/src/core/services/statistics/mod.rs index 01e49df71..7c2233efd 100644 --- a/src/core/services/statistics/mod.rs +++ b/src/core/services/statistics/mod.rs @@ -139,7 +139,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); let (_stats_event_sender, stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); @@ -150,7 +150,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, )); let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); diff --git a/src/core/services/torrent.rs b/src/core/services/torrent.rs index dc07405ee..c2ffa05aa 100644 --- a/src/core/services/torrent.rs +++ b/src/core/services/torrent.rs @@ -125,7 +125,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(config); Arc::new(initialize_tracker( @@ -133,7 +133,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, )) } @@ -178,7 +177,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); let tracker = initialize_tracker( @@ -186,7 +185,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ); let tracker = Arc::new(tracker); diff --git a/src/servers/http/v1/handlers/announce.rs b/src/servers/http/v1/handlers/announce.rs index 4088ab73c..a9567fb81 100644 --- a/src/servers/http/v1/handlers/announce.rs +++ b/src/servers/http/v1/handlers/announce.rs @@ -281,7 +281,7 @@ mod tests { authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); @@ -292,7 +292,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, )); (tracker, stats_event_sender, whitelist_authorization, authentication_service) diff --git a/src/servers/http/v1/handlers/scrape.rs b/src/servers/http/v1/handlers/scrape.rs index 24b1c783d..116d717a1 100644 --- a/src/servers/http/v1/handlers/scrape.rs +++ b/src/servers/http/v1/handlers/scrape.rs @@ -158,7 +158,7 @@ mod tests { authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); @@ -169,7 +169,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ), stats_event_sender, authentication_service, @@ -190,7 +189,7 @@ mod tests { authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); @@ -201,7 +200,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ), stats_event_sender, authentication_service, @@ -222,7 +220,7 @@ mod tests { authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); @@ -233,7 +231,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ), stats_event_sender, authentication_service, @@ -254,7 +251,7 @@ mod tests { authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); @@ -265,7 +262,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ), stats_event_sender, authentication_service, diff --git a/src/servers/http/v1/services/announce.rs b/src/servers/http/v1/services/announce.rs index 56b2dd1e3..322bc80eb 100644 --- a/src/servers/http/v1/services/announce.rs +++ b/src/servers/http/v1/services/announce.rs @@ -80,7 +80,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); @@ -90,7 +90,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ); (tracker, stats_event_sender) @@ -152,7 +151,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); Tracker::new( @@ -160,7 +159,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ) .unwrap() } diff --git a/src/servers/http/v1/services/scrape.rs b/src/servers/http/v1/services/scrape.rs index ea4cb2702..299938f84 100644 --- a/src/servers/http/v1/services/scrape.rs +++ b/src/servers/http/v1/services/scrape.rs @@ -94,7 +94,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); initialize_tracker( @@ -102,7 +102,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ) } @@ -136,7 +135,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); Tracker::new( @@ -144,7 +143,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ) .unwrap() } diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index c85efc1fa..5584c167b 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -523,7 +523,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); @@ -535,7 +535,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, )); ( @@ -651,7 +650,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); let tracker = Arc::new( @@ -660,7 +659,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ) .unwrap(), ); @@ -1415,7 +1413,7 @@ mod tests { _authentication_service, in_memory_torrent_repository, db_torrent_repository, - torrents_manager, + _torrents_manager, ) = initialize_tracker_dependencies(&config); let mut stats_event_sender_mock = statistics::event::sender::MockSender::new(); @@ -1433,7 +1431,6 @@ mod tests { &whitelist_authorization, &in_memory_torrent_repository, &db_torrent_repository, - &torrents_manager, ) .unwrap(), );