diff --git a/Cargo.lock b/Cargo.lock index 0a8a0fe..5bcbbca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,6 +1213,7 @@ dependencies = [ "mio", "pin-project-lite", "socket2", + "tokio-macros", "windows-sys 0.61.2", ] @@ -1223,6 +1224,19 @@ dependencies = [ "neon", "reqwest", "serde", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-macros" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] diff --git a/examples/tokio-fetch/Cargo.toml b/examples/tokio-fetch/Cargo.toml index f112154..05a770c 100644 --- a/examples/tokio-fetch/Cargo.toml +++ b/examples/tokio-fetch/Cargo.toml @@ -13,3 +13,5 @@ crate-type = ["cdylib"] neon.workspace = true reqwest = { version = "0.12.24", features = ["json"] } serde = { version = "1", features = ["derive"] } +tokio = { version = "1", features = ["macros"] } +tokio-util = "0.7" diff --git a/examples/tokio-fetch/src/lib.rs b/examples/tokio-fetch/src/lib.rs index 98bc395..a1f67c5 100644 --- a/examples/tokio-fetch/src/lib.rs +++ b/examples/tokio-fetch/src/lib.rs @@ -54,3 +54,26 @@ fn current_node_release_date( // This task is executed asynchronously on the tokio thread pool Ok(node_release_date(version)) } + +#[neon::export] +async fn node_release_date_with_abort( + version: String, + token: CancellationToken, +) -> Result { + tokio::select! { + release = node_release_date(version) => release, + _ = token.token.cancelled() => Err(Error::new("Request aborted")), + } +} + +#[derive(Clone, Debug, Default)] +struct CancellationToken { + token: tokio_util::sync::CancellationToken, +} + +#[neon::export(class)] +impl CancellationToken { + fn cancel(&self) { + self.token.cancel(); + } +} diff --git a/examples/tokio-fetch/test.js b/examples/tokio-fetch/test.js new file mode 100644 index 0000000..e6ce7f7 --- /dev/null +++ b/examples/tokio-fetch/test.js @@ -0,0 +1,18 @@ +const { CancellationToken, nodeReleaseDateWithAbort } = require("."); + +const timeout = Number(process.argv[2]) || 10000; + +async function main() { + const version = process.version; + const ctrl = new AbortController(); + const token = new CancellationToken(); + + ctrl.signal.addEventListener("abort", () => token.cancel()); + setTimeout(() => ctrl.abort(), timeout).unref(); + + const date = await nodeReleaseDateWithAbort(version, token); + + console.log(date); +} + +main();