Skip to content

Commit c68570c

Browse files
committed
Merge #1497: Overhaul stats: Improve torrent-repository package before adding events (part 1)
728de22 docs: [#1495] add todo (Jose Celano) 34c159a refactor: [#1495] update method Swarm::meets_retaining_policy (Jose Celano) 0f4596e fix: [#1495] formatting (Jose Celano) 0411a9a refactor: [#1495] rename TorrentRepository to Swarms (Jose Celano) 78d4b83 refactor: [#1495] rename TrackedTorrentHandle to SwarmHandle (Jose Celano) 030ae26 refactor: [#1495] reorganize torrent-repository mod (Jose Celano) ca9937d refactor: [#1495] remove unneeded TrackedTorrent (wrapper over Swarm) (Jose Celano) b6afed5 refactor: [#1495] rename methods (Jose Celano) ef7292f refactor: [#1495] move logic from TrackedTorrent to Swarm (Jose Celano) 23ce6e4 refactor: [#1495]remove unused field in TrackedTorrent (Jose Celano) ec597f0 refactor: [#1495] get the number of downloads from Swarm instead of from TrackedTorrent (Jose Celano) 3fb117b refactor: [#1495] initialize number of downloads in Swarm to persisted value (Jose Celano) 9b2392e refactor: [#1495] make TrackedTorrent fields private (Jose Celano) 82bbfe3 refactor: [#1495] move logic from TackedTorrent to Swarm (Jose Celano) f73c566 refactor: [#1495] some renamings in Swarm type (Jose Celano) 61560a8 chore: add gitignore to torrent-repository pkg (Jose Celano) 0a4c805 refactor: [#1495] add SwarmMetadata to Swarm (Jose Celano) 2882705 refactor: [#1495] use SocketAddr as key for peers in Swarm (Jose Celano) 15c14c5 refactor: [#1495] rename PeerList to Swarm (Jose Celano) cb51ec9 docs: [#1495] improve torrent-repository pkg readme (Jose Celano) Pull request description: Partially implements #1495 Improve `torrent-repository` package before adding events. ### Sutasks - [x] Update README #### Refactoring `PeerList` - [x] Rename `PeerList` to `Swarm`. - [x] Use `SocketAddr` as key for peers in `Swarm` instead of the `PeerId`. - [x] Use a cache for seeders and leechers counters to avoid iterating the list. - [x] Move logic from `TrackerTorrent` to `Swarm` #### Refactoring `TrackedTorrent` (it was removed) - [x] Remove the `downloaded` field from `TrackedTorrent`. The logic can be moved to `Swarm`. - [x] Document `meets_retaining_policy` method behavior. I don't know why peerless torrents are kept when persisted stats (`downloaded` field) are enabled (only if the torrent has been downloaded at least once). It was removed because after the refactorings, it became just a wrapper over `Swarm`. #### Refactoring `TorrentRepository` To be implemented in a new PR. ### New state There are only two primary types: - `Swarm`: a collection of peers. Peers are members of the swarm. - `Swarms`: a collection of swarms. ``` $ tree ./src/ ./src/ ├── lib.rs ├── swarm.rs └── swarms.rs 1 directory, 3 files ``` ACKs for top commit: josecelano: ACK 728de22 Tree-SHA512: ffe9e0cd02cb18dc657c3ec5f378ed4a17b982dfef06aed5f0274e6135d54c12fba156d8a5290c5b749ed743eca01cb3df9bcfa4d613eb1e64e2528f958e2ad6
2 parents e1fd309 + 728de22 commit c68570c

File tree

22 files changed

+962
-598
lines changed

22 files changed

+962
-598
lines changed

packages/axum-http-tracker-server/tests/server/asserts.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub fn assert_bencoded_error(response_text: &String, expected_failure_reason: &s
2222
);
2323
}
2424

25+
#[allow(dead_code)]
2526
pub async fn assert_empty_announce_response(response: Response) {
2627
assert_eq!(response.status(), 200);
2728
let announce_response: Announce = serde_bencode::from_str(&response.text().await.unwrap()).unwrap();

packages/axum-http-tracker-server/tests/server/requests/announce.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ impl QueryBuilder {
126126
self
127127
}
128128

129+
pub fn with_port(mut self, port: u16) -> Self {
130+
self.announce_query.port = port;
131+
self
132+
}
133+
129134
pub fn without_compact(mut self) -> Self {
130135
self.announce_query.compact = None;
131136
self

packages/axum-http-tracker-server/tests/server/v1/contract.rs

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ mod for_all_config_modes {
105105
use crate::common::fixtures::invalid_info_hashes;
106106
use crate::server::asserts::{
107107
assert_announce_response, assert_bad_announce_request_error_response, assert_cannot_parse_query_param_error_response,
108-
assert_cannot_parse_query_params_error_response, assert_compact_announce_response, assert_empty_announce_response,
109-
assert_is_announce_response, assert_missing_query_params_for_announce_request_error_response,
108+
assert_cannot_parse_query_params_error_response, assert_compact_announce_response, assert_is_announce_response,
109+
assert_missing_query_params_for_announce_request_error_response,
110110
};
111111
use crate::server::client::Client;
112112
use crate::server::requests::announce::{Compact, QueryBuilder};
@@ -559,27 +559,53 @@ mod for_all_config_modes {
559559
}
560560

561561
#[tokio::test]
562-
async fn should_consider_two_peers_to_be_the_same_when_they_have_the_same_peer_id_even_if_the_ip_is_different() {
562+
async fn should_consider_two_peers_to_be_the_same_when_they_have_the_same_socket_address_even_if_the_peer_id_is_different(
563+
) {
563564
logging::setup();
564565

565566
let env = Started::new(&configuration::ephemeral_public().into()).await;
566567

567568
let info_hash = InfoHash::from_str("9c38422213e30bff212b30c360d26f9a02136422").unwrap(); // DevSkim: ignore DS173237
568569
let peer = PeerBuilder::default().build();
569570

570-
// Add a peer
571-
env.add_torrent_peer(&info_hash, &peer);
572-
573-
let announce_query = QueryBuilder::default()
571+
let announce_query_1 = QueryBuilder::default()
574572
.with_info_hash(&info_hash)
575573
.with_peer_id(&peer.peer_id)
574+
.with_peer_addr(&peer.peer_addr.ip())
575+
.with_port(peer.peer_addr.port())
576+
.query();
577+
578+
let announce_query_2 = QueryBuilder::default()
579+
.with_info_hash(&info_hash)
580+
.with_peer_id(&PeerId(*b"-qB00000000000000002")) // Different peer ID
581+
.with_peer_addr(&peer.peer_addr.ip())
582+
.with_port(peer.peer_addr.port())
576583
.query();
577584

578-
assert_ne!(peer.peer_addr.ip(), announce_query.peer_addr);
585+
// Same peer socket address
586+
assert_eq!(announce_query_1.peer_addr, announce_query_2.peer_addr);
587+
assert_eq!(announce_query_1.port, announce_query_2.port);
588+
589+
// Different peer ID
590+
assert_ne!(announce_query_1.peer_id, announce_query_2.peer_id);
579591

580-
let response = Client::new(*env.bind_address()).announce(&announce_query).await;
592+
let _response = Client::new(*env.bind_address()).announce(&announce_query_1).await;
593+
let response = Client::new(*env.bind_address()).announce(&announce_query_2).await;
581594

582-
assert_empty_announce_response(response).await;
595+
let announce_policy = env.container.tracker_core_container.core_config.announce_policy;
596+
597+
// The response should contain only the first peer.
598+
assert_announce_response(
599+
response,
600+
&Announce {
601+
complete: 1,
602+
incomplete: 0,
603+
interval: announce_policy.interval,
604+
min_interval: announce_policy.interval_min,
605+
peers: vec![],
606+
},
607+
)
608+
.await;
583609

584610
env.stop().await;
585611
}

packages/primitives/src/swarm_metadata.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use derive_more::Constructor;
77
/// Swarm metadata dictionary in the scrape response.
88
///
99
/// See [BEP 48: Tracker Protocol Extension: Scrape](https://www.bittorrent.org/beps/bep_0048.html)
10-
#[derive(Copy, Clone, Debug, PartialEq, Default, Constructor)]
10+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Constructor)]
1111
pub struct SwarmMetadata {
1212
/// (i.e `completed`): The number of peers that have ever completed
1313
/// downloading a given torrent.
@@ -27,6 +27,21 @@ impl SwarmMetadata {
2727
pub fn zeroed() -> Self {
2828
Self::default()
2929
}
30+
31+
#[must_use]
32+
pub fn downloads(&self) -> u32 {
33+
self.downloaded
34+
}
35+
36+
#[must_use]
37+
pub fn seeders(&self) -> u32 {
38+
self.complete
39+
}
40+
41+
#[must_use]
42+
pub fn leechers(&self) -> u32 {
43+
self.incomplete
44+
}
3045
}
3146

3247
/// Structure that holds aggregate swarm metadata.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/.coverage/

packages/torrent-repository/README.md

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,16 @@
22

33
A library to provide a torrent repository to the [Torrust Tracker](https://github.com/torrust/torrust-tracker).
44

5-
## Benchmarking
6-
7-
```console
8-
cargo bench -p torrust-tracker-torrent-repository
9-
```
10-
11-
Example partial output:
12-
13-
```output
14-
Running benches/repository_benchmark.rs (target/release/deps/repository_benchmark-a9b0013c8d09c3c3)
15-
add_one_torrent/RwLockStd
16-
time: [63.057 ns 63.242 ns 63.506 ns]
17-
Found 12 outliers among 100 measurements (12.00%)
18-
2 (2.00%) low severe
19-
2 (2.00%) low mild
20-
2 (2.00%) high mild
21-
6 (6.00%) high severe
22-
add_one_torrent/RwLockStdMutexStd
23-
time: [62.505 ns 63.077 ns 63.817 ns]
24-
```
5+
Its main responsibilities include:
6+
7+
- Managing Torrent Entries: It stores, retrieves, and manages torrent entries, which are torrents being tracked.
8+
- Persistence: It supports lading tracked torrents from a persistent storage, ensuring that torrent data can be restored across restarts.
9+
- Pagination and sorting: It provides paginated and stable/sorted access to torrent entries.
10+
- Peer management: It manages peers associated with torrents, including removing inactive peers and handling torrents with no peers (peerless torrents).
11+
- Policy handling: It supports different policies for handling torrents, such as persisting, removing, or custom policies for torrents with no peers.
12+
- Metrics: It can provide metrics about the torrents, such as counts or statuses, likely for monitoring or statistics.
13+
14+
This repo is a core component for managing the state and lifecycle of torrents and their peers in a BitTorrent tracker, with peer management, and flexible policies.
2515

2616
## Documentation
2717

packages/torrent-repository/src/entry/mod.rs

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)