Ответ 1
Средство материализации, создающее результаты graph
Материализатор делает actors выполнение графика для получения этих результатов.
Граф в его простейшей форме состоит из источника, который предоставляет элементы, и приемника, который потребляет элементы.
Здесь источник, который предоставляет диапазон целых чисел (в этом примере целые числа являются нашими элементами):
val source = Source(1 to 10)
И вот раковина, которая суммирует все целые числа, получаемые от источника:
val sink = Sink.fold[Int, Int](0)(_ + _)
Мы подключаем источник и приемник для получения графика:
val graph = source.toMat(sink)(Keep.right)
Учтите, что никакие вычисления, добавление в нашем случае, не выполняются при создании графика. Код declarative, графики описывают, как мы хотим преобразовать наши данные, но это еще одно задание для фактического выполнения вычислений: Графы чертежи.
Теперь, как насчет материализатора? Материализатор принимает меры, когда мы запускаем график:
implicit val materializer = ActorMaterializer()
val futureResult = graph.run()
Когда мы run()
на графике, материализатор берет граф и заставляет актеров выполнять преобразования данных, указанные в графе (в этом примере он добавляет целые числа).
Возможно, было бы полезно представить график в качестве чертежа для построения дома, материализатора, как мастера, который смотрит на чертеж, рассказывая строителям, как построить дом в соответствии с планом. Строители этой аналогии соответствуют актерам Акки.
Причина, по которой теперь работают несколько частей вашего кода, заключается в том, что с помощью материализатора вы предоставляете способ выполнения графиков. Графы в основном используются в Akka HTTP, который используется для использования HTTP-запросов и ответов.
WSClient, о котором вы упомянули в своем комментарии, конечно, использует графики для выполнения своих запросов и, следовательно, нуждается в материализаторе.
Вот полный пример создания и запуска графика:
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Keep, Sink, Source}
object Graphs extends App {
// The start of our simple graph. It provides elements, integers in our case
val source = Source(1 to 10)
// The end of our graph. It processes the source elements
val sink = Sink.fold[Int, Int](0)(_ + _)
/*
* Connect source and sink.
* Keep only the output values (i.e., the graph right side).
* Note that this is declarative: no result is computed until we run the graph.
*/
val graph = source.toMat(sink)(Keep.right)
// The system coordinates actors and provides threads for them
implicit val actorSystem = ActorSystem()
// The materializer makes actors execute graphs
implicit val materializer = ActorMaterializer()
// Running the graph means that the materializer assigns actors to execute
// the graph from start (source) to end (sink)
val futureResult = graph.run()
// Use the actor system execution context, which provides threads,
// to print the result of running the graph
implicit val executionContext = actorSystem.dispatcher
futureResult.foreach(res => println(s"Result of running the graph: $res"))
actorSystem.terminate().foreach(_ => println("System is shut down"))
}
Поместите libraryDependencies += "com.typesafe.akka" %% "akka-stream" % "2.5.3"
в свой build.sbt
, чтобы сделать библиотеку потока Akka доступной в вашем коде.
Здесь больше об источниках и стоках.