diff --git a/.gitignore b/.gitignore index 6d25471..ef9619e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ **/target -tools/depgraph/target/ -node_modules/ +**/node_modules/ .vscode/ -.venv -__pycache__ \ No newline at end of file +**/.venv +__pycache__ diff --git a/Cargo.lock b/Cargo.lock index 4f55210..a208c57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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]] diff --git a/Cargo.toml b/Cargo.toml index 353f364..33da0af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] } diff --git a/crates/swactor-python/Cargo.toml b/crates/swactor-python/Cargo.toml new file mode 100644 index 0000000..553d0d3 --- /dev/null +++ b/crates/swactor-python/Cargo.toml @@ -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"] } diff --git a/pyproject.toml b/crates/swactor-python/pyproject.toml similarity index 81% rename from pyproject.toml rename to crates/swactor-python/pyproject.toml index 2e6a774..e2e5ac9 100644 --- a/pyproject.toml +++ b/crates/swactor-python/pyproject.toml @@ -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" }, ] diff --git a/src/python.rs b/crates/swactor-python/src/lib.rs similarity index 97% rename from src/python.rs rename to crates/swactor-python/src/lib.rs index bb6fc32..d6a1924 100644 --- a/src/python.rs +++ b/crates/swactor-python/src/lib.rs @@ -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::()?; m.add_class::()?; m.add_class::()?; @@ -582,3 +581,8 @@ pub fn register(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; Ok(()) } + +#[pymodule] +fn swactor(m: &Bound<'_, PyModule>) -> PyResult<()> { + register(m) +} diff --git a/uv.lock b/crates/swactor-python/uv.lock similarity index 100% rename from uv.lock rename to crates/swactor-python/uv.lock diff --git a/wasm/Cargo.toml b/crates/swactor-wasm/Cargo.toml similarity index 59% rename from wasm/Cargo.toml rename to crates/swactor-wasm/Cargo.toml index dfc5e24..28ac8a1 100644 --- a/wasm/Cargo.toml +++ b/crates/swactor-wasm/Cargo.toml @@ -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" diff --git a/wasm/src/lib.rs b/crates/swactor-wasm/src/lib.rs similarity index 100% rename from wasm/src/lib.rs rename to crates/swactor-wasm/src/lib.rs diff --git a/wasm/test.mjs b/crates/swactor-wasm/test.mjs similarity index 100% rename from wasm/test.mjs rename to crates/swactor-wasm/test.mjs diff --git a/src/actor.rs b/src/actor.rs index 78886c7..c9703a7 100644 --- a/src/actor.rs +++ b/src/actor.rs @@ -26,16 +26,16 @@ impl ActorAddress { } /// The actor process as represented in the Runtime — thin wrapper around user state. -pub(crate) struct Actor(A); +pub struct Actor(A); impl Actor { - 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); } @@ -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) -> Result<(), Error>; fn spawn_any(&self, addr: ActorAddress, actor: Box) -> 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 } diff --git a/src/crate_test/mod.rs b/src/crate_test/mod.rs index 1eac33e..627ce1e 100644 --- a/src/crate_test/mod.rs +++ b/src/crate_test/mod.rs @@ -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 ───────────────────────────────────────────────────────── diff --git a/src/lib.rs b/src/lib.rs index aea0a4a..022e519 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; \ No newline at end of file +mod crate_test; diff --git a/src/worker.rs b/src/worker.rs index 9090f8e..61ab302 100644 --- a/src/worker.rs +++ b/src/worker.rs @@ -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, spawn_rx: Receiver<(ActorAddress, Box)>, stats: Arc, diff --git a/package-lock.json b/tools/package-lock.json similarity index 100% rename from package-lock.json rename to tools/package-lock.json diff --git a/package.json b/tools/package.json similarity index 100% rename from package.json rename to tools/package.json diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock deleted file mode 100644 index a99a116..0000000 --- a/wasm/Cargo.lock +++ /dev/null @@ -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", -]