refactor: repack external bindings into their own crates (#19)

This commit is contained in:
zacheryasc 2026-02-07 17:39:02 +00:00
parent 282fcc3d01
commit 75aefa0c49
17 changed files with 57 additions and 176 deletions

7
.gitignore vendored
View file

@ -1,6 +1,5 @@
**/target
tools/depgraph/target/
node_modules/
**/node_modules/
.vscode/
.venv
__pycache__
**/.venv
__pycache__

15
Cargo.lock generated
View file

@ -532,7 +532,22 @@ dependencies = [
"crossbeam-queue",
"crossbeam-utils",
"getrandom",
]
[[package]]
name = "swactor-python"
version = "0.1.0"
dependencies = [
"pyo3",
"swactor",
]
[[package]]
name = "swactor-wasm"
version = "0.1.0"
dependencies = [
"swactor",
"wasm-bindgen",
]
[[package]]

View file

@ -1,3 +1,7 @@
[workspace]
members = [".", "crates/swactor-python", "crates/swactor-wasm"]
exclude = ["tools/depgraph"]
[package]
name = "swactor"
version = "0.1.0"
@ -5,19 +9,17 @@ edition = "2024"
autobenches = false
[lib]
crate-type = ["cdylib", "rlib"]
crate-type = ["rlib"]
[features]
default = ["getrandom"]
getrandom = ["dep:getrandom"]
no_random = [] # compile without access to a source of randomness
python = ["dep:pyo3"]
[dependencies]
getrandom = { version = "0.2", optional = true }
crossbeam-queue = "0.3.12"
crossbeam-utils = "0.8.21"
pyo3 = { version = "0.23", features = ["extension-module"], optional = true }
[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }

View file

@ -0,0 +1,12 @@
[package]
name = "swactor-python"
version = "0.1.0"
edition = "2024"
[lib]
name = "swactor"
crate-type = ["cdylib"]
[dependencies]
swactor = { path = "../.." }
pyo3 = { version = "0.23", features = ["extension-module"] }

View file

@ -10,12 +10,11 @@ requires-python = ">=3.9"
[dependency-groups]
dev = ["jupyter", "ipykernel"]
[tool.maturin]
features = ["python"]
[tool.uv]
cache-keys = [
{ file = "pyproject.toml" },
{ file = "Cargo.toml" },
{ file = "src/**/*.rs" },
{ file = "../../Cargo.toml" },
{ file = "../../src/**/*.rs" },
]

View file

@ -4,10 +4,9 @@ use std::cell::RefCell;
use pyo3::prelude::*;
use pyo3::types::PyModule;
use crate::actor::{Actor, ActorAddress, ActorInterface, AnyActor, Ctx};
use crate::config::{BackoffPolicy, RuntimeConfig};
use crate::runtime::{Inbox, Runtime, RuntimeHandle};
use crate::Error;
use ::swactor::actor::{Actor, ActorAddress, ActorInterface, AnyActor, Ctx};
use ::swactor::config::{BackoffPolicy, RuntimeConfig};
use ::swactor::runtime::{Inbox, Runtime, RuntimeHandle};
// ─── PyMsg newtype ───────────────────────────────────────────────────────────
@ -38,7 +37,7 @@ impl PyMsg {
// ─── Helpers ─────────────────────────────────────────────────────────────────
fn to_py_err(e: Error) -> PyErr {
fn to_py_err(e: ::swactor::Error) -> PyErr {
pyo3::exceptions::PyRuntimeError::new_err(e.to_string())
}
@ -570,7 +569,7 @@ fn build_stats(runtime: &Runtime) -> PyRuntimeStats {
// ─── Module registration ─────────────────────────────────────────────────────
pub fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<PyActorAddress>()?;
m.add_class::<PyCtx>()?;
m.add_class::<PyInbox>()?;
@ -582,3 +581,8 @@ pub fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<PyRuntimeStats>()?;
Ok(())
}
#[pymodule]
fn swactor(m: &Bound<'_, PyModule>) -> PyResult<()> {
register(m)
}

View file

@ -1,5 +1,3 @@
[workspace]
[package]
name = "swactor-wasm"
version = "0.1.0"
@ -9,5 +7,5 @@ edition = "2024"
crate-type = ["cdylib"]
[dependencies]
swactor = { path = "..", default-features = false, features = ["no_random"] }
swactor = { path = "../..", default-features = false, features = ["no_random"] }
wasm-bindgen = "0.2"

View file

@ -26,16 +26,16 @@ impl ActorAddress {
}
/// The actor process as represented in the Runtime — thin wrapper around user state.
pub(crate) struct Actor<A: ActorInterface>(A);
pub struct Actor<A: ActorInterface>(A);
impl<A: ActorInterface> Actor<A> {
pub(crate) fn new(inner: A) -> Self {
pub fn new(inner: A) -> Self {
Self(inner)
}
}
/// Trait for type-erased actors — single-message handler.
pub(crate) trait AnyActor: Send {
pub trait AnyActor: Send {
fn handle_any(&mut self, ctx: &Ctx, msg: Box<dyn Any + Send>);
}
@ -51,7 +51,7 @@ where
}
/// Object-safe inner trait for sending type-erased messages.
pub(crate) trait ContextInner {
pub trait ContextInner {
fn send_any(&self, addr: ActorAddress, msg: Box<dyn Any + Send>) -> Result<(), Error>;
fn spawn_any(&self, addr: ActorAddress, actor: Box<dyn AnyActor>) -> Result<(), Error>;
fn mailbox_waterlevel(&self) -> usize;
@ -71,8 +71,7 @@ impl<'a> Ctx<'a> {
Self { inner, self_addr }
}
#[cfg(feature = "python")]
pub(crate) fn raw_inner(&self) -> &dyn ContextInner {
pub fn raw_inner(&self) -> &dyn ContextInner {
self.inner
}

View file

@ -12,7 +12,7 @@ use crate::config::RuntimeConfig;
use crate::delivery::{AddressMap, Envelope, InboxRegistry, Placement, TickContext, WorkerId};
use crate::stats::WorkerStats;
use super::Worker;
use crate::worker::Worker;
// ── Actors ─────────────────────────────────────────────────────────

View file

@ -12,21 +12,12 @@ pub mod stats;
pub mod runtime;
#[cfg(feature = "python")]
mod python;
#[cfg(feature = "python")]
#[pyo3::pymodule]
fn swactor(m: &pyo3::Bound<'_, pyo3::types::PyModule>) -> pyo3::PyResult<()> {
python::register(m)
}
#[cfg(feature = "getrandom")]
pub(crate) fn get_random(buf: &mut [u8]) {
getrandom::getrandom(buf).unwrap()
}
#[cfg(feature = "no_random")]
#[cfg(all(feature = "no_random", not(feature = "getrandom")))]
pub(crate) fn get_random(buf: &mut [u8]) {
use core::sync::atomic::{AtomicUsize, Ordering};
@ -42,4 +33,4 @@ pub(crate) fn get_random(buf: &mut [u8]) {
#[cfg(test)]
mod crate_test;
mod crate_test;

View file

@ -14,7 +14,7 @@ use crate::Error;
/// A worker owns a set of actors and runs them in a loop.
pub(crate) struct Worker {
id: WorkerId,
pool: ActorPool,
pub(crate) pool: ActorPool,
transfer_rx: Receiver<Envelope>,
spawn_rx: Receiver<(ActorAddress, Box<dyn AnyActor>)>,
stats: Arc<WorkerStats>,

138
wasm/Cargo.lock generated
View file

@ -1,138 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "bumpalo"
version = "3.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "crossbeam-queue"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "proc-macro2"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "swactor"
version = "0.1.0"
dependencies = [
"crossbeam-queue",
"crossbeam-utils",
]
[[package]]
name = "swactor-wasm"
version = "0.1.0"
dependencies = [
"swactor",
"wasm-bindgen",
]
[[package]]
name = "syn"
version = "2.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "wasm-bindgen"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
dependencies = [
"unicode-ident",
]