Comments (6)
The other thing is pre_start
would probably have to take in self
and return Result<Self, ActorProcessingErr>
in order to deal with potential ownership things. Then the other function would probably be
async fn handle(&mut self, ...)
etc...
The reason the supervisor example uses the struct itself is just an artifact that should be cleaned up. If self
contains re-only data you're free to use it, but ideally it should be in the state as a pattern. It should be moved to that actor's Arguments
and stored in the state, thanks for the pointer :)
from ractor.
I'll try and add something to this effect onto the docs, but the short answer is the Actor's state is constructed and mutated only by the actor's processing loop. It also allows ownership of objects where if we utilize the struct implementing the Actor
trait we can only give a mutable reference and can't have full ownership of objects inside the pre_start
routine.
Essentially if we made the struct mutable from the start, you have to initialize it before calling spawn
of the actor. This means that if initialization were to panic!
or throw some unhandled error, it would need to be captured manually by the caller instead of getting a cleaner SpawnErr
.
It was a design choice, but this seemed like a safer pattern to me when creating it to prevent unhandled panic
's from accidentally taking down the caller.
As another anecdote, imagine your "root" actor panic!
s in it's initialization. Without pre_start
capturing it for you, you might crash your app where you could potentially handle the error.
Does that make sense?
from ractor.
Fair enough! Thanks for that clarification.
I had a reference to db in the struct field, but I think I'll move it to state now. Mentally to me it's more of some kind of "global resource" as opposed to actor state but I think it still fits best there.
from ractor.
It also allows ownership of objects where if we utilize the struct implementing the
Actor
trait we can only give a mutable reference and can't have full ownership of objects inside thepre_start
routine.Essentially if we made the struct mutable from the start, you have to initialize it before calling
spawn
of the actor. This means that if initialization were topanic!
or throw some unhandled error, it would need to be captured manually by the caller instead of getting a cleanerSpawnErr
.
Wouldn't this all be solved if pre_start
could simply return Self
without taking &self
?
#[async_trait]
impl Actor for PingPong {
type Msg = Message;
type Arguments = u32;
async fn pre_start(
_: ActorRef<Self::Msg>,
initial_value: u32,
) -> Result<Self, ActorProcessingErr> {
Ok(initial_value)
}
}
It was a design choice, but this seemed like a safer pattern to me when creating it to prevent unhandled
panic
's from accidentally taking down the caller.As another anecdote, imagine your "root" actor
panic!
s in it's initialization. Withoutpre_start
capturing it for you, you might crash your app where you could potentially handle the error.
Another idea would be to use a kind of "factory" to start actors.
Actor::spawn(MyActor { state: 123 }); // Like this if MyActor cannot fail.
Actor::try_spawn(move || MyActor::new(123).unwrap()); // This could fail, but won't panic outside the scope.
This means the pre_start method is optional, and all the methods would take &mut self
.
In my opionion, removing the State
associated type would make things much simpler.
from ractor.
So there's an open problem in Rust which we're looking at addressing, in that even if a panic is caught, the context isn't capturable. We'll likely be proposing some upstream core Rust change to support this, but at the moment if a panic is unwinding, and we catch_unwind
, the backtrace can't be caught and propagated to understand where an error occurred. This was the reason for adding ActorProcessingErr
in the crate, so you could return a better typed error with both an underlying error context along with a backtrace to understand the root of an actor exiting due to error.
By making a change like this, if you try_spawn
and it panic's you would catch it, but any logging infra / etc wouldn't know where it was caused. Perhaps a closure which returns an ActorProcessingErr might make sense, but then this new syntax is getting heavier/uglier.
from ractor.
The way I think of it is that the data in the Actor is like config, whereas its State is the dynamic runtime state. The distinction may seem moot for the simple case but I find it very valuable when using a Factory which means that for every logical actor (Factory) there's distinct state for each worker (actor instance).
This would work better if Factories were more transparent (ie don't change the channel type).
from ractor.
Related Issues (20)
- How to communicate between local actors and remote actors across hosts using ractor? HOT 1
- quickstart bugs HOT 1
- protobuf-src build requires autotools, which is not available on windows (by default) HOT 4
- bug in monte_carlo example HOT 2
- SpawnErr is misleading HOT 3
- Bidirectional linking can cause stack overflow on actor shutdown
- `CallResult` should return errors that occured handling the message HOT 2
- Add `Scope`-> `GroupName` mapping HOT 3
- Mod Driver Aplikasi Fake GPS HOT 1
- About section needs update for async-std
- Support `async fn` in traits. HOT 1
- Request for TCP Echo Server Example with TcpListener and TcpStream as Actors HOT 1
- Enum contains type of itself HOT 4
- Add support to downcast a BoxedMessage to get a reference to it's wrapped type without consuming it HOT 4
- When panic=abort is on, panic is not captured. HOT 1
- Lifetimes do not match method in trait HOT 2
- Subscriber-Driven OutputPort Subscriptions
- Enhancing OutputPort Backpressure Handling via RecvError::Lagged Management and Buffer Configurability HOT 6
- `post_stop` of children are being called when supervisor fails. HOT 1
- Not depend protobuf-src on windows HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ractor.