Skip to content

elixir: convert DirtyIo nifs to use message passing for asynchronous responses#172

Draft
npry wants to merge 5 commits into
mainfrom
npry/ex.async-msg
Draft

elixir: convert DirtyIo nifs to use message passing for asynchronous responses#172
npry wants to merge 5 commits into
mainfrom
npry/ex.async-msg

Conversation

@npry
Copy link
Copy Markdown
Collaborator

@npry npry commented May 7, 2026

DirtyIO NIFs are thread-pooled by the BEAM behind the scenes, and though the pool is configurable, this approach can limit throughput in highly concurrent scenarios. This is an alternate approach that offloads the synchronization to message passing using elixir's Task abstraction (slightly cleaner interface around processes) and a helper macro that handles spawning the task, waiting for it, and destructuring the response message. This is done in a task rather than the caller's process to avoid clashing with any existing message handling it might be doing (though a macro is also provided to support the in-process receive, which I think we may want for #119).

I don't believe there will be a great amount of overhead for this approach, since spawning tasks on both the tokio and BEAM sides should be quite cheap.

Also refactors the ts_elixir Rust code a fair amount — I understand a bit better now how rustler wants to be held to avoid a bunch of explicit conversions.

review notes

Probably much easier to read commit-by-commit

@npry npry force-pushed the npry/ex.async-msg branch 20 times, most recently from 840d0ab to 515f752 Compare May 14, 2026 19:27
@npry npry force-pushed the npry/ex.async-msg branch from 515f752 to ef4b684 Compare May 19, 2026 20:45
npry added 5 commits May 20, 2026 05:35
Signed-off-by: Nathan Perry <nathan@tailscale.com>
Change-Id: Ibdfa3c10dd50379a43b52a07c1a713cd6a6a6964
It erroneously expected all deps to have `workspace = true`, now checks
this correctly.

Signed-off-by: Nathan Perry <nathan@tailscale.com>
Change-Id: Iafe01153ca52b9f618c80666de5e6f186a6a6964
Signed-off-by: Nathan Perry <nathan@tailscale.com>
Change-Id: Iafe01153ca52b9f618c80666de5e6f186a6a6964
Potentially-blocking Rust-side calls now use message passing to respond
to the caller. Elixir now has `Tailscale.Util.await`, which spawns a
task that listens for the relevant response.

Signed-off-by: Nathan Perry <nathan@tailscale.com>
Change-Id: Iafe01153ca52b9f618c80666de5e6f186a6a6964
Provide tests to exercise the async callback type conversions.

Signed-off-by: Nathan Perry <nathan@tailscale.com>
Change-Id: Iafe01153ca52b9f618c80666de5e6f186a6a6964

Change-Id: I9d1d3e23de8a558fc6f0f81677b6237e6a6a6964
Signed-off-by: Nathan Perry <nathan@tailscale.com>
@npry npry force-pushed the npry/ex.async-msg branch from ef4b684 to ce2bf90 Compare May 20, 2026 09:35
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

Successfully merging this pull request may close these issues.

1 participant