9

I am new to Akka Stream and have only started reading its docs as of last week. I am able to understand most of the concepts but I am finding it hard to understand what Materialized Value means in Akka stream and what its significance is?.

If somebody could explain this to me with a real world example that would help a lot in co-relating it and its use cases in Akka Stream.

Update

I was going through below example and wanted to understand the two different kind of output that we get for the same graph. I know it has direct relation with the Materialized Value and that's why I asked the above question.

  implicit val system = ActorSystem("PlainSinkProducerMain")
  implicit val materializer = ActorMaterializer()
  val source = Source(1 to 10)
  val sink = Sink.fold[Int, Int](0)(_ + _)
  val runnable: RunnableGraph[Future[Int]] =
  source.toMat(sink)(Keep.right)
  val sum1: Future[Int] = runnable.run()
  val sum2: Future[Int] = runnable.run()
   println(sum1.value)
   println(sum2.value)

When I run this I get below output :

None
Some(Success(55))

The above example is from the docs and below is the explanation of it.

Since a stream can be materialized multiple times, the materialized value will also be calculated anew for each such materialization, usually leading to different values being returned each time. In the example below we create two running materialized instance of the stream that we described in the runnable variable, and both materializations give us a different Future from the map even though we used the same sink to refer to the future.

I have 2 questions here: 1) Why the 2 different Materialized Instance of same graph have 2 different output values? Although the materialized value is calculated twice but under the hood both the calculation are for same graph.

2) Why the return type is Some(Success(55)) instead of a plain 55 for successful execution and Failure Exception for failed cases? (This might be dumb questions but I want to understand what problem/advantage does this special return value solves/gives.)

Explorer
  • 1,491
  • 4
  • 26
  • 67
  • 2
    Possible duplicate of [Akka Streams: What does Mat represents in Source\[out, Mat\]](https://stackoverflow.com/questions/39727729/akka-streams-what-does-mat-represents-in-sourceout-mat) – Vladimir Matveev Aug 03 '17 at 15:46
  • @VladimirMatveev Thanks for your comment, I read your explanation and it was really helpful. What I understood from your explanation is that the `Future[Int]` says that the Materialization of graph will give a Integer value in future if it completes successfully or it will give a Failure msg. I want to know what was the motivation for this design? and why a plain success and failure msg was not thrown? Is it because it is running `Asynchronously` and other task will use `Future[Int]` value to determine whether any error is occurred or not at a particular time instance 'T'? – Explorer Aug 03 '17 at 16:18
  • 1
    Finally, if you have additional questions, on stackoverflow you need to create separate topics for them. – Vladimir Matveev Aug 03 '17 at 16:30
  • `Therefore, even if the stream terminates immediately, it is not guaranteed that the value will be available immediately` this line explains the reason of having `Future[Int]`. Thanks for the other comments too, that helped a lot in understanding the design advantage that Akka Stream brings. – Explorer Aug 03 '17 at 16:30
  • @VladimirMatveev If you can put all those comments in answer section I can mark it as correct answer as it answered all the doubts that I had. – Explorer Aug 03 '17 at 16:32
  • Done. The answers turned out to be longer than I expected :) – Vladimir Matveev Aug 03 '17 at 16:35

1 Answers1

8

(answer to the comment) I'm not sure I understand your question entirely, but in general streams are asynchronous, and when you execute run() to materialize a stream, it starts executing in a different thread pool. Therefore, even if the stream terminates immediately, it is not guaranteed that the value will be available immediately. That's why the result of the Sink.fold is Future[T] - futures means values which are going to be available "in future", and this is exactly the semantics which is needed here.

"why ... have 2 different values" - precisely because of the asynchronicity. In your case it happened that the second future has been completed before you observed it, but the first one has not. If you run this program multiple times, it is likely you will get different results.

"why the return type is Some(Success(55))..." well, that's how the futures in Scala are designed. The Future.value method returns Option[Try[T]], that is, it returns None if the future is not completed at the moment of the invocation and Some(v) if it is completed, where v is either Success(result) or Failure(throwable). In general, in Scala it is idiomatic to treat errors as values instead of exceptions which implicitly unroll the call stack when thrown.

Note that you usually do not use Future.value when working with futures. Usually you transform futures with combinators like map, flatMap or Future.sequence, and then either pass the result of the final transformed future to some library (e.g. as an HTTP response in a web framework) or use a method like Await.result(future, timeout) to get the final result of the future or an exception, if the future is not completed during the specified time frame.

Vladimir Matveev
  • 120,085
  • 34
  • 287
  • 296