xtra
A tiny, fast, and safe actor framework. It is modelled around Actix (copyright and license here).
Features
- Safe: there is no unsafe code in xtra (there is some necessary in
futures, but that's par for the course). - Small and lightweight: it only depends on
futuresby default. - Asynchronous and synchronous message handlers.
- Simple asynchronous message handling interface which allows
async/awaitsyntax. No moreActorFutureand laborious combinators - asynchronous responders just returnimpl Future, even when borrowingself. - Does not depend on its own runtime and can be run with any futures executor (Tokio and
async-std have the
Actor::spawnconvenience method implemented out of the box). - Quite fast (under Tokio, <170ns time from sending a message to it being processed for sending without waiting for a result on my development machine with an AMD Ryzen 3 3200G)
Caveats
- The main caveat of this crate is that it uses many unstable features. For example, to get rid of
ActorFuture, Generic Associated Types (GATs) must be used. This is an incomplete and unstable feature, which appears to be a way off from stabilisation. It also usesimpl TraitType Aliases to avoidBoxing the futures returned from theHandlertrait (the library, however, is not totally alloc-free). This means that it requires nightly to use, and may be unstable in future as those features evolve. What you get in return for this is a cleaner, simpler, and more expressive API. - It is also still very much under development, so it may not be ready for production code.
Example
use Future;
use *;
;
// In the real world, the synchronous SyncHandler trait would be better-suited (and is a few ns faster)
async
For a longer example, check out Vertex, a chat application written with xtra (on the server).
Okay, sounds great! How do I use it?
Check out the docs and the examples
to get started! Enabling the with-tokio-0_2 or with-async_std-1 features are recommended in order to enable some
convenience methods (such as Actor::spawn). Which you enable will depend on which executor you want to use (check out
their docs to learn more about each). If you have any questions, feel free to open an issue
or message me on the Rust discord.
Latest Breaking Changes
From version 0.1.x to 0.2.0:
- Removal of the
with-runtimefeature- How to upgrade: You probably weren't using this anyway, but rather use
with-tokio-*orwith-async_std-*instead.
- How to upgrade: You probably weren't using this anyway, but rather use
Addressmethods were moved toAddressExtto accommodate newAddresstypes- How to upgrade: add
use xtra::AddressExtto wherever address methods are used (or, better yet,use xtra::prelude::*).
- How to upgrade: add
- All
*_asyncmethods were removed. Asynchronous and synchronous messages now use the same method for everything.- How to upgrade: simply switch from the
[x]_asyncmethod to the[x]method.
- How to upgrade: simply switch from the
AsyncHandlerwas renamed toHandler, and the oldHandlertoSyncHandler. Also, aHandlerandSyncHandlerimplementation can no longer coexist.- How to upgrade: rename all
Handlerimplementations toSyncHandler, and allAsyncHandlerimplementations toHandler.
- How to upgrade: rename all
See the full list of breaking changes by version here
Note: this crate has been yanked a bunch in 0.2. This is because of a git mess-up on my part, cargo doc not playing
nice with type alias impl trait and GATs, a mistake in the code making MessageChannel unusable, and having to mitigate
this bug in futures. Apologies!
To do
- Examples in documentation