Live resources in Akka Stream flow description

346 views Asked by At

There is this note in the akka-stream docs stating as follows:

… a reusable flow description cannot be bound to “live” resources, any connection to or allocation of such resources must be deferred until materialization time. Examples of “live” resources are already existing TCP connections, a multicast Publisher, etc.; …

I have several questions concerning the note:

  • Apart from the these two examples, what other resource counts as a live?
    • Anything that cannot be safely (deep)copied? Like a Thread?
    • Should I also avoid sharing anything that's not thread-safe?
  • What about an ActorRef existing in the ActorSystem used by the ActorFlowMaterializer?
  • How to defer allocation until materialization time? Is it safe for example to allocate it in the constructor of a PushPullStage but not in the create function of a FlowGraph?
1

There are 1 answers

0
Afsin Buyuksarac On BEST ANSWER

The problem here is a common problem if we consider webservices, RMI connections or any other communication protocol. It's always recommended sharing "primitive" values then references, because marshalling/unmarshalling or serializing/unserializing is always a headache. Also think of different types of environments communicating each other. Sharing solid values is a safe way to solve communication.

Akka by itself is a good example of "microservices" communicating actors each other. When I read the documentation of Akka, one good word defines Akka actors very well. Actors are like mailbox clients and you can think of each client has a mailbox. When you pass a variable, it's just like you got a new email.

Short result of long story, be avoid sharing "dependent" objects that can be invalidated before it's read from another actor. Additionally, if your system names actorRefs dynamically, avoid calling them by its reference.

"Materializing" is explained in docs of akka-streams.

The process of materialization may be parameterized, e.g. instantiating a blueprint for handling a TCP connection’s data with specific information about the connection’s address and port information. Additionally, materialization will often create specific objects that are useful to interact with the processing engine once it is running, for example for shutting it down or for extracting metrics. This means that the materialization function takes a set of parameters from the outside and it produces a set of results. Compositionality demands that these two sets cannot interact, because that would establish a covert channel by which different pieces could communicate, leading to problems of initialization order and inscrutable runtime failures.

So use parameters instead of passing "connection" itself.

Deferring a live resource is not a big think. That means if you use one connection for all system, you should keep it alive always. Or when you create a transaction in actor-1 and send it to actor-2, you shouldn't terminate the transaction in actor-1 until actor-2 finished its job with transaction.

Then how you can understand ? Then you use "Future" and "offer()".

Hope I understand your question and hope I can express myself.