akka / akka-meta

This repository is dedicated to high-level feature discussions and for persisting design decisions.
Apache License 2.0
201 stars 23 forks source link

coexistence of typed and untyped actors #26

Open rkuhn opened 8 years ago

rkuhn commented 8 years ago

The purpose of this issue is to illuminate to which degree we shall support typed and untyped actors to coexist and collaborate—within the same ActorSystem as well as across systems (in-JVM; remoting would probably be a different topic).

The base assumption is that untyped actors will not go away anytime soon.

Another assumption I’m making is that the internals of remote & cluster will be reformulated and included in Akka Typed eventually. APIs for Persistence are not yet considered, but for streams it should be enough to add some new sinks and sources plus a new Materializer.

So, what we should discuss here is which operations shall be supported between typed and untyped actors on the different ActorSystem implementations.

jducoeur commented 7 years ago

A few thoughts from the POV of a user who does lot with untyped but is very naive about typed at this point: my primary goal for the interaction is to enable evolution from my current purely-untyped world to eventually being primarily or entirely typed. (Since the only plausible way I will ever move to typed is if I can evolve my application piece by piece.)

That being the case, from a thousand-foot view my highest priority is to be able to create a new (or rewritten) Actor in the typed world, expose its API in proper typed fashion, and be able to invoke that API with a reasonable minimum of boilerplate from the untyped world while that evolution is happening. I don't expect that invocation to be anywhere near as easy as it a typed-to-typed call, but it should be predictable and decently easy to understand.

It might be helpful for a typed Actor to be able to call an untyped one -- I could see this arising for a while if it turns out that the dependencies are complex -- but I suspect that's significantly lower priority.

jducoeur commented 7 years ago

Oh, and regarding one ActorSystem or two: I think I care only because of serialization cost. The goal of location transparency aside, in practice I have Actor troupes that need to be co-located on the same node because they are passing around some potentially enormous (multi-megabyte in extreme cases) immutable structures. It's crucial that those messages not be serialized, and much of my architecture depends on that. This is the one potential gotcha of two separate ActorSystems -- if messages between them required serialization, it might well leave me without any practical evolutionary path. If they don't need serialization, I suspect it wouldn't be too difficult...

patriknw commented 7 years ago

Thanks for input @jducoeur. I agree that this integration is crucial for the success of Akka Typed and Akka at large.

rkuhn commented 7 years ago

Yes, thanks for writing these down! Currently the following are possible:

What is not supported is DeathWatch between typed and untyped in any direction.

Concerning the interoperation of typed and untyped ActorSystem in the same JVM: no serialization is necessary if the ActorRefs (typed or untyped) are just directly passed around and used—there is no reason for an ActorRef to be sensitive to which code is calling its tell method.

The question is whether this is good enough.

jducoeur commented 7 years ago

Okay, good. Next question, on:

How does this work with Sharding? Specifically, is it possible for my cluster-sharded Entities to be typed?

The thing is, most of my code is in fairly complex troupes, each living under a Sharded Entity. (This is why I was such a booster for Sharding while Patrik was writing it -- it's central to my architecture.) The root of each troupe is a SpaceRouter, which is responsible for owning the lifecycle of all of the members of the troupe, and routing messages (based mainly on marker traits).

So since the SpaceRouter is the root of the troupe, according to the above limitation it would probably need to be the first thing to become a Typed Actor. But it is created by the Sharding Region -- which, last I checked, was still in the old world.

So I suspect that's my immediate gating factor: I probably can't start looking at this seriously until Sharding gets ported to the Typed world. Not a disaster, mind -- I won't have time to start playing with this for several months anyway, but I want to keep thinking about when it becomes plausible to start seriously experimenting with this stuff.

The DeathWatch limitation is one I need to pay attention to, but probably isn't too serious in my case -- I don't actually use DW too often anyway.

(And just FYI, I'll be covering Akka Typed briefly tomorrow, in my "Survey of Akka" presentation, basically in the context of "these are the weaknesses of current Akka and this is how they're being addressed down the road". Trying to get people excited about this project, since I think it's important...)

rkuhn commented 7 years ago

Since October several things have changed, most notably due to the native Akka Typed implementation: now there are two paths to consider.

ActorSystemAdapter

This implementation is based upon an untyped ActorSystem and typed adapters for ActorContext, ActorRef, Props, ActorSystem. The mechanics are therefore fully compatible between the typed and untyped worlds, since there is no new typed implementation.

ActorSystemImpl

This is a completely new implementation for the whole ActorCell and system, with great internal simplifications and much less configurability—lots of complications from the untyped system have been removed. This makes the implementation faster, in particular due to the abolishment of the Envelope that no longer needs to be allocated for every message dispatch.

One of the greater simplifications is that supervision mechanics have been moved from the parent into the child actor; therefore no suspend/resume/restart is needed anymore, removing the hairiest part of the old dungeon. This unfortunately also means that a new typed actor cannot supervise an old untyped ActorCell—the parent–child protocol has been changed.

It might be possible to create a new old-style ActorCell with limited supervisability, i.e. with the same “every uncaught exception is a failure that will stop the actor” semantics as the new typed implementation. This would serve as an adapter that enables the new system to create untyped actors—which is crucial in order to reuse the implementations of remoting, clustering, persistence, etc. When going this route we will also need to create a full complement of ActorRef adapters in both directions with the capability of DeathWatch between typed and untyped parts; semantically that should not be a problem, but it can be tricky to get the adapters’ lifecycle right.

The Plan

If the hybrid ActorCell can be created then we could offer full compatibility between typed and untyped concerning actor creation, allowing the reuse of all nice infrastructure. We will still want to create an optimized ActorMaterializer to benefit from the potentially allocation-free stream message passing, but we should be able to get clustering (including sharding) going relatively quickly. Usage of the APIs (e.g. for Persistence) can be made type-safe by wrapping the exposed ActorRefs with their appropriately typed counterparts.

Then, over the coming months we can slowly and carefully look into translating parts to Akka Typed natively—for reasons of performance as well as internal type-safety.

In general we should strive for 100% equivalence of the ActorSystemImpl and ActorSystemAdapter. The tests are currently set up to validate that, and it should stay that way as we expand feature coverage.

jducoeur commented 7 years ago

Excellent! Sounds like it's moving towards usable for serious code faster than I had hoped...