Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support async fn with #[neon::export] #1032

Open
kjvalencik opened this issue Apr 3, 2024 · 0 comments
Open

Support async fn with #[neon::export] #1032

kjvalencik opened this issue Apr 3, 2024 · 0 comments

Comments

@kjvalencik
Copy link
Member

kjvalencik commented Apr 3, 2024

#1025 introduced #[neon::export]. When the task attribute is included, the body of the function is executed on the libuv worker pool and a JsPromise is returned.

The #[neon::export] macro should also return a JsPromise when the function is async. The transformation is fairly straightforward, but we need a way to spawn a future. Ideally this is done in a runtime agnostic way.

  • Use a Spawn trait from a public crate or write our own
  • Provide a method for registering a global runtime

We will need good docs for registering the runtime. Since there are a couple of gotchas:

  • We likely do not want distinct runtimes across workers
  • neon::main gets called multiple times and may attempt to register

The macro should catch some common pitfalls and give clear error messages:

  • task attribute cannot be used with async
  • FunctionContext and Handle cannot be used

Notes

Runtime will likely be registered as instance data. However, users will almost always want to share a runtime across workers. Docs should encourage creating a global static runtime and sharing that across instances.

use std::{io, sync::OnceLock};

use neon::prelude::*;
use tokio::runtime::Runtime;

#[neon::main]
fn main(mut cx: ModuleContext) -> NeonResult<()> {
    static RUNTIME: OnceLock<Runtime> = OnceLock::new();

    let runtime = RUNTIME
        .get_or_try_init(|| Runtime::new())
        .or_else(|err| cx.throw_error(err.to_string()))?;

    neon::register_runtime(runtime)?;

    Ok(())
}

This can be simplified by using a macro attribute and defaults.

#[neon::main(tokio)]
fn main(x: ModuleContext) -> Neonresult<()> {
    Ok(())
}

Alternatively, to avoid requiring a #[neon::main] just to register, a feature flag could be provided that automatically creates it.

[dependencies]
neon = { version = "1.1", features = ["tokio-multi-thread"] }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant