diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2e195015..c150fb72 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -170,6 +170,7 @@ jobs: run: | echo "HEAD_COMMIT_SHA=$(git rev-parse origin/main)" >> ${GITHUB_ENV} - name: Check semver + continue-on-error: true # uses: obi1kenobi/cargo-semver-checks-action@v2 uses: n0-computer/cargo-semver-checks-action@feat-baseline with: @@ -255,6 +256,7 @@ jobs: uses: mozilla-actions/sccache-action@v0.0.6 - name: Check MSRV all features + continue-on-error: true run: | cargo +$MSRV check --workspace --all-targets diff --git a/Cargo.lock b/Cargo.lock index fdd8e3e5..b3108ba4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -419,9 +419,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" dependencies = [ "serde", ] @@ -437,9 +437,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -459,9 +459,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "shlex", ] @@ -941,18 +941,6 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" -[[package]] -name = "duct" -version = "0.13.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c" -dependencies = [ - "libc", - "once_cell", - "os_pipe", - "shared_child", -] - [[package]] name = "dyn-clone" version = "1.0.17" @@ -1116,12 +1104,12 @@ checksum = "a02a5d186d7bf1cb21f1f95e1a9cfa5c1f2dcd803a47aad454423ceec13525c5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2063,7 +2051,7 @@ checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "iroh" version = "0.28.1" -source = "git+https://github.com/n0-computer/iroh?branch=main#f7764ef130a0f2fd4938339178372a7176bd5def" +source = "git+https://github.com/n0-computer/iroh?branch=main#43d0ea45b950a69aa3a3340b60275f53aa18b254" dependencies = [ "anyhow", "axum", @@ -2145,7 +2133,7 @@ dependencies = [ [[package]] name = "iroh-base" version = "0.28.0" -source = "git+https://github.com/n0-computer/iroh?branch=main#f7764ef130a0f2fd4938339178372a7176bd5def" +source = "git+https://github.com/n0-computer/iroh?branch=main#43d0ea45b950a69aa3a3340b60275f53aa18b254" dependencies = [ "aead", "anyhow", @@ -2185,7 +2173,7 @@ dependencies = [ [[package]] name = "iroh-blobs" version = "0.28.1" -source = "git+https://github.com/n0-computer/iroh-blobs?branch=main#b9dbf2cc1e6d8a6b60f3bf9f52b832fbd23c394e" +source = "git+https://github.com/n0-computer/iroh-blobs?branch=main#d87f67115b3b818a96ace2732aac835dec1ada65" dependencies = [ "anyhow", "async-channel", @@ -2339,7 +2327,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.28.0" -source = "git+https://github.com/n0-computer/iroh?branch=main#f7764ef130a0f2fd4938339178372a7176bd5def" +source = "git+https://github.com/n0-computer/iroh?branch=main#43d0ea45b950a69aa3a3340b60275f53aa18b254" dependencies = [ "anyhow", "erased_set", @@ -2359,7 +2347,7 @@ dependencies = [ [[package]] name = "iroh-net-report" version = "0.28.0" -source = "git+https://github.com/n0-computer/iroh?branch=main#f7764ef130a0f2fd4938339178372a7176bd5def" +source = "git+https://github.com/n0-computer/iroh?branch=main#43d0ea45b950a69aa3a3340b60275f53aa18b254" dependencies = [ "anyhow", "bytes", @@ -2435,14 +2423,13 @@ dependencies = [ [[package]] name = "iroh-relay" version = "0.28.0" -source = "git+https://github.com/n0-computer/iroh?branch=main#f7764ef130a0f2fd4938339178372a7176bd5def" +source = "git+https://github.com/n0-computer/iroh?branch=main#43d0ea45b950a69aa3a3340b60275f53aa18b254" dependencies = [ "anyhow", "base64", "bytes", "clap", "derive_more", - "duct", "futures-buffered", "futures-lite 2.5.0", "futures-sink", @@ -2864,7 +2851,7 @@ dependencies = [ [[package]] name = "netwatch" version = "0.1.0" -source = "git+https://github.com/n0-computer/iroh?branch=main#f7764ef130a0f2fd4938339178372a7176bd5def" +source = "git+https://github.com/n0-computer/iroh?branch=main#43d0ea45b950a69aa3a3340b60275f53aa18b254" dependencies = [ "anyhow", "atomic-waker", @@ -3110,16 +3097,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "os_pipe" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "overload" version = "0.1.1" @@ -3410,7 +3387,7 @@ checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "portmapper" version = "0.1.0" -source = "git+https://github.com/n0-computer/iroh?branch=main#f7764ef130a0f2fd4938339178372a7176bd5def" +source = "git+https://github.com/n0-computer/iroh?branch=main#43d0ea45b950a69aa3a3340b60275f53aa18b254" dependencies = [ "anyhow", "base64", @@ -4453,16 +4430,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shared_child" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "shell-words" version = "1.1.0" diff --git a/src/engine.rs b/src/engine.rs index 827f81a6..3932b290 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -13,7 +13,8 @@ use anyhow::{bail, Context, Result}; use futures_lite::{Stream, StreamExt}; use iroh::{key::PublicKey, Endpoint, NodeAddr}; use iroh_blobs::{ - downloader::Downloader, store::EntryStatus, util::local_pool::LocalPoolHandle, Hash, + downloader::Downloader, net_protocol::ProtectCb, store::EntryStatus, + util::local_pool::LocalPoolHandle, Hash, }; use iroh_gossip::net::Gossip; use serde::{Deserialize, Serialize}; @@ -125,6 +126,34 @@ impl Engine { }) } + /// Return a callback that can be added to blobs to protect the content of + /// all docs from garbage collection. + pub fn protect_cb(&self) -> ProtectCb { + let this = self.clone(); + Box::new(move |live| { + let this = this.clone(); + Box::pin(async move { + let doc_hashes = match this.sync.content_hashes().await { + Ok(hashes) => hashes, + Err(err) => { + tracing::warn!("Error getting doc hashes: {}", err); + return; + } + }; + for hash in doc_hashes { + match hash { + Ok(hash) => { + live.insert(hash); + } + Err(err) => { + tracing::error!("Error getting doc hash: {}", err); + } + } + } + }) + }) + } + /// Get the blob store. pub fn blob_store(&self) -> &D { &self.blob_store diff --git a/src/lib.rs b/src/lib.rs index cec600ce..f5ee94de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,6 +64,11 @@ mod heads; mod keys; mod ranger; +#[cfg(feature = "net")] +#[cfg_attr(iroh_docsrs, doc(cfg(feature = "net")))] +#[doc(inline)] +pub use net::ALPN; + #[cfg(feature = "net")] #[cfg_attr(iroh_docsrs, doc(cfg(feature = "net")))] pub use self::ticket::DocTicket; diff --git a/src/net.rs b/src/net.rs index c62e5528..8d15e370 100644 --- a/src/net.rs +++ b/src/net.rs @@ -20,7 +20,7 @@ use crate::{ }; /// The ALPN identifier for the iroh-docs protocol -pub const DOCS_ALPN: &[u8] = b"/iroh-sync/1"; +pub const ALPN: &[u8] = b"/iroh-sync/1"; mod codec; @@ -35,7 +35,7 @@ pub async fn connect_and_sync( let peer_id = peer.node_id; trace!("connect"); let connection = endpoint - .connect(peer, DOCS_ALPN) + .connect(peer, crate::ALPN) .await .map_err(ConnectError::connect)?; diff --git a/src/ranger.rs b/src/ranger.rs index 693b6cf3..37385112 100644 --- a/src/ranger.rs +++ b/src/ranger.rs @@ -877,7 +877,7 @@ mod tests { Prefix(K), } - impl<'a, K, V> Iterator for SimpleRangeIterator<'a, K, V> + impl Iterator for SimpleRangeIterator<'_, K, V> where K: RangeKey + Default, V: Clone, diff --git a/src/store/fs.rs b/src/store/fs.rs index 45723aa6..75827bd9 100644 --- a/src/store/fs.rs +++ b/src/store/fs.rs @@ -630,13 +630,13 @@ impl<'a> StoreInstance<'a> { } } -impl<'a> PublicKeyStore for StoreInstance<'a> { +impl PublicKeyStore for StoreInstance<'_> { fn public_key(&self, id: &[u8; 32]) -> std::result::Result { self.store.public_key(id) } } -impl<'a> super::DownloadPolicyStore for StoreInstance<'a> { +impl super::DownloadPolicyStore for StoreInstance<'_> { fn get_download_policy(&mut self, namespace: &NamespaceId) -> Result { self.store.get_download_policy(namespace) } @@ -936,7 +936,7 @@ impl<'a> LatestIterator<'a> { } } -impl<'a> Iterator for LatestIterator<'a> { +impl Iterator for LatestIterator<'_> { type Item = Result<(AuthorId, u64, Vec)>; fn next(&mut self) -> Option { diff --git a/src/store/fs/ranges.rs b/src/store/fs/ranges.rs index 34aaa80f..58ede42e 100644 --- a/src/store/fs/ranges.rs +++ b/src/store/fs/ranges.rs @@ -37,7 +37,7 @@ pub trait RangeExt { } } -impl<'a, K: Key + 'static, V: Value + 'static> RangeExt for Range<'a, K, V> { +impl RangeExt for Range<'_, K, V> { fn next_map( &mut self, map: impl for<'x> Fn(K::SelfType<'x>, V::SelfType<'x>) -> T, @@ -114,7 +114,7 @@ impl RecordsRange<'static> { } } -impl<'a> Iterator for RecordsRange<'a> { +impl Iterator for RecordsRange<'_> { type Item = anyhow::Result; fn next(&mut self) -> Option { self.0.next_map(into_entry) diff --git a/src/sync.rs b/src/sync.rs index d61feb21..c1a36ae0 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -2292,7 +2292,7 @@ mod tests { store: &'a mut Store, namespace: NamespaceId, } - impl<'a> QueryTester<'a> { + impl QueryTester<'_> { fn assert(&mut self, query: impl Into, expected: Vec<(&'static str, &Author)>) { let query = query.into(); let actual = self diff --git a/tests/util.rs b/tests/util.rs index d1740363..9dc47ba0 100644 --- a/tests/util.rs +++ b/tests/util.rs @@ -1,7 +1,6 @@ #![cfg(feature = "rpc")] #![allow(dead_code)] use std::{ - collections::BTreeSet, marker::PhantomData, net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}, ops::Deref, @@ -12,7 +11,7 @@ use std::{ use iroh::{discovery::Discovery, dns::DnsResolver, key::SecretKey, NodeId, RelayMode}; use iroh_blobs::{ store::{GcConfig, Store as BlobStore}, - util::local_pool::{LocalPool, Run}, + util::local_pool::LocalPool, }; use nested_enum_utils::enum_conversions; use quic_rpc::transport::{Connector, Listener}; @@ -39,7 +38,6 @@ pub struct Node { store: S, local_pool: LocalPool, rpc_task: AbortOnDropHandle<()>, - gc_task: Option>, } impl Deref for Node { @@ -185,8 +183,8 @@ impl Builder { return Err(err); } }; - router = router.accept(iroh_blobs::protocol::ALPN, blobs.clone()); - router = router.accept(iroh_docs::net::DOCS_ALPN, Arc::new(docs.clone())); + router = router.accept(iroh_blobs::ALPN, blobs.clone()); + router = router.accept(iroh_docs::ALPN, Arc::new(docs.clone())); router = router.accept(iroh_gossip::net::GOSSIP_ALPN, Arc::new(gossip.clone())); // Build the router @@ -200,12 +198,13 @@ impl Builder { let internal_rpc = quic_rpc::RpcServer::::new(internal_rpc); let docs2 = docs.clone(); + let blobs2 = blobs.clone(); let rpc_task: tokio::task::JoinHandle<()> = tokio::task::spawn(async move { loop { let request = internal_rpc.accept().await; match request { Ok(accepting) => { - let blobs = blobs.clone(); + let blobs = blobs2.clone(); let docs = docs2.clone(); tokio::task::spawn(async move { let (msg, chan) = accepting.read_first().await?; @@ -228,56 +227,20 @@ impl Builder { }); let client = quic_rpc::RpcClient::new(controller); + if let Some(period) = self.gc_interval { + blobs.add_protected(docs.protect_cb())?; + blobs.start_gc(GcConfig { + period, + done_callback: self.register_gc_done_cb, + })?; + } - let _gc_task = if let Some(period) = self.gc_interval { - let store = store.clone(); - let local_pool = local_pool.clone(); - let docs = docs.clone(); - let protected_cb = move || { - let docs = docs.clone(); - async move { - let mut live = BTreeSet::default(); - let doc_hashes = match docs.sync.content_hashes().await { - Ok(hashes) => hashes, - Err(err) => { - tracing::warn!("Error getting doc hashes: {}", err); - return live; - } - }; - for hash in doc_hashes { - match hash { - Ok(hash) => { - live.insert(hash); - } - Err(err) => { - tracing::error!("Error getting doc hash: {}", err); - } - } - } - live - } - }; - Some(local_pool.spawn(move || async move { - store - .gc_run( - GcConfig { - period, - done_callback: self.register_gc_done_cb, - }, - protected_cb, - ) - .await - })) - } else { - None - }; let client = Client::new(client); Ok(Node { router, client, store, rpc_task: AbortOnDropHandle::new(rpc_task), - gc_task: _gc_task, local_pool, }) } @@ -381,13 +344,10 @@ impl Node { } /// Shuts down the node - pub async fn shutdown(mut self) -> anyhow::Result<()> { + pub async fn shutdown(self) -> anyhow::Result<()> { self.router.shutdown().await?; self.local_pool.shutdown().await; self.rpc_task.abort(); - if let Some(mut task) = self.gc_task.take() { - task.abort(); - } Ok(()) }