Expand description
§Orb
Orb is an abstraction layer for writing runtime-agnostic async Rust code, allowing you to write code that works with different async runtimes, like tokio or smol.
We took the name Orb because it gets around :)
§Features
-
Runtime Agnostic: Write code that works with multiple async runtimes
- The hehavior of this crate is more aligned to tokio, to prevent unnotice bugs (for example, dropping a task handle means detach by default)
-
Extensible: Easy to implement support for new runtimes as plugin, without modification to the main crate.
-
Networking:
- Provide AsyncFd abstraction.
- Provide unify abstraction (tcp + unix) as UnifyListener / UnifyStream.
- Non-blocking name resolving: via ResolveAddr trait.
-
Worker Pool (requires
workerfeature): Support thread based and async, auto scallingWorkerPoolUnbounded- Submit message with unbounded channel.WorkerPoolBounded- Submit message with bounded channel
-
Implementation:
§The goal
The main goal is to decouple your application logic from specific async runtime implementations, allowing you to:
- Write portable async code that works at the same time in combination of multiple runtimes
- Switch to new runtimes without changing your core logic
- Test your code with different runtime characteristics
- Enhance async network programing experience
This is a side project during the development of razor-rpc. Because:
- There is no established standard for designing different runtimes, when developing shared libraries, developers often only target specific runtimes.
- Using too many
#[cfg(feature=xxx)]in code makes it hard to read. - Runtimes like
smolecology enable you to customize executors, but there’s high learning cost, and lack utility functions (for example, there’s notimeoutfunction inasync-ioorsmol). - Passing features through sub-projects through multiple layers of cargo dependencies is even more difficult. (that’s why we don’t use feature in this crate)
- If users want to customize a runtime for their own needs, they face the dilemma of incomplete ecosystem support.
- Some projects like Hyper define abstraction layers, having each project do this individually is a huge maintenance cost.
This is why this crate was written.
§Usage
To use Orb, you need to depend on both the core orb crate and a runtime adapter crate like orb-tokio or orb-smol.
In your Cargo.toml:
[dependencies]
# when you write runtime agnostic codes
orb = "0"
# when you setup as end-user
orb-tokio = "0"
# or
orb-smol = "0"There’s a global trait AsyncRuntime that combines all features at the crate level, and adding use orb::prelude::* will import all the traits you need, including AsyncExec, AsyncIO, and AsyncTime.
use orb::prelude::*;
use std::time::Duration;
// Generic function that works with any runtime
fn run<RT: AsyncRuntime>() {
let rt: RT::Exec = RT::multi(2);
rt.block_on(async {
// Spawn tasks using static methods
let handle = RT::spawn(async {
RT::sleep(Duration::from_millis(100)).await;
42
});
let result = handle.await.unwrap();
println!("Result: {}", result);
});
}
fn main() {
// Use with any runtime implementation
run::<orb_smol::SmolRT>();
}§Runtime Varieties Note
§Task Detach
The drop behavior of task handle is unified to “detach”, task will not be cancel unless abort is called.
§Panic
- tokio will issolate panic between tasks, a task handle may return Err() on join.
- smol will not issolate panic. Although a panic hook will work, the program might panic if one
of the task panic. You may use feature
unwindto enable panic capturing.
§thread local context
When the first time enter block_on in current() runtime, or threaded worker spawn,
we have maintain thread local ref for the runtime, so that you can use AsyncRuntime::spawn() static method directly.
(Note that calling AsyncRuntime::spawn() from non-async context will panic (just like tokio::spawn behavior)
§Cloning the runtime
AsyncExec is a cloneable runtime handle, can be initiated by AsyncRuntime::current(), AsyncRuntime::one(), AsyncRuntime::multi()
Modules§
- io
- Asynchronous I/O traits and utilities.
- net
- TCP and Unix domain socket listener implementations.
- prelude
- Re-export all the traits you need
- runtime
- Runtime execution traits for async task management.
- time
- Time-related traits and utilities for async operations.
- utils
- Utility types and functions for async operations.
- worker_
pool worker - Worker pool implementations for concurrent message processing.
Traits§
- Async
Runtime - A marker trait that combines all the core async runtime capabilities,
including
AsyncIO, andAsyncTime. It serves as a convenient way to specify that a type provides all the core async runtime functionality.