Closed blueforesticarus closed 2 weeks ago
If I understand correctly, could this be solved by using only tell
requests between the actors instead of ask
? That way, your actor which needs to mutate the state can handle the initial request, and then tell a message to some other part of your app (actor pool, tokio task, etc), and then when that other part finished processing, it sends a different tell
message to the original actor which can finalize whatever it needs to using its &mut self
access.
Would this approach possibly solve your issue? Its the more "pure" way of messaging between actors and can be pretty powerful.
Yes, that is an option.
Here is my counterpoint: there is a reason kameo supports ask requests.
It is common and useful to have that bidirectional request-style communication. In my mind the greatest benefit is that it makes actors kinda like async objects (in the java/oop sense), where the message passing looks like functions. I think this is an easier model to think-in than channels (and also the reason why alot of net protocols are also request response, rather than bidirectional pubsub); it's hard to think about control flow when the response is disconnected from the request ("ie. the data/event goes here, then here, then eventually works its way back around to the caller, hopefully...").
Here is my stab at a current way to do it.
In the course of writing this, this feels more solid. I'll try it out and post some code.
A side note: one of the things making my head hurt here is the difference between fast and slow async. Ie. putting something in an async queue is fast, network requests are slow. When designing things, one kind has to know how long they expect any given .await to block for and when and why.
Kameo does let you get control of the reply oneshot channel on the Context struct using .reply_sender(). You can store this and reply at any later time which might give you some of the flexibility you're looking for
A random thought, but async tasks could probably be written to take a RefCell
( Then the question is what polls the tasks, and how would tasks be defined and queued )
Motivation
Lets say my actor represents a client to an API. Among the things this actor does is request data on Items. The requests are batched using an internal queue and a separate task, but we want the actor to be able for the individual items. The initial handling of the request does need &mut, (to add items to the queue), but waiting on the result does not need (and cannot hold up) the &mut Self.
ie. it is a class of problem which has a sequential mutable part, and a concurrent part (and really it might need the &mut after the current part as well.)
Proposed Solution
None. Want to open this discussion.
Alternatives Considered
Returning a one-shot channel.