-
-
Notifications
You must be signed in to change notification settings - Fork 289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Get rid of static/singletons ? #431
Comments
I've thought about changing that as well. I think Roger and I have discussed it at some point, but tbh I can't remember why we decided not to change it 😅 I'd say that if we do change it then it should be for solving an important use case, e.g. if we want to have support for isolating actors or exposing multiple GRPC endpoints within a single process, and not out of language/design purism. |
TLDR; if you have instances of remoting, then the serialization layer needs to understand what instance it should deserialize its messages for, context aware messages. This puts an enormous burden on the serializer and forces you to use custom serialization schemes. |
Thinking about it, now with the new API with context.Send. this might not be an issue as the context will know the context so to say :-) |
Ok, it's on my "will do if time" list. |
@rogeralsing Not sure if you remember exactly what you were thinking 256 days ago 😄 But how would we go about this more precisely? Should we just move e.g. the static logger factory to the context instance? In that case what about remoting? Would we have a "remote context" inheriting from the root context but adding the remote-specific instances like the server, serialization config, internal processes, etc? |
Let's see if I remember the reasoning here. Deserilizing ActorRef in Akka.NET was a pain as it needs to be attached to the ActorSystem it belonged to. This lead to the static API. But, now that Tell has moved onto the context, e.g RootContext, ActorContext. e.g. if the process registry was not static, but an instance. |
Pseudo: var registry = new ProcessRegistry();
var rootContext = new RootContext(registry);
var pid = rootContext.SpawnNamed(props, "MyActor");
rootContext.Send(pid, message); Through all of this code, we know the context and what registry to use. |
This would even work for remoting. if remoting is started on a given port for a given processregistry. |
Yes! Feels very much in line with the protoactor approach. I always kind of liked the ActorSystem in Akka since it's a fully isolated encapsulation of a set of actors. One thing though - is there any reason to separate the registry from the root context (by |
You can set up different middleware for the rootcontext. |
I like the idea of the ActorSystem. Haven't worked with Akka but used it in Orleankka. One of the issues I have with Proto.Actor is that I cannot get an existing actor from the system by name unless I keep track of spun up actors myself. I had to work around this issue by creating my own ActorRegistry. Concerning the ability to have multiple actor systems or root contexts in one application, I am not sure. Is there a use-case for it. to have two separate actor systems in one app? Isn't that the idea to have all actors to talk to each other within and outside the process boundaries? |
Yes and this is AFAIK how it works in Erlang. Also, having things static, makes it hard to configure things. |
So would the use case be if you have the same set of actors exposed on different endpoints (possibly different transports) and you want to configure different actor middlewares per endpoint? I'm not disregarding the idea completely, but I'm unsure if there is a case for it. As I recall it, the reason for introducing middlewares originally was basically to have reusable "behaviors" that you can easily inject via the Props, whereas the reason for the root context was to be able to propagate metadata within messages sent between actors and across remote boundaries. I don't see either of those cases being hurt by having a 1:1 relationship between registry and context. |
Let's say you have Web API endpoints and NServiceBus endpoints, and you use Zipkin. in one case you would have something like:
And in the other case:
|
But isn't Erlang a very different beast since the VM itself has a process abstraction such that the Erlang processes don't need to cater for out-of-(OS-)-process communications? I'm all for emulating the good parts about Erlang but replicating the (quite peculiar) behaviors of it's VM in other VM's feels like it might be taking it too far. I believe we said at some point that the core concepts of protoactor should remain the same across languages/platforms, but it should also stay idiomatic to those. :) |
@rogeralsing I might be missing something, but in that example wouldn't you anyway be manually picking up a request/message from WebAPI/NSB and forwarding it to an actor? If so, couldn't you just wrap it in a MessageEnvelope yourself and add the appropriate headers? |
Maybe :-) |
True but internally we can do whatever we want 😉 We should be able to quite easily bypass app-level middlewares for system-level actors/processes, no? |
Yes absolutely. But, fiddling with the MessageEnvelope is smelly IMO. |
From the user/app perspective yes. But wouldn't you typically wrap that in your own middleware/glue-code anyway such that it doesn't touch your app code? E.g. let's say your app subscribes to messages from and routes them to internal actors; for any non-trivial app I'd prolly write a small middleware layer to handle that routing; would it really be smelly to handle MessageEnvelopes within that routing layer?
I do agree though that if we could hide/avoid the need for fiddling with the MessageEnvelope directly and create some sort of abstraction around it, that'd prolly be better :) |
As far as statics are concerned, I may have started making an What else should be done? |
I can only speak for the issues I encountered in #462 At the moment it is difficult (not impossible) to write good tests to simulate remote failure scenarios. Being able to spin up multiple actor systems within the same process and be able to connect / disconnect them from each other to ensure that remote systems recover correctly from failure would be of great benefit IMHO. Looking back through the comments on this issue it seems like the process registry needs to be tied to the actor system and that Proto.Remote needs to be refactored to allow two actor systems to talk to each other within the same process (presumably listening on different ports) I am not sure if this is what is needed to support #467 too. |
Done |
Hello @rogeralsing, @cpx86
Can I ask why you design such static/singletons stuffs ?
I was the Remote unit test, confirming that the only way to test such thing is to run another process.
Don't you think it could be better if we get rid if all these singletons and encapsulate them into some root "ActorSystem" instance, so we can start mutliple ActorSystem in a unit test more easily ?
Would it then possible to have multiple GRPC endpoint (associated with distinct/isolated ActorSystems) again in order to easier Remote tests ?
The text was updated successfully, but these errors were encountered: