Making actor non reentrant

I don't see how actors have any influence here; if you have many instances of ChatCache or whatever, you just make the caller responsible for passing you a valid live instance (or you have a function that selects a live handle), the overall signature of the getMessages function can remain the same, and ChatCache could even be a struct of pointers for what it's worth.

It doesn't matter, it's called in all situations where you need to get a list of N most recent messages. If all N messages are available in memory and the cache isn't contended, the function doesn't suspend; if it needs to reach out to the server or the cache is contended, it has to suspend and thus the function is async. For pagination, there's typically a separate function with an argument that tells what message to paginate from, but otherwise the signature is the same, and this function will also be async.

I'm not talking about data access layer abstractions, but rather live instance part. ChatCache just hides it away database part. That db is a shared state here—if db node fails, it means whole system fails. This can be improved by adding several nodes, but then it brings more complexity with data replication and etc.
Actor as a concurrent primitive trying to fix those problems—you can wrap some part of this logic, have only writes to db of this part, read db only on actor restart and etc. Best part if some node fails—you can quickly restart this actor on different node, while others will just have a bit of lag.

So it's just sync mechanism? :thinking: Think this matters a lot, you have two states on client and server, which you always sync. With 1mil. clients this will be very problematic to handle.


Think biggest misunderstanding here is what exactly a system—it's not iOS client, it's iOS + backend. Of course then having ChatRoom on client doesn't make sense, it should be on backend and for client it's just some ID. And client is another actor (theoretically). But what I don't get is why complicating it with cache and etc., when client can just be stateless with websocket connection? :thinking:

And out of server world, this also applicable to client apps as well. Of course there are no nodes and load that can make them to fail. But the idea of actor isolating such actions on a separate concurrency domain is still remain relevant, allowing to think in terms of this domains and their interactions.

This is only true to the most simple apps, like if you want to add support chat in the app, that is perfectly fine strategy. But we have moved out of stateless clients that just load information from the server long time ago, I think. You have to have cached data, deal with various types of chats (take that some support p2p and server-synced), local state and even so-called "offline" mode, when you can effectively write message and get it delivered once connection is here (+ handling temporary connection lost). There is so much going on in modern client applications, that their complexity is far beyond being stateless readers of server state. That is only can be held true for some web apps (and justified for web), but on mobile devices you have to be rich-featured app that, probably, has only one difference from the servers – no need to handle huge load.

1 Like

Yeah, of course. Tbh when you start to treat code as it can always fail—actors is a very nice primitive.

This mostly relates to Guest <-> ChatRoom example, for something more complex there will be just different abstractions on client side (like MessageQueue and etc.).

1 Like

Yeah, that was probably my poor choice of the example/its description with ChatRoom. Chat room is indeed bad abstraction on a client in that form as you and @nkbelov were talking about. My intention was to consider complex chat behaviour, that involves various parties, abstracting over the entire complexity of the feature(s).

1 Like

Would you be willing to share your macro implementation, would be curious to try it out

1 Like

Of course : GitHub - martiall/swift-nonreentrant-actor: Macro to implement some kind of non-reentrant actor in Swift

2 Likes