Skip to content

Commit

Permalink
Merge #515: BEP 5. Persist metainfo field nodes
Browse files Browse the repository at this point in the history
7b9d5a4 feat: [#438] persist metainfo field nodes. BEP 5 (Jose Celano)

Pull request description:

  The field `nodes` was included in the `Torrent` struct but not persisted into or loaded from the database.

ACKs for top commit:
  josecelano:
    ACK 7b9d5a4

Tree-SHA512: 901054f1079c8ec17a9b45725dd4cc9d767ca81e6a477b6df163e6e4ec78d2f6861c9f024ed7d848ea29682da68ef3bbe8b4d5e25aa37c11561397cc373c4113
  • Loading branch information
josecelano committed Mar 4, 2024
2 parents 0cd58e4 + 7b9d5a4 commit 2e8bd5a
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS torrust_torrent_nodes (
node_id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
torrent_id INTEGER NOT NULL,
node_ip VARCHAR(256) NOT NULL,
node_port INTEGER NOT NULL,
FOREIGN KEY(torrent_id) REFERENCES torrust_torrents(torrent_id) ON DELETE CASCADE
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS torrust_torrent_nodes (
node_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
torrent_id INTEGER NOT NULL,
node_ip TEXT NOT NULL,
node_port INTEGER NOT NULL,
FOREIGN KEY(torrent_id) REFERENCES torrust_torrents(torrent_id) ON DELETE CASCADE
)
2 changes: 1 addition & 1 deletion share/default/config/index.development.sqlite3.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
log_level = "info"
log_level = "debug"

[website]
name = "Torrust"
Expand Down
9 changes: 9 additions & 0 deletions src/databases/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,14 @@ pub trait Database: Sync + Send {

let torrent_http_seed_urls = self.get_torrent_http_seed_urls_from_id(db_torrent.torrent_id).await?;

let torrent_nodes = self.get_torrent_nodes_from_id(db_torrent.torrent_id).await?;

Ok(Torrent::from_database(
&db_torrent,
&torrent_files,
torrent_announce_urls,
torrent_http_seed_urls,
torrent_nodes,
))
}

Expand All @@ -226,11 +229,14 @@ pub trait Database: Sync + Send {

let torrent_http_seed_urls = self.get_torrent_http_seed_urls_from_id(db_torrent.torrent_id).await?;

let torrent_nodes = self.get_torrent_nodes_from_id(db_torrent.torrent_id).await?;

Ok(Torrent::from_database(
&db_torrent,
&torrent_files,
torrent_announce_urls,
torrent_http_seed_urls,
torrent_nodes,
))
}

Expand Down Expand Up @@ -274,6 +280,9 @@ pub trait Database: Sync + Send {
/// Get all torrent's HTTP seed urls as `Vec<Vec<String>>` from `torrent_id`.
async fn get_torrent_http_seed_urls_from_id(&self, torrent_id: i64) -> Result<Vec<String>, Error>;

/// Get all torrent's nodes as `Vec<(String, i64)>` from `torrent_id`.
async fn get_torrent_nodes_from_id(&self, torrent_id: i64) -> Result<Vec<(String, i64)>, Error>;

/// Get `TorrentListing` from `torrent_id`.
async fn get_torrent_listing_from_id(&self, torrent_id: i64) -> Result<TorrentListing, Error>;

Expand Down
38 changes: 37 additions & 1 deletion src/databases/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use crate::models::category::CategoryId;
use crate::models::info_hash::InfoHash;
use crate::models::response::TorrentsResponse;
use crate::models::torrent::{Metadata, TorrentListing};
use crate::models::torrent_file::{DbTorrent, DbTorrentAnnounceUrl, DbTorrentFile, DbTorrentHttpSeedUrl, Torrent, TorrentFile};
use crate::models::torrent_file::{
DbTorrent, DbTorrentAnnounceUrl, DbTorrentFile, DbTorrentHttpSeedUrl, DbTorrentNode, Torrent, TorrentFile,
};
use crate::models::torrent_tag::{TagId, TorrentTag};
use crate::models::tracker_key::TrackerKey;
use crate::models::user::{User, UserAuthentication, UserCompact, UserId, UserProfile};
Expand Down Expand Up @@ -606,6 +608,31 @@ impl Database for Mysql {
return Err(e);
}

// add nodes

let insert_torrent_nodes_result: Result<(), database::Error> = if let Some(nodes) = &torrent.nodes {
for node in nodes {
let () = query("INSERT INTO torrust_torrent_nodes (torrent_id, node_ip, node_port) VALUES (?, ?, ?)")
.bind(torrent_id)
.bind(node.0.clone())
.bind(node.1)
.execute(&mut *tx)
.await
.map(|_| ())
.map_err(|_| database::Error::Error)?;
}

Ok(())
} else {
Ok(())
};

// rollback transaction on error
if let Err(e) = insert_torrent_nodes_result {
drop(tx.rollback().await);
return Err(e);
}

// add tags

for tag_id in &metadata.tags {
Expand Down Expand Up @@ -773,6 +800,15 @@ impl Database for Mysql {
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_nodes_from_id(&self, torrent_id: i64) -> Result<Vec<(String, i64)>, database::Error> {
query_as::<_, DbTorrentNode>("SELECT node_ip, node_port FROM torrust_torrent_nodes WHERE torrent_id = ?")
.bind(torrent_id)
.fetch_all(&self.pool)
.await
.map(|v| v.iter().map(|a| (a.node_ip.to_string(), a.node_port)).collect())
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_listing_from_id(&self, torrent_id: i64) -> Result<TorrentListing, database::Error> {
query_as::<_, TorrentListing>(
"SELECT
Expand Down
38 changes: 37 additions & 1 deletion src/databases/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use crate::models::category::CategoryId;
use crate::models::info_hash::InfoHash;
use crate::models::response::TorrentsResponse;
use crate::models::torrent::{Metadata, TorrentListing};
use crate::models::torrent_file::{DbTorrent, DbTorrentAnnounceUrl, DbTorrentFile, DbTorrentHttpSeedUrl, Torrent, TorrentFile};
use crate::models::torrent_file::{
DbTorrent, DbTorrentAnnounceUrl, DbTorrentFile, DbTorrentHttpSeedUrl, DbTorrentNode, Torrent, TorrentFile,
};
use crate::models::torrent_tag::{TagId, TorrentTag};
use crate::models::tracker_key::TrackerKey;
use crate::models::user::{User, UserAuthentication, UserCompact, UserId, UserProfile};
Expand Down Expand Up @@ -600,6 +602,31 @@ impl Database for Sqlite {
return Err(e);
}

// add nodes

let insert_torrent_nodes_result: Result<(), database::Error> = if let Some(nodes) = &torrent.nodes {
for node in nodes {
let () = query("INSERT INTO torrust_torrent_nodes (torrent_id, node_ip, node_port) VALUES (?, ?, ?)")
.bind(torrent_id)
.bind(node.0.clone())
.bind(node.1)
.execute(&mut *tx)
.await
.map(|_| ())
.map_err(|_| database::Error::Error)?;
}

Ok(())
} else {
Ok(())
};

// rollback transaction on error
if let Err(e) = insert_torrent_nodes_result {
drop(tx.rollback().await);
return Err(e);
}

// add tags

for tag_id in &metadata.tags {
Expand Down Expand Up @@ -767,6 +794,15 @@ impl Database for Sqlite {
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_nodes_from_id(&self, torrent_id: i64) -> Result<Vec<(String, i64)>, database::Error> {
query_as::<_, DbTorrentNode>("SELECT node_ip, node_port FROM torrust_torrent_nodes WHERE torrent_id = ?")
.bind(torrent_id)
.fetch_all(&self.pool)
.await
.map(|v| v.iter().map(|a| (a.node_ip.to_string(), a.node_port)).collect())
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_listing_from_id(&self, torrent_id: i64) -> Result<TorrentListing, database::Error> {
query_as::<_, TorrentListing>(
"SELECT
Expand Down
9 changes: 8 additions & 1 deletion src/models/torrent_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ impl Torrent {
torrent_files: &[TorrentFile],
torrent_announce_urls: Vec<Vec<String>>,
torrent_http_seed_urls: Vec<String>,
torrent_nodes: Vec<(String, i64)>,
) -> Self {
let info_dict = TorrentInfoDictionary::with(
&db_torrent.name,
Expand All @@ -88,7 +89,7 @@ impl Torrent {
Self {
info: info_dict,
announce: None,
nodes: None,
nodes: if torrent_nodes.is_empty() { None } else { Some(torrent_nodes) },
encoding: db_torrent.encoding.clone(),
httpseeds: if torrent_http_seed_urls.is_empty() {
None
Expand Down Expand Up @@ -359,6 +360,12 @@ pub struct DbTorrentHttpSeedUrl {
pub seed_url: String,
}

#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
pub struct DbTorrentNode {
pub node_ip: String,
pub node_port: i64,
}

#[cfg(test)]
mod tests {

Expand Down

0 comments on commit 2e8bd5a

Please sign in to comment.