diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..226dec961 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[target.wasm32-unknown-unknown] +runner = "wasm-bindgen-test-runner" +rustflags = ['--cfg', 'getrandom_backend="wasm_js"'] diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b2a48b5e4..7a3eac76c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -277,3 +277,40 @@ jobs: - uses: actions/checkout@v5 - run: pip install --user codespell[toml] - run: codespell --ignore-words-list=ans,atmost,crate,inout,ratatui,ser,stayin,swarmin,worl --skip=CHANGELOG.md + + wasm_build: + name: Build & test wasm32 + runs-on: ubuntu-latest + env: + RUSTFLAGS: '--cfg getrandom_backend="wasm_js"' + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install stable toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Add wasm target + run: rustup target add wasm32-unknown-unknown + + - name: Install wasm-tools + uses: bytecodealliance/actions/wasm-tools/setup@v1 + + - name: Install wasm-pack + uses: taiki-e/install-action@v2 + with: + tool: wasm-bindgen,wasm-pack + + - name: wasm32 build + run: cargo build --target wasm32-unknown-unknown --no-default-features + + # If the Wasm file contains any 'import "env"' declarations, then + # some non-Wasm-compatible code made it into the final code. + - name: Ensure no 'import "env"' in wasm + run: | + ! wasm-tools print --skeleton target/wasm32-unknown-unknown/debug/iroh_blobs.wasm | grep 'import "env"' \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 76a37d681..518ff0a99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -259,8 +259,7 @@ dependencies = [ [[package]] name = "bao-tree" version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff16d65e48353db458be63ee395c03028f24564fd48668389bd65fd945f5ac36" +source = "git+https://github.com/n0-computer/bao-tree?branch=main#109ce557ec3feafb29a4702a0d1d195b1d52a706" dependencies = [ "blake3", "bytes", @@ -1692,6 +1691,7 @@ dependencies = [ "atomic_refcell", "bao-tree", "bytes", + "cfg_aliases", "chrono", "clap", "concat_const", @@ -1728,7 +1728,6 @@ dependencies = [ "test-strategy", "testresult", "tokio", - "tokio-util", "tracing", "tracing-subscriber", "tracing-test", @@ -1910,8 +1909,7 @@ dependencies = [ [[package]] name = "irpc" version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52cf44fdb253f2a3e22e5ecfa8efa466929f8b7cdd4fc0f958f655406e8cdab6" +source = "git+https://github.com/n0-computer/irpc?branch=main#83c9dcbfe000f016e9a77419472a8b717036d5c8" dependencies = [ "anyhow", "futures-buffered", @@ -1933,8 +1931,7 @@ dependencies = [ [[package]] name = "irpc-derive" version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969df6effc474e714fb7e738eb9859aa22f40dc2280cadeab245817075c7f273" +source = "git+https://github.com/n0-computer/irpc?branch=main#83c9dcbfe000f016e9a77419472a8b717036d5c8" dependencies = [ "proc-macro2", "quote", @@ -2579,9 +2576,9 @@ dependencies = [ [[package]] name = "positioned-io" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8078ce4d22da5e8f57324d985cc9befe40c49ab0507a192d6be9e59584495c9" +checksum = "d4ec4b80060f033312b99b6874025d9503d2af87aef2dd4c516e253fbfcdada7" dependencies = [ "libc", "winapi", @@ -3814,12 +3811,10 @@ checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ "bytes", "futures-core", - "futures-io", "futures-sink", "futures-util", "hashbrown", "pin-project-lite", - "slab", "tokio", ] @@ -4295,7 +4290,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ddeb85949..e6f448bc7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,14 +17,13 @@ bao-tree = { version = "0.15.1", features = ["experimental-mixed", "tokio_fsm", bytes = { version = "1", features = ["serde"] } derive_more = { version = "2.0.1", features = ["from", "try_from", "into", "debug", "display", "deref", "deref_mut"] } futures-lite = "2.6.0" -quinn = { package = "iroh-quinn", version = "0.14.0" } +quinn = { package = "iroh-quinn", version = "0.14.0", optional = true } n0-future = "0.3.0" n0-snafu = "0.2.2" range-collections = { version = "0.4.6", features = ["serde"] } smallvec = { version = "1", features = ["serde", "const_new"] } snafu = "0.8.5" -tokio = { version = "1.43.0", features = ["full"] } -tokio-util = { version = "0.7.13", features = ["full"] } +tokio = { version = "1.43.0", default-features = false, features = ["sync"] } tracing = "0.1.41" iroh-io = "0.6.1" rand = "0.9.2" @@ -36,12 +35,12 @@ chrono = "0.4.39" nested_enum_utils = "0.2.1" ref-cast = "1.0.24" arrayvec = "0.7.6" -iroh = "0.94" +iroh = { version = "0.94", default-features = false } self_cell = "1.1.0" genawaiter = { version = "0.99.1", features = ["futures03"] } iroh-base = "0.94" iroh-tickets = "0.1" -irpc = { version = "0.10.0", features = ["rpc", "quinn_endpoint_setup", "spans", "stream", "derive"], default-features = false } +irpc = { version = "0.10.0", features = ["spans", "stream", "derive", "varint-util"], default-features = false } iroh-metrics = { version = "0.36" } redb = { version = "2.6.3", optional = true } reflink-copy = { version = "0.1.24", optional = true } @@ -64,8 +63,24 @@ iroh = { version = "0.94", features = ["discovery-local-network"]} async-compression = { version = "0.4.30", features = ["lz4", "tokio"] } concat_const = "0.2.0" +[build-dependencies] +cfg_aliases = "0.2.1" + [features] hide-proto-docs = [] metrics = [] -default = ["hide-proto-docs", "fs-store"] -fs-store = ["dep:redb", "dep:reflink-copy"] +default = ["hide-proto-docs", "fs-store", "rpc"] +fs-store = ["dep:redb", "dep:reflink-copy", "bao-tree/fs"] +rpc = ["dep:quinn", "irpc/rpc", "irpc/quinn_endpoint_setup"] + +[[example]] +name = "expiring-tags" +required-features = ["fs-store"] + +[[example]] +name = "random_store" +required-features = ["fs-store"] + +[patch.crates-io] +irpc = { git = "https://github.com/n0-computer/irpc", branch = "main" } +bao-tree = { git = "https://github.com/n0-computer/bao-tree", branch = "main" } diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..7aae56820 --- /dev/null +++ b/build.rs @@ -0,0 +1,9 @@ +use cfg_aliases::cfg_aliases; + +fn main() { + // Setup cfg aliases + cfg_aliases! { + // Convenience aliases + wasm_browser: { all(target_family = "wasm", target_os = "unknown") }, + } +} diff --git a/examples/expiring-tags.rs b/examples/expiring-tags.rs index e19771e80..c8a4e1119 100644 --- a/examples/expiring-tags.rs +++ b/examples/expiring-tags.rs @@ -122,17 +122,17 @@ async fn print_store_info(store: &Store) -> anyhow::Result<()> { } async fn info_task(store: Store) -> anyhow::Result<()> { - tokio::time::sleep(Duration::from_secs(1)).await; + n0_future::time::sleep(Duration::from_secs(1)).await; loop { print_store_info(&store).await?; - tokio::time::sleep(Duration::from_secs(5)).await; + n0_future::time::sleep(Duration::from_secs(5)).await; } } async fn delete_expired_tags_task(store: Store, prefix: &str) -> anyhow::Result<()> { loop { delete_expired_tags(&store, prefix, false).await?; - tokio::time::sleep(Duration::from_secs(5)).await; + n0_future::time::sleep(Duration::from_secs(5)).await; } } diff --git a/examples/limit.rs b/examples/limit.rs index 4a9a379ed..58a1d7635 100644 --- a/examples/limit.rs +++ b/examples/limit.rs @@ -156,7 +156,7 @@ fn throttle(delay_ms: u64) -> EventSender { ); // we could compute the delay from the size of the data to have a fixed rate. // but the size is almost always 16 KiB (16 chunks). - tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await; + n0_future::time::sleep(std::time::Duration::from_millis(delay_ms)).await; msg.tx.send(Ok(())).await.ok(); }); } diff --git a/src/api.rs b/src/api.rs index 3abb13bdb..26ebf3415 100644 --- a/src/api.rs +++ b/src/api.rs @@ -12,14 +12,13 @@ //! //! You can also [`connect`](Store::connect) to a remote store that is listening //! to rpc requests. -use std::{io, net::SocketAddr, ops::Deref}; +use std::{io, ops::Deref}; use bao_tree::io::EncodeError; use iroh::Endpoint; -use irpc::rpc::{listen, RemoteService}; use n0_snafu::SpanTrace; use nested_enum_utils::common_fields; -use proto::{Request, ShutdownRequest, SyncDbRequest}; +use proto::{ShutdownRequest, SyncDbRequest}; use ref_cast::RefCast; use serde::{Deserialize, Serialize}; use snafu::{Backtrace, IntoError, Snafu}; @@ -128,6 +127,7 @@ impl From for ExportBaoError { irpc::Error::OneshotRecv(e) => OneshotRecvSnafu.into_error(e), irpc::Error::Send(e) => SendSnafu.into_error(e), irpc::Error::Request(e) => RequestSnafu.into_error(e), + #[cfg(feature = "rpc")] irpc::Error::Write(e) => ExportBaoIoSnafu.into_error(e.into()), } } @@ -220,6 +220,7 @@ impl From for Error { } } +#[cfg(feature = "rpc")] impl From for Error { fn from(e: irpc::rpc::WriteError) -> Self { Self::Io(e.into()) @@ -298,16 +299,21 @@ impl Store { } /// Connect to a remote store as a rpc client. - pub fn connect(endpoint: quinn::Endpoint, addr: SocketAddr) -> Self { + #[cfg(feature = "rpc")] + pub fn connect(endpoint: quinn::Endpoint, addr: std::net::SocketAddr) -> Self { let sender = irpc::Client::quinn(endpoint, addr); Store::from_sender(sender) } /// Listen on a quinn endpoint for incoming rpc connections. + #[cfg(feature = "rpc")] pub async fn listen(self, endpoint: quinn::Endpoint) { + use irpc::rpc::RemoteService; + + use self::proto::Request; let local = self.client.as_local().unwrap().clone(); let handler = Request::remote_handler(local); - listen::(endpoint, handler).await + irpc::rpc::listen::(endpoint, handler).await } pub async fn sync_db(&self) -> RequestResult<()> { diff --git a/src/api/downloader.rs b/src/api/downloader.rs index fffacc142..9f5bfbc2d 100644 --- a/src/api/downloader.rs +++ b/src/api/downloader.rs @@ -10,10 +10,9 @@ use anyhow::bail; use genawaiter::sync::Gen; use iroh::{Endpoint, EndpointId}; use irpc::{channel::mpsc, rpc_requests}; -use n0_future::{future, stream, BufferedStreamExt, Stream, StreamExt}; +use n0_future::{future, stream, task::JoinSet, BufferedStreamExt, Stream, StreamExt}; use rand::seq::SliceRandom; use serde::{de::Error, Deserialize, Serialize}; -use tokio::task::JoinSet; use tracing::instrument::Instrument; use super::Store; @@ -31,7 +30,7 @@ pub struct Downloader { client: irpc::Client, } -#[rpc_requests(message = SwarmMsg, alias = "Msg")] +#[rpc_requests(message = SwarmMsg, alias = "Msg", rpc_feature = "rpc")] #[derive(Debug, Serialize, Deserialize)] enum SwarmProtocol { #[rpc(tx = mpsc::Sender)] @@ -42,7 +41,7 @@ struct DownloaderActor { store: Store, pool: ConnectionPool, tasks: JoinSet<()>, - running: HashSet, + running: HashSet, } #[derive(Debug, Serialize, Deserialize)] @@ -342,7 +341,7 @@ impl Downloader { pub fn new(store: &Store, endpoint: &Endpoint) -> Self { let (tx, rx) = tokio::sync::mpsc::channel::(32); let actor = DownloaderActor::new(store.clone(), endpoint.clone()); - tokio::spawn(actor.run(rx)); + n0_future::task::spawn(actor.run(rx)); Self { client: tx.into() } } diff --git a/src/api/proto.rs b/src/api/proto.rs index b2a0eed94..80478e934 100644 --- a/src/api/proto.rs +++ b/src/api/proto.rs @@ -87,7 +87,7 @@ impl HashSpecific for CreateTagMsg { } } -#[rpc_requests(message = Command, alias = "Msg")] +#[rpc_requests(message = Command, alias = "Msg", rpc_feature = "rpc")] #[derive(Debug, Serialize, Deserialize)] pub enum Request { #[rpc(tx = mpsc::Sender>)] diff --git a/src/get.rs b/src/get.rs index 15f40ea1b..d9c59b034 100644 --- a/src/get.rs +++ b/src/get.rs @@ -18,12 +18,13 @@ //! [iroh]: https://docs.rs/iroh use std::{ fmt::{self, Debug}, - time::{Duration, Instant}, + time::Duration, }; use anyhow::Result; use bao_tree::{io::fsm::BaoContentItem, ChunkNum}; use fsm::RequestCounters; +use n0_future::time::Instant; use n0_snafu::SpanTrace; use nested_enum_utils::common_fields; use serde::{Deserialize, Serialize}; diff --git a/src/provider.rs b/src/provider.rs index 390254010..ed3de25d1 100644 --- a/src/provider.rs +++ b/src/provider.rs @@ -3,19 +3,13 @@ //! Note that while using this API directly is fine, the standard way //! to provide data is to just register a [`crate::BlobsProtocol`] protocol //! handler with an [`iroh::Endpoint`](iroh::protocol::Router). -use std::{ - fmt::Debug, - future::Future, - io, - time::{Duration, Instant}, -}; +use std::{fmt::Debug, future::Future, io, time::Duration}; use anyhow::Result; use bao_tree::ChunkRanges; -use iroh::endpoint::{self, VarInt}; +use iroh::endpoint::{self, ConnectionError, VarInt}; use iroh_io::{AsyncStreamReader, AsyncStreamWriter}; -use n0_future::StreamExt; -use quinn::ConnectionError; +use n0_future::{time::Instant, StreamExt}; use serde::{Deserialize, Serialize}; use snafu::Snafu; use tokio::select; @@ -309,7 +303,7 @@ pub async fn handle_connection( while let Ok(pair) = StreamPair::accept(&connection, progress.clone()).await { let span = debug_span!("stream", stream_id = %pair.stream_id()); let store = store.clone(); - tokio::spawn(handle_stream(pair, store).instrument(span)); + n0_future::task::spawn(handle_stream(pair, store).instrument(span)); } progress .connection_closed(|| ConnectionClosed { connection_id }) diff --git a/src/provider/events.rs b/src/provider/events.rs index 932570e9c..7f27b2dd2 100644 --- a/src/provider/events.rs +++ b/src/provider/events.rs @@ -1,5 +1,6 @@ use std::{fmt::Debug, io, ops::Deref}; +use iroh::endpoint::VarInt; use irpc::{ channel::{mpsc, none::NoSender, oneshot}, rpc_requests, Channels, WithChannels, @@ -106,11 +107,11 @@ impl From for io::Error { } pub trait HasErrorCode { - fn code(&self) -> quinn::VarInt; + fn code(&self) -> VarInt; } impl HasErrorCode for ProgressError { - fn code(&self) -> quinn::VarInt { + fn code(&self) -> VarInt { match self { ProgressError::Limit => ERR_LIMIT, ProgressError::Permission => ERR_PERMISSION, @@ -531,7 +532,7 @@ impl EventSender { } } -#[rpc_requests(message = ProviderMessage)] +#[rpc_requests(message = ProviderMessage, rpc_feature = "rpc")] #[derive(Debug, Serialize, Deserialize)] pub enum ProviderProto { /// A new client connected to the provider. @@ -705,10 +706,15 @@ mod irpc_ext { .map_err(irpc::Error::from)?; Ok(req_tx) } + #[cfg(feature = "rpc")] irpc::Request::Remote(remote) => { let (s, _) = remote.write(msg).await?; Ok(s.into()) } + #[cfg(not(feature = "rpc"))] + irpc::Request::Remote(_) => { + unreachable!() + } } } } diff --git a/src/store/fs.rs b/src/store/fs.rs index 8bf43f3d3..53c697abc 100644 --- a/src/store/fs.rs +++ b/src/store/fs.rs @@ -1561,7 +1561,7 @@ pub mod tests { let ranges = ChunkRanges::all(); let (hash, bao) = create_n0_bao(&data, &ranges)?; let obs = store.observe(hash); - let task = tokio::spawn(async move { + let task = n0_future::task::spawn(async move { obs.await_completion().await?; api::Result::Ok(()) }); diff --git a/src/store/fs/meta.rs b/src/store/fs/meta.rs index aac43cb4a..b03304ad1 100644 --- a/src/store/fs/meta.rs +++ b/src/store/fs/meta.rs @@ -766,7 +766,7 @@ impl Actor { self.cmds.push_back(cmd.into()).ok(); let tx = db.begin_read().context(TransactionSnafu)?; let tables = ReadOnlyTables::new(&tx).context(TableSnafu)?; - let timeout = tokio::time::sleep(self.options.max_read_duration); + let timeout = n0_future::time::sleep(self.options.max_read_duration); pin!(timeout); let mut n = 0; while let Some(cmd) = self.cmds.extract(Command::read_only, &mut timeout).await @@ -784,7 +784,7 @@ impl Actor { let ftx = self.ds.begin_write(); let tx = db.begin_write().context(TransactionSnafu)?; let mut tables = Tables::new(&tx, &ftx).context(TableSnafu)?; - let timeout = tokio::time::sleep(self.options.max_read_duration); + let timeout = n0_future::time::sleep(self.options.max_read_duration); pin!(timeout); let mut n = 0; while let Some(cmd) = self diff --git a/src/store/fs/util/entity_manager.rs b/src/store/fs/util/entity_manager.rs index b0b2898ea..ea5762594 100644 --- a/src/store/fs/util/entity_manager.rs +++ b/src/store/fs/util/entity_manager.rs @@ -723,7 +723,7 @@ impl EntityManager

{ options.entity_response_inbox_size, options.entity_futures_initial_capacity, ); - tokio::spawn(actor.run()); + n0_future::task::spawn(actor.run()); Self(send) } diff --git a/src/store/gc.rs b/src/store/gc.rs index ca8404c92..435c06fbf 100644 --- a/src/store/gc.rs +++ b/src/store/gc.rs @@ -221,7 +221,7 @@ pub async fn run_gc(store: Store, config: GcConfig) { let mut live = HashSet::new(); loop { live.clear(); - tokio::time::sleep(config.interval).await; + n0_future::time::sleep(config.interval).await; if let Some(ref cb) = config.add_protected { match (cb)(&mut live).await { ProtectOutcome::Continue => {} diff --git a/src/store/mem.rs b/src/store/mem.rs index 76bc0e6e4..bbdd78913 100644 --- a/src/store/mem.rs +++ b/src/store/mem.rs @@ -14,7 +14,6 @@ use std::{ num::NonZeroU64, ops::Deref, sync::Arc, - time::SystemTime, }; use bao_tree::{ @@ -29,13 +28,13 @@ use bao_tree::{ }; use bytes::Bytes; use irpc::channel::mpsc; -use n0_future::future::yield_now; -use range_collections::range_set::RangeSetRange; -use tokio::{ - io::AsyncReadExt, - sync::watch, +use n0_future::{ + future::yield_now, task::{JoinError, JoinSet}, + time::SystemTime, }; +use range_collections::range_set::RangeSetRange; +use tokio::sync::watch; use tracing::{error, info, instrument, trace, Instrument}; use super::util::{BaoTreeSender, PartialMemStorage}; @@ -121,7 +120,7 @@ impl MemStore { pub fn new_with_opts(opts: Options) -> Self { let (sender, receiver) = tokio::sync::mpsc::channel(32); - tokio::spawn( + n0_future::task::spawn( Actor { commands: receiver, tasks: JoinSet::new(), @@ -140,7 +139,7 @@ impl MemStore { let store = Self::from_sender(sender.into()); if let Some(gc_config) = opts.gc_config { - tokio::spawn(run_gc(store.deref().clone(), gc_config)); + n0_future::task::spawn(run_gc(store.deref().clone(), gc_config)); } store @@ -755,8 +754,18 @@ async fn import_byte_stream( import_bytes(res.into(), scope, format, tx).await } +#[cfg(wasm_browser)] +async fn import_path(cmd: ImportPathMsg) -> anyhow::Result { + let _: ImportPathRequest = cmd.inner; + Err(anyhow::anyhow!( + "import_path is not supported in the browser" + )) +} + #[instrument(skip_all, fields(path = %cmd.path.display()))] +#[cfg(not(wasm_browser))] async fn import_path(cmd: ImportPathMsg) -> anyhow::Result { + use tokio::io::AsyncReadExt; let ImportPathMsg { inner: ImportPathRequest { @@ -1098,7 +1107,7 @@ mod tests { let store2 = MemStore::new(); let mut or = store2.observe(hash).stream().await?; - tokio::spawn(async move { + n0_future::task::spawn(async move { while let Some(event) = or.next().await { println!("event: {event:?}"); } diff --git a/src/store/readonly_mem.rs b/src/store/readonly_mem.rs index cb46228cd..649acdcbc 100644 --- a/src/store/readonly_mem.rs +++ b/src/store/readonly_mem.rs @@ -23,10 +23,12 @@ use bao_tree::{ }; use bytes::Bytes; use irpc::channel::mpsc; -use n0_future::future::{self, yield_now}; +use n0_future::{ + future::{self, yield_now}, + task::{JoinError, JoinSet}, +}; use range_collections::range_set::RangeSetRange; use ref_cast::RefCast; -use tokio::task::{JoinError, JoinSet}; use super::util::BaoTreeSender; use crate::{ @@ -369,7 +371,7 @@ impl ReadonlyMemStore { } let (sender, receiver) = tokio::sync::mpsc::channel(1); let actor = Actor::new(receiver, entries); - tokio::spawn(actor.run()); + n0_future::task::spawn(actor.run()); let local = irpc::LocalSender::from(sender); Self { client: local.into(), diff --git a/src/store/util.rs b/src/store/util.rs index 03be152bb..03630a6fc 100644 --- a/src/store/util.rs +++ b/src/store/util.rs @@ -1,8 +1,9 @@ -use std::{borrow::Borrow, fmt, time::SystemTime}; +use std::{borrow::Borrow, fmt}; use bao_tree::io::mixed::EncodedItem; use bytes::Bytes; use derive_more::{From, Into}; +use n0_future::time::SystemTime; mod sparse_mem_file; use irpc::channel::mpsc; @@ -68,6 +69,13 @@ impl fmt::Display for Tag { impl Tag { /// Create a new tag that does not exist yet. pub fn auto(time: SystemTime, exists: impl Fn(&[u8]) -> bool) -> Self { + // On wasm, SystemTime is web_time::SystemTime, but we need a std system time + // to convert to chrono. + // TODO: Upstream to n0-future or expose SystemTimeExt on wasm + #[cfg(wasm_browser)] + let time = std::time::SystemTime::UNIX_EPOCH + + time.duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let now = chrono::DateTime::::from(time); let mut i = 0; loop { diff --git a/src/tests.rs b/src/tests.rs index 76af8f0a8..5460f428b 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -266,7 +266,7 @@ async fn two_nodes_observe( let mut stream = store2 .remote() .observe(conn.clone(), ObserveRequest::new(hash)); - let remote_observe_task = tokio::spawn(async move { + let remote_observe_task = n0_future::task::spawn(async move { let mut current = Bitfield::empty(); while let Some(item) = stream.next().await { current = current.combine(item?); @@ -346,7 +346,7 @@ fn event_handler( let (count_tx, count_rx) = tokio::sync::watch::channel(0usize); let (events_tx, mut events_rx) = EventSender::channel(16, EventMask::ALL_READONLY); let allowed_nodes = allowed_nodes.into_iter().collect::>(); - let task = AbortOnDropHandle::new(tokio::task::spawn(async move { + let task = AbortOnDropHandle::new(n0_future::task::spawn(async move { while let Some(event) = events_rx.recv().await { match event { ProviderMessage::ClientConnected(msg) => { @@ -360,7 +360,7 @@ fn event_handler( ProviderMessage::PushRequestReceived(mut msg) => { msg.tx.send(Ok(())).await.ok(); let count_tx = count_tx.clone(); - tokio::task::spawn(async move { + n0_future::task::spawn(async move { while let Ok(Some(update)) = msg.rx.recv().await { if let RequestUpdate::Completed(_) = update { count_tx.send_modify(|x| *x += 1); diff --git a/src/util/connection_pool.rs b/src/util/connection_pool.rs index e3c2d3a1a..92155790d 100644 --- a/src/util/connection_pool.rs +++ b/src/util/connection_pool.rs @@ -32,7 +32,6 @@ use tokio::sync::{ mpsc::{self, error::SendError as TokioSendError}, oneshot, Notify, }; -use tokio_util::time::FutureExt as TimeFutureExt; use tracing::{debug, error, info, trace}; pub type OnConnected = @@ -194,8 +193,7 @@ impl Context { }; // Connect to the node - let state = conn_fut - .timeout(context.options.connect_timeout) + let state = n0_future::time::timeout(context.options.connect_timeout, conn_fut) .await .map_err(|_| PoolConnectError::Timeout) .and_then(|r| r); @@ -265,7 +263,7 @@ impl Context { break; } // set the idle timer - idle_timer.as_mut().set_future(tokio::time::sleep(context.options.idle_timeout)); + idle_timer.as_mut().set_future(n0_future::time::sleep(context.options.idle_timeout)); } // Idle timeout - request shutdown @@ -422,7 +420,7 @@ impl ConnectionPool { let (actor, tx) = Actor::new(endpoint, alpn, options); // Spawn the main actor - tokio::spawn(actor.run()); + n0_future::task::spawn(actor.run()); Self { tx } } @@ -714,7 +712,7 @@ mod tests { assert_eq!(cid1, cid2); connection_ids.insert(id, cid1); } - tokio::time::sleep(Duration::from_millis(1000)).await; + n0_future::time::sleep(Duration::from_millis(1000)).await; for id in &ids { let cid1 = *connection_ids.get(id).expect("Connection ID not found"); let (cid2, res) = client.echo(*id, msg.clone()).await??; @@ -846,7 +844,7 @@ mod tests { let conn = pool.get_or_connect(ids[0]).await?; let cid1 = conn.stable_id(); conn.close(0u32.into(), b"test"); - tokio::time::sleep(Duration::from_millis(500)).await; + n0_future::time::sleep(Duration::from_millis(500)).await; let conn = pool.get_or_connect(ids[0]).await?; let cid2 = conn.stable_id(); assert_ne!(cid1, cid2); diff --git a/tests/blobs.rs b/tests/blobs.rs index 16f626cc9..e59930a29 100644 --- a/tests/blobs.rs +++ b/tests/blobs.rs @@ -109,7 +109,7 @@ async fn blobs_smoke_fs_rpc() -> TestResult { let client = irpc::util::make_client_endpoint(unspecified, &[cert.as_ref()])?; let td = tempfile::tempdir()?; let store = FsStore::load(td.path().join("a")).await?; - tokio::spawn(store.deref().clone().listen(server.clone())); + n0_future::task::spawn(store.deref().clone().listen(server.clone())); let api = Store::connect(client, server.local_addr()?); blobs_smoke(td.path(), api.blobs()).await?; api.shutdown().await?; diff --git a/tests/tags.rs b/tests/tags.rs index 5fe929488..3df517756 100644 --- a/tests/tags.rs +++ b/tests/tags.rs @@ -154,7 +154,7 @@ async fn tags_smoke_fs_rpc() -> TestResult<()> { let client = irpc::util::make_client_endpoint(unspecified, &[cert.as_ref()])?; let td = tempfile::tempdir()?; let store = FsStore::load(td.path().join("a")).await?; - tokio::spawn(store.deref().clone().listen(server.clone())); + n0_future::task::spawn(store.deref().clone().listen(server.clone())); let api = Store::connect(client, server.local_addr()?); tags_smoke(api.tags()).await?; api.shutdown().await?;