diff --git a/Cargo.lock b/Cargo.lock index b302ac7..2adbbd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -428,7 +428,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.0", "event-listener-strategy", "pin-project-lite", ] @@ -646,9 +646,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.23" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "9560b07a799281c7e0958b9296854d6fafd4c5f31444a7e5bb1ad6dde5ccf1bd" dependencies = [ "clap_builder", "clap_derive", @@ -656,9 +656,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "874e0dd3eb68bf99058751ac9712f622e61e6f393a94f7128fa26e3f02f5c7cd" dependencies = [ "anstream", "anstyle", @@ -668,9 +668,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck", "proc-macro2", @@ -951,9 +951,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "5.3.1" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" dependencies = [ "concurrent-queue", "parking", @@ -966,7 +966,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.0", "pin-project-lite", ] @@ -1688,9 +1688,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" @@ -2119,7 +2119,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.9", + "thiserror 2.0.10", "tokio", "tracing", ] @@ -2138,7 +2138,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.9", + "thiserror 2.0.10", "tinyvec", "tracing", "web-time", @@ -2393,9 +2393,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.42" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ "bitflags", "errno", @@ -2493,9 +2493,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -2509,9 +2509,9 @@ checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "sentry" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016958f51b96861dead7c1e02290f138411d05e94fad175c8636a835dee6e51e" +checksum = "3a7332159e544e34db06b251b1eda5e546bd90285c3f58d9c8ff8450b484e0da" dependencies = [ "httpdate", "native-tls", @@ -2530,9 +2530,9 @@ dependencies = [ [[package]] name = "sentry-actix" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8c2610e32ab81cc376b6b4310101cff6636063b12f3f993884d0a8ec81c6187" +checksum = "4df26563afddf6fa2e158def69d70bbc2e60bd2b158ea6077a0f51358da31806" dependencies = [ "actix-web", "futures-util", @@ -2541,9 +2541,9 @@ dependencies = [ [[package]] name = "sentry-backtrace" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57712c24e99252ef175b4b06c485294f10ad6bc5b5e1567ff3803ee7a0b7d3f" +checksum = "565ec31ad37bab8e6d9f289f34913ed8768347b133706192f10606dabd5c6bc4" dependencies = [ "backtrace", "once_cell", @@ -2553,9 +2553,9 @@ dependencies = [ [[package]] name = "sentry-contexts" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba8754ec3b9279e00aa6d64916f211d44202370a1699afde1db2c16cbada089" +checksum = "e860275f25f27e8c0c7726ce116c7d5c928c5bba2ee73306e52b20a752298ea6" dependencies = [ "hostname", "libc", @@ -2567,9 +2567,9 @@ dependencies = [ [[package]] name = "sentry-core" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9f8b6dcd4fbae1e3e22b447f32670360b27e31b62ab040f7fb04e0f80c04d92" +checksum = "653942e6141f16651273159f4b8b1eaeedf37a7554c00cd798953e64b8a9bf72" dependencies = [ "once_cell", "rand", @@ -2580,9 +2580,9 @@ dependencies = [ [[package]] name = "sentry-debug-images" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8982a69133d3f5e4efdbfa0776937fca43c3a2e275a8fe184f50b1b0aa92e07c" +checksum = "2a60bc2154e6df59beed0ac13d58f8dfaf5ad20a88548a53e29e4d92e8e835c2" dependencies = [ "findshlibs", "once_cell", @@ -2591,9 +2591,9 @@ dependencies = [ [[package]] name = "sentry-panic" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de296dae6f01e931b65071ee5fe28d66a27909857f744018f107ed15fd1f6b25" +checksum = "105e3a956c8aa9dab1e4087b1657b03271bfc49d838c6ae9bfc7c58c802fd0ef" dependencies = [ "sentry-backtrace", "sentry-core", @@ -2601,9 +2601,9 @@ dependencies = [ [[package]] name = "sentry-tracing" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "263f73c757ed7915d3e1e34625eae18cad498a95b4261603d4ce3f87b159a6f0" +checksum = "64e75c831b4d8b34a5aec1f65f67c5d46a26c7c5d3c7abd8b5ef430796900cf8" dependencies = [ "sentry-backtrace", "sentry-core", @@ -2613,9 +2613,9 @@ dependencies = [ [[package]] name = "sentry-types" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a71ed3a389948a6a6d92b98e997a2723ca22f09660c5a7b7388ecd509a70a527" +checksum = "2d4203359e60724aa05cf2385aaf5d4f147e837185d7dd2b9ccf1ee77f4420c8" dependencies = [ "debugid", "hex", @@ -2814,7 +2814,7 @@ dependencies = [ "crc", "crossbeam-queue", "either", - "event-listener 5.3.1", + "event-listener 5.4.0", "futures-core", "futures-intrusive", "futures-io", @@ -2832,7 +2832,7 @@ dependencies = [ "serde_json", "sha2", "smallvec", - "thiserror 2.0.9", + "thiserror 2.0.10", "tokio", "tokio-stream", "tracing", @@ -2916,7 +2916,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.9", + "thiserror 2.0.10", "tracing", "whoami", ] @@ -2953,7 +2953,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.9", + "thiserror 2.0.10", "tracing", "whoami", ] @@ -3066,11 +3066,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.9" +version = "2.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +checksum = "a3ac7f54ca534db81081ef1c1e7f6ea8a3ef428d2fc069097c079443d24124d3" dependencies = [ - "thiserror-impl 2.0.9", + "thiserror-impl 2.0.10", ] [[package]] @@ -3086,9 +3086,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.9" +version = "2.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +checksum = "9e9465d30713b56a37ede7185763c3492a91be2f5fa68d958c44e41ab9248beb" dependencies = [ "proc-macro2", "quote", @@ -3163,9 +3163,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.42.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -3181,9 +3181,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", @@ -3289,7 +3289,7 @@ dependencies = [ [[package]] name = "torrust-actix" -version = "4.0.5" +version = "4.0.6" dependencies = [ "actix-cors", "actix-web", @@ -3318,7 +3318,7 @@ dependencies = [ "serde_millis", "sha1", "sqlx", - "thiserror 2.0.9", + "thiserror 2.0.10", "tokio", "tokio-shutdown", "toml 0.8.19", @@ -4089,7 +4089,7 @@ dependencies = [ "flate2", "indexmap", "memchr", - "thiserror 2.0.9", + "thiserror 2.0.10", "zopfli", ] diff --git a/Cargo.toml b/Cargo.toml index e9ebca5..559f2fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "torrust-actix" -version = "4.0.5" +version = "4.0.6" edition = "2021" license = "AGPL-3.0" authors = [ @@ -42,15 +42,15 @@ rcgen = "^0.13" regex = "^1.11" rustls = { version = "^0.23", default-features = false, features = ["std", "ring"] } rustls-pemfile = "^2.2" -sentry = { version = "^0.35", default-features = false, features = ["rustls", "backtrace", "contexts", "panic", "transport", "debug-images", "reqwest"] } -sentry-actix = "^0.35" +sentry = { version = "^0.36", default-features = false, features = ["rustls", "backtrace", "contexts", "panic", "transport", "debug-images", "reqwest"] } +sentry-actix = "^0.36" serde = { version = "^1.0", features = ["derive"] } serde_json = { version = "^1.0", features = ["preserve_order"] } serde_millis = "^0.1" sha1 = "^0.10" sqlx = { version = "^0.8", features = ["mysql", "postgres", "sqlite", "runtime-tokio-rustls"] } thiserror = "^2.0" -tokio = { version = "^1.41", features = ["full"] } +tokio = { version = "^1.43", features = ["full"] } tokio-shutdown = "^0.1" toml = "^0.8" utoipa = { version = "^5", features = ["actix_extras"] } diff --git a/README.md b/README.md index df7b467..88cc5c2 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,12 @@ Sentry.io support is introduced, you can enable it in the configuration and the ### ChangeLog +#### v4.0.6 +* Fixed some clippy issues +* Found a performance issue on peers cleanup +* Switched peers cleanup from Tokio spawn to Thread spawn for speedup +* Bumped version of Tokio + #### v4.0.5 * Library bump diff --git a/docker/Dockerfile b/docker/Dockerfile index efb6281..c8b909c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -2,7 +2,7 @@ FROM rust:alpine RUN apk add git musl-dev curl pkgconfig openssl-dev openssl-libs-static RUN git clone https://github.com/Power2All/torrust-actix.git /tmp/torrust-actix -RUN cd /tmp/torrust-actix && git checkout tags/v4.0.5 +RUN cd /tmp/torrust-actix && git checkout tags/v4.0.6 WORKDIR /tmp/torrust-actix RUN cd /tmp/torrust-actix RUN cargo build --release && rm -Rf target/release/.fingerprint target/release/build target/release/deps target/release/examples target/release/incremental diff --git a/src/main.rs b/src/main.rs index a8d9180..771bf73 100644 --- a/src/main.rs +++ b/src/main.rs @@ -229,7 +229,7 @@ fn main() -> std::io::Result<()> } info!("[PEERS] Checking now for dead peers."); - let _ = tracker_spawn_cleanup_peers.torrent_peers_cleanup(Duration::from_secs(tracker_spawn_cleanup_peers.config.tracker_config.clone().peers_timeout), tracker_spawn_cleanup_peers.config.database.clone().persistent); + let _ = tracker_spawn_cleanup_peers.torrent_peers_cleanup(tracker_spawn_cleanup_peers.clone(), Duration::from_secs(tracker_spawn_cleanup_peers.config.tracker_config.clone().peers_timeout), tracker_spawn_cleanup_peers.config.database.clone().persistent).await; info!("[PEERS] Peers cleaned up."); if tracker_spawn_cleanup_peers.config.tracker_config.clone().users_enabled { diff --git a/src/tracker/impls/info_hash_visitor.rs b/src/tracker/impls/info_hash_visitor.rs index a13eafb..56fafc2 100644 --- a/src/tracker/impls/info_hash_visitor.rs +++ b/src/tracker/impls/info_hash_visitor.rs @@ -3,7 +3,7 @@ use std::fmt::Formatter; use crate::tracker::structs::info_hash::InfoHash; use crate::tracker::structs::info_hash_visitor::InfoHashVisitor; -impl<'v> serde::de::Visitor<'v> for InfoHashVisitor { +impl serde::de::Visitor<'_> for InfoHashVisitor { type Value = InfoHash; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { diff --git a/src/tracker/impls/peer_id_visitor.rs b/src/tracker/impls/peer_id_visitor.rs index adf8367..a0e375c 100644 --- a/src/tracker/impls/peer_id_visitor.rs +++ b/src/tracker/impls/peer_id_visitor.rs @@ -3,7 +3,7 @@ use std::fmt::Formatter; use crate::tracker::structs::peer_id::PeerId; use crate::tracker::structs::peer_id_visitor::PeerIdVisitor; -impl<'v> serde::de::Visitor<'v> for PeerIdVisitor { +impl serde::de::Visitor<'_> for PeerIdVisitor { type Value = PeerId; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { diff --git a/src/tracker/impls/torrent_tracker_peers.rs b/src/tracker/impls/torrent_tracker_peers.rs index daf6766..b2cafd0 100644 --- a/src/tracker/impls/torrent_tracker_peers.rs +++ b/src/tracker/impls/torrent_tracker_peers.rs @@ -1,6 +1,9 @@ use std::collections::BTreeMap; use std::collections::btree_map::Entry; use std::net::{IpAddr, SocketAddr}; +use std::sync::Arc; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::thread; use std::time::Duration; use log::info; use crate::common::structs::number_of_bytes::NumberOfBytes; @@ -198,6 +201,38 @@ impl TorrentTracker { } } + #[tracing::instrument(level = "debug")] + pub fn remove_torrent_peers(&self, shard: u8, peers: Vec<(InfoHash, PeerId)>, persistent: bool) -> Vec<(InfoHash, Option, Option)> + { + let mut return_data = vec![]; + let shard = self.torrents_sharding.clone().get_shard(shard).unwrap(); + let mut lock = shard.write(); + for (info_hash, peer_id) in peers { + match lock.entry(info_hash) { + Entry::Vacant(_) => { + return_data.push((info_hash, None, None)); + } + Entry::Occupied(mut o) => { + let previous_torrent = o.get().clone(); + if o.get_mut().seeds.remove(&peer_id).is_some() { + self.update_stats(StatsEvent::Seeds, -1); + }; + if o.get_mut().peers.remove(&peer_id).is_some() { + self.update_stats(StatsEvent::Peers, -1); + }; + if !persistent && o.get().seeds.is_empty() && o.get().peers.is_empty() { + lock.remove(&info_hash); + self.update_stats(StatsEvent::Torrents, -1); + return_data.push((info_hash, Some(previous_torrent), None)); + } else { + return_data.push((info_hash, Some(previous_torrent), Some(o.get().clone()))); + } + } + } + } + return_data + } + #[tracing::instrument(level = "debug")] pub fn remove_torrent_peer(&self, info_hash: InfoHash, peer_id: PeerId, persistent: bool) -> (Option, Option) { @@ -226,55 +261,61 @@ impl TorrentTracker { } #[tracing::instrument(level = "debug")] - pub fn torrent_peers_cleanup(&self, peer_timeout: Duration, persistent: bool) -> (u64, u64, u64) + pub async fn torrent_peers_cleanup(&self, torrent_tracker: Arc, peer_timeout: Duration, persistent: bool) { - let mut torrents_removed = 0u64; - let mut seeds_found = 0u64; - let mut peers_found = 0u64; + let torrents_removed = Arc::new(AtomicU64::new(0)); + let seeds_found = Arc::new(AtomicU64::new(0)); + let peers_found = Arc::new(AtomicU64::new(0)); + let mut threads = vec![]; for shard in 0u8..=255u8 { - let shard_data = self.torrents_sharding.get_shard_content(shard); + let torrent_tracker_clone = torrent_tracker.clone(); + let shard_data = torrent_tracker.torrents_sharding.get_shard_content(shard); if !shard_data.is_empty() { - for (info_hash, torrent_entry) in shard_data.iter() { - for (peer_id, torrent_peer) in torrent_entry.seeds.iter() { - if torrent_peer.updated.elapsed() > peer_timeout { - match self.remove_torrent_peer(*info_hash, *peer_id, persistent) { - (None, None) => { - torrents_removed += 1; - } - (previous, None) => { - torrents_removed += 1; - seeds_found += previous.clone().unwrap().seeds.len() as u64; - peers_found += previous.clone().unwrap().peers.len() as u64; - } - (previous, new) => { - seeds_found += previous.clone().unwrap().seeds.len() as u64 - new.clone().unwrap().seeds.len() as u64; - peers_found += previous.clone().unwrap().peers.len() as u64 - new.clone().unwrap().peers.len() as u64; - } + let torrents_removed_clone = torrents_removed.clone(); + let seeds_found_clone = seeds_found.clone(); + let peers_found_clone = peers_found.clone(); + threads.push(thread::spawn(move || { + let mut seeds = 0u64; + let mut peers = 0u64; + let mut remove_list = vec![]; + for (info_hash, torrent_entry) in shard_data.iter() { + for (peer_id, torrent_peer) in torrent_entry.seeds.iter() { + seeds += 1; + if torrent_peer.updated.elapsed() > peer_timeout { + remove_list.push((*info_hash, *peer_id)); + } + } + for (peer_id, torrent_peer) in torrent_entry.peers.iter() { + peers += 1; + if torrent_peer.updated.elapsed() > peer_timeout { + remove_list.push((*info_hash, *peer_id)); } } } - for (peer_id, torrent_peer) in torrent_entry.peers.iter() { - if torrent_peer.updated.elapsed() > peer_timeout { - match self.remove_torrent_peer(*info_hash, *peer_id, persistent) { - (None, None) => { - torrents_removed += 1; - } - (previous, None) => { - torrents_removed += 1; - seeds_found += previous.clone().unwrap().seeds.len() as u64; - peers_found += previous.clone().unwrap().peers.len() as u64; - } - (previous, new) => { - seeds_found += previous.clone().unwrap().seeds.len() as u64 - new.clone().unwrap().seeds.len() as u64; - peers_found += previous.clone().unwrap().peers.len() as u64 - new.clone().unwrap().peers.len() as u64; - } + for (_, previous, next) in torrent_tracker_clone.remove_torrent_peers(shard, remove_list, persistent).iter() { + match (previous, next) { + (None, None) => { + torrents_removed_clone.fetch_add(1, Ordering::SeqCst); + } + (previous, None) => { + torrents_removed_clone.fetch_add(1, Ordering::SeqCst); + seeds_found_clone.fetch_add(previous.clone().unwrap().seeds.len() as u64, Ordering::SeqCst); + peers_found_clone.fetch_add(previous.clone().unwrap().peers.len() as u64, Ordering::SeqCst); + } + (previous, new) => { + seeds_found_clone.fetch_add(previous.clone().unwrap().seeds.len() as u64 - new.clone().unwrap().seeds.len() as u64, Ordering::SeqCst); + peers_found_clone.fetch_add(previous.clone().unwrap().peers.len() as u64 - new.clone().unwrap().peers.len() as u64, Ordering::SeqCst); } } } - } + info!("[PEERS CLEANUP] Scanned {} seeds and {} peers", seeds, peers); + })); } } - info!("[PEERS CLEANUP] Removed {} torrents, {} seeds and {} peers", torrents_removed, seeds_found, peers_found); - (torrents_removed, seeds_found, peers_found) + for thread in threads.into_iter() { + thread.join().unwrap(); + } + + info!("[PEERS CLEANUP] Removed {} torrents, {} seeds and {} peers", torrents_removed.clone().load(Ordering::SeqCst), seeds_found.clone().load(Ordering::SeqCst), peers_found.clone().load(Ordering::SeqCst)); } } \ No newline at end of file diff --git a/src/tracker/impls/user_id_visitor.rs b/src/tracker/impls/user_id_visitor.rs index cb30908..3c1b3d5 100644 --- a/src/tracker/impls/user_id_visitor.rs +++ b/src/tracker/impls/user_id_visitor.rs @@ -3,7 +3,7 @@ use std::fmt::Formatter; use crate::tracker::structs::user_id::UserId; use crate::tracker::structs::user_id_visitor::UserIdVisitor; -impl<'v> serde::de::Visitor<'v> for UserIdVisitor { +impl serde::de::Visitor<'_> for UserIdVisitor { type Value = UserId; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {