SlideShare a Scribd company logo
Практика Akka Streams
Алексей Романчук
2
Обо мне
3
4
Обо мне
• Знаете синтаксис Scala
• Знакомы со стандартной библиотекой Scala
• Слышали про Reactive Streams
• Видели Akka Streams*
5
О вас
В предыдущих сериях
T
T
Iterable[T]
T
Iterable[T]
Future[T]
T
Iterable[T]
Future[T]
Source[T]
• Реализуют спецификацию Reactive Streams
• Основаны на Akka
• Умеют Backpressure
• Статически типизированы
8
Akka Streams
9
Ключевые абстракции
Source SinkFlow
Базовые комбинаторы
11
Source
Source.single(1)

Source.failed(new Exception())

Source.empty[Int]



Source.repeat(1)

Source.fromIterator(() => Iterator(1, 2, 3))

Source.cycle(() => Iterator(1, 2, 3))



Source.tick(1 second, 100 millis, ())
11
Source
Source.single(1)

Source.failed(new Exception())

Source.empty[Int]



Source.repeat(1)

Source.fromIterator(() => Iterator(1, 2, 3))

Source.cycle(() => Iterator(1, 2, 3))



Source.tick(1 second, 100 millis, ())
11
Source
Source.single(1)

Source.failed(new Exception())

Source.empty[Int]



Source.repeat(1)

Source.fromIterator(() => Iterator(1, 2, 3))

Source.cycle(() => Iterator(1, 2, 3))



Source.tick(1 second, 100 millis, ())
11
Source
Source.single(1)

Source.failed(new Exception())

Source.empty[Int]



Source.repeat(1)

Source.fromIterator(() => Iterator(1, 2, 3))

Source.cycle(() => Iterator(1, 2, 3))



Source.tick(1 second, 100 millis, ())
11
Source
Source.single(1)

Source.failed(new Exception())

Source.empty[Int]



Source.repeat(1)

Source.fromIterator(() => Iterator(1, 2, 3))

Source.cycle(() => Iterator(1, 2, 3))



Source.tick(1 second, 100 millis, ())
11
Source
Source.single(1)

Source.failed(new Exception())

Source.empty[Int]



Source.repeat(1)

Source.fromIterator(() => Iterator(1, 2, 3))

Source.cycle(() => Iterator(1, 2, 3))



Source.tick(1 second, 100 millis, ())
11
Source
Source.single(1)

Source.failed(new Exception())

Source.empty[Int]



Source.repeat(1)

Source.fromIterator(() => Iterator(1, 2, 3))

Source.cycle(() => Iterator(1, 2, 3))



Source.tick(1 second, 100 millis, ())
11
Source
Source.single(1)

Source.failed(new Exception())

Source.empty[Int]



Source.repeat(1)

Source.fromIterator(() => Iterator(1, 2, 3))

Source.cycle(() => Iterator(1, 2, 3))



Source.tick(1 second, 100 millis, ())
11
Source
Source.single(1)

Source.failed(new Exception())

Source.empty[Int]



Source.repeat(1)

Source.fromIterator(() => Iterator(1, 2, 3))

Source.cycle(() => Iterator(1, 2, 3))



Source.tick(1 second, 100 millis, ())
12
Sink
Sink.ignore

Sink.cancelled

Sink.foreach[Int](println)



Sink.head

Sink.headOption

Sink.last

Sink.lastOption



Sink.fold(0)(_ + _)

Sink.reduce[Int](_ + _)
12
Sink
Sink.ignore

Sink.cancelled

Sink.foreach[Int](println)



Sink.head

Sink.headOption

Sink.last

Sink.lastOption



Sink.fold(0)(_ + _)

Sink.reduce[Int](_ + _)
12
Sink
Sink.ignore

Sink.cancelled

Sink.foreach[Int](println)



Sink.head

Sink.headOption

Sink.last

Sink.lastOption



Sink.fold(0)(_ + _)

Sink.reduce[Int](_ + _)
12
Sink
Sink.ignore

Sink.cancelled

Sink.foreach[Int](println)



Sink.head

Sink.headOption

Sink.last

Sink.lastOption



Sink.fold(0)(_ + _)

Sink.reduce[Int](_ + _)
12
Sink
Sink.ignore

Sink.cancelled

Sink.foreach[Int](println)



Sink.head

Sink.headOption

Sink.last

Sink.lastOption



Sink.fold(0)(_ + _)

Sink.reduce[Int](_ + _)
12
Sink
Sink.ignore

Sink.cancelled

Sink.foreach[Int](println)



Sink.head

Sink.headOption

Sink.last

Sink.lastOption



Sink.fold(0)(_ + _)

Sink.reduce[Int](_ + _)
12
Sink
Sink.ignore

Sink.cancelled

Sink.foreach[Int](println)



Sink.head

Sink.headOption

Sink.last

Sink.lastOption



Sink.fold(0)(_ + _)

Sink.reduce[Int](_ + _)
13
Flow
Flow[Int].map(identity)

Flow[Int].mapAsync(10)(Future.successful)

Flow[Int].mapAsyncUnordered(10)(Future.successful)



Flow[Int].filter(_ % 2 == 0)

Flow[Int].collect {

case n if n % 2 == 0 => n

}
Flow[Int].take(10)

Flow[Int].takeWhile(_ > 10)

Flow[Int].drop(10)

Flow[Int].dropWhile(_ > 10)
13
Flow
Flow[Int].map(identity)

Flow[Int].mapAsync(10)(Future.successful)

Flow[Int].mapAsyncUnordered(10)(Future.successful)



Flow[Int].filter(_ % 2 == 0)

Flow[Int].collect {

case n if n % 2 == 0 => n

}
Flow[Int].take(10)

Flow[Int].takeWhile(_ > 10)

Flow[Int].drop(10)

Flow[Int].dropWhile(_ > 10)
13
Flow
Flow[Int].map(identity)

Flow[Int].mapAsync(10)(Future.successful)

Flow[Int].mapAsyncUnordered(10)(Future.successful)



Flow[Int].filter(_ % 2 == 0)

Flow[Int].collect {

case n if n % 2 == 0 => n

}
Flow[Int].take(10)

Flow[Int].takeWhile(_ > 10)

Flow[Int].drop(10)

Flow[Int].dropWhile(_ > 10)
13
Flow
Flow[Int].map(identity)

Flow[Int].mapAsync(10)(Future.successful)

Flow[Int].mapAsyncUnordered(10)(Future.successful)



Flow[Int].filter(_ % 2 == 0)

Flow[Int].collect {

case n if n % 2 == 0 => n

}
Flow[Int].take(10)

Flow[Int].takeWhile(_ > 10)

Flow[Int].drop(10)

Flow[Int].dropWhile(_ > 10)
13
Flow
Flow[Int].map(identity)

Flow[Int].mapAsync(10)(Future.successful)

Flow[Int].mapAsyncUnordered(10)(Future.successful)



Flow[Int].filter(_ % 2 == 0)

Flow[Int].collect {

case n if n % 2 == 0 => n

}
Flow[Int].take(10)

Flow[Int].takeWhile(_ > 10)

Flow[Int].drop(10)

Flow[Int].dropWhile(_ > 10)
13
Flow
Flow[Int].map(identity)

Flow[Int].mapAsync(10)(Future.successful)

Flow[Int].mapAsyncUnordered(10)(Future.successful)



Flow[Int].filter(_ % 2 == 0)

Flow[Int].collect {

case n if n % 2 == 0 => n

}
Flow[Int].take(10)

Flow[Int].takeWhile(_ > 10)

Flow[Int].drop(10)

Flow[Int].dropWhile(_ > 10)
13
Flow
Flow[Int].map(identity)

Flow[Int].mapAsync(10)(Future.successful)

Flow[Int].mapAsyncUnordered(10)(Future.successful)



Flow[Int].filter(_ % 2 == 0)

Flow[Int].collect {

case n if n % 2 == 0 => n

}
Flow[Int].take(10)

Flow[Int].takeWhile(_ > 10)

Flow[Int].drop(10)

Flow[Int].dropWhile(_ > 10)
13
Flow
Flow[Int].map(identity)

Flow[Int].mapAsync(10)(Future.successful)

Flow[Int].mapAsyncUnordered(10)(Future.successful)



Flow[Int].filter(_ % 2 == 0)

Flow[Int].collect {

case n if n % 2 == 0 => n

}
Flow[Int].take(10)

Flow[Int].takeWhile(_ > 10)

Flow[Int].drop(10)

Flow[Int].dropWhile(_ > 10)
14
Flow
Flow[Int].flatMapConcat(n =>

Source.fromIterator(() => Iterator.range(1, n))

)
1 2 3 Х
14
Flow
Flow[Int].flatMapConcat(n =>

Source.fromIterator(() => Iterator.range(1, n))

)
1 2 3 Х
1 Х
14
Flow
Flow[Int].flatMapConcat(n =>

Source.fromIterator(() => Iterator.range(1, n))

)
1 2 3 Х
1 Х 1 2 Х
14
Flow
Flow[Int].flatMapConcat(n =>

Source.fromIterator(() => Iterator.range(1, n))

)
1 2 3 Х
1 Х 1 2 Х 1 2 3 Х
14
Flow
Flow[Int].flatMapConcat(n =>

Source.fromIterator(() => Iterator.range(1, n))

)
1 2 3 Х
1 Х 1 2 Х 1 2 3 Х
1 1 2 1 2 3 Х
Пример №1
• Прочитать с хадупа логи транзакций и найти там 100
примеров фродных транзакций
16
Задача
List Files APIRead Line Result
17
Наивная реализация
def checkFraud(in: String): Future[Option[TransactionId]]
= ???
val result: List[TransactionId] = (for {

file <- hdfs.listStatusIterator(path)

if file.isFile

line <-fromInputStream(fs.open(file.getPath)).getLines()

resultOpt = Await.result(checkFraud(line), 10 seconds)

result <- resultOpt

} yield result)
.take(100).toList
17
Наивная реализация
def checkFraud(in: String): Future[Option[TransactionId]]
= ???
val result: List[TransactionId] = (for {

file <- hdfs.listStatusIterator(path)

if file.isFile

line <-fromInputStream(fs.open(file.getPath)).getLines()

resultOpt = Await.result(checkFraud(line), 10 seconds)

result <- resultOpt

} yield result)
.take(100).toList
17
Наивная реализация
def checkFraud(in: String): Future[Option[TransactionId]]
= ???
val result: List[TransactionId] = (for {

file <- hdfs.listStatusIterator(path)

if file.isFile

line <-fromInputStream(fs.open(file.getPath)).getLines()

resultOpt = Await.result(checkFraud(line), 10 seconds)

result <- resultOpt

} yield result)
.take(100).toList
17
Наивная реализация
def checkFraud(in: String): Future[Option[TransactionId]]
= ???
val result: List[TransactionId] = (for {

file <- hdfs.listStatusIterator(path)

if file.isFile

line <-fromInputStream(fs.open(file.getPath)).getLines()

resultOpt = Await.result(checkFraud(line), 10 seconds)

result <- resultOpt

} yield result)
.take(100).toList
17
Наивная реализация
def checkFraud(in: String): Future[Option[TransactionId]]
= ???
val result: List[TransactionId] = (for {

file <- hdfs.listStatusIterator(path)

if file.isFile

line <-fromInputStream(fs.open(file.getPath)).getLines()

resultOpt = Await.result(checkFraud(line), 10 seconds)

result <- resultOpt

} yield result)
.take(100).toList
17
Наивная реализация
def checkFraud(in: String): Future[Option[TransactionId]]
= ???
val result: List[TransactionId] = (for {

file <- hdfs.listStatusIterator(path)

if file.isFile

line <-fromInputStream(fs.open(file.getPath)).getLines()

resultOpt = Await.result(checkFraud(line), 10 seconds)

result <- resultOpt

} yield result)
.take(100).toList
17
Наивная реализация
def checkFraud(in: String): Future[Option[TransactionId]]
= ???
val result: List[TransactionId] = (for {

file <- hdfs.listStatusIterator(path)

if file.isFile

line <-fromInputStream(fs.open(file.getPath)).getLines()

resultOpt = Await.result(checkFraud(line), 10 seconds)

result <- resultOpt

} yield result)
.take(100).toList
17
Наивная реализация
def checkFraud(in: String): Future[Option[TransactionId]]
= ???
val result: List[TransactionId] = (for {

file <- hdfs.listStatusIterator(path)

if file.isFile

line <-fromInputStream(fs.open(file.getPath)).getLines()

resultOpt = Await.result(checkFraud(line), 10 seconds)

result <- resultOpt

} yield result)
.take(100).toList
17
Наивная реализация
def checkFraud(in: String): Future[Option[TransactionId]]
= ???
val result: List[TransactionId] = (for {

file <- hdfs.listStatusIterator(path)

if file.isFile

line <-fromInputStream(fs.open(file.getPath)).getLines()

resultOpt = Await.result(checkFraud(line), 10 seconds)

result <- resultOpt

} yield result)
.take(100).toList
17
Наивная реализация
def checkFraud(in: String): Future[Option[TransactionId]]
= ???
val result: List[TransactionId] = (for {

file <- hdfs.listStatusIterator(path)

if file.isFile

line <-fromInputStream(fs.open(file.getPath)).getLines()

resultOpt = Await.result(checkFraud(line), 10 seconds)

result <- resultOpt

} yield result)
.take(100).toList
17
Наивная реализация
def checkFraud(in: String): Future[Option[TransactionId]]
= ???
val result: List[TransactionId] = (for {

file <- hdfs.listStatusIterator(path)

if file.isFile

line <-fromInputStream(fs.open(file.getPath)).getLines()

resultOpt = Await.result(checkFraud(line), 10 seconds)

result <- resultOpt

} yield result)
.take(100).toList
Ок?
• Не терять лишнего времени на скачивание
• Параллельные запросы к сервису
• Не превышать ограничения в 10 запросов в секунду
19
Требования
20
Красивая картинка со схемой
List Files APIRead Line Result
21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

21
Красивый код на стримах
val stream =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

Все на стандартных
комбинаторах
23
Запуск
val result: Future[List[TransactionId]] = stream.run()


val result2: Future[List[TransactionId]] = stream.run()
24
Запуск
List Files APIRead Line Result
24
Запуск
List Files APIRead Line Result
run()
Future Stream
24
Запуск
List Files APIRead Line Result
run()
Future Stream
run()
Future Stream
Материализация
Чертеж → Деталь
27
RunnableGraph
RunnableGraph[+Mat] {
def run(): Mat
}
28
Mat
final class Source[+Out, +Mat]
final class Flow[-In, +Out, +Mat]
final class Sink[-In, +Mat]
29
Sources
case object NotUsed
def single[T](element: T)
def empty[T]
def failed[T](cause: Throwable)
def repeat[T](element: T)
def fromIterator[T](f: () => Iterator[T])
def cycle[T](f: () => Iterator[T])
30
Sinks
def ignore: Sink[Any, Future[Done]]
def foreach[T](f: T => Unit): Sink[T, Future[Done]]
def head[T]: Sink[T, Future[T]]
def headOption[T]: Sink[T, Future[Option[T]]]
def fold[U, T](z: U)(f: (U, T) => U): Sink[T, Future[U]]
def reduce[T](f: (T, T) => T): Sink[T, Future[T]]
30
Sinks
def ignore: Sink[Any, Future[Done]]
def foreach[T](f: T => Unit): Sink[T, Future[Done]]
def head[T]: Sink[T, Future[T]]
def headOption[T]: Sink[T, Future[Option[T]]]
def fold[U, T](z: U)(f: (U, T) => U): Sink[T, Future[U]]
def reduce[T](f: (T, T) => T): Sink[T, Future[T]]
30
Sinks
def ignore: Sink[Any, Future[Done]]
def foreach[T](f: T => Unit): Sink[T, Future[Done]]
def head[T]: Sink[T, Future[T]]
def headOption[T]: Sink[T, Future[Option[T]]]
def fold[U, T](z: U)(f: (U, T) => U): Sink[T, Future[U]]
def reduce[T](f: (T, T) => T): Sink[T, Future[T]]
30
Sinks
def ignore: Sink[Any, Future[Done]]
def foreach[T](f: T => Unit): Sink[T, Future[Done]]
def head[T]: Sink[T, Future[T]]
def headOption[T]: Sink[T, Future[Option[T]]]
def fold[U, T](z: U)(f: (U, T) => U): Sink[T, Future[U]]
def reduce[T](f: (T, T) => T): Sink[T, Future[T]]
30
Sinks
def ignore: Sink[Any, Future[Done]]
def foreach[T](f: T => Unit): Sink[T, Future[Done]]
def head[T]: Sink[T, Future[T]]
def headOption[T]: Sink[T, Future[Option[T]]]
def fold[U, T](z: U)(f: (U, T) => U): Sink[T, Future[U]]
def reduce[T](f: (T, T) => T): Sink[T, Future[T]]
30
Sinks
def ignore: Sink[Any, Future[Done]]
def foreach[T](f: T => Unit): Sink[T, Future[Done]]
def head[T]: Sink[T, Future[T]]
def headOption[T]: Sink[T, Future[Option[T]]]
def fold[U, T](z: U)(f: (U, T) => U): Sink[T, Future[U]]
def reduce[T](f: (T, T) => T): Sink[T, Future[T]]
30
Sinks
def ignore: Sink[Any, Future[Done]]
def foreach[T](f: T => Unit): Sink[T, Future[Done]]
def head[T]: Sink[T, Future[T]]
def headOption[T]: Sink[T, Future[Option[T]]]
def fold[U, T](z: U)(f: (U, T) => U): Sink[T, Future[U]]
def reduce[T](f: (T, T) => T): Sink[T, Future[T]]
30
Sinks
def ignore: Sink[Any, Future[Done]]
def foreach[T](f: T => Unit): Sink[T, Future[Done]]
def head[T]: Sink[T, Future[T]]
def headOption[T]: Sink[T, Future[Option[T]]]
def fold[U, T](z: U)(f: (U, T) => U): Sink[T, Future[U]]
def reduce[T](f: (T, T) => T): Sink[T, Future[T]]
31
Композиция
val source: Source[Int, NotUsed] = Source.single(1)

val sink: Sink[Any, Future[Done]] = Sink.ignore



val s1: RunnableGraph[NotUsed] = source.to(sink)



val s2: RunnableGraph[Future[Done]] =

source.toMat(sink)(Keep.right)



val s3: RunnableGraph[(NotUsed, Future[Done])] =

source.toMat(sink)(Keep.both)

31
Композиция
val source: Source[Int, NotUsed] = Source.single(1)

val sink: Sink[Any, Future[Done]] = Sink.ignore



val s1: RunnableGraph[NotUsed] = source.to(sink)



val s2: RunnableGraph[Future[Done]] =

source.toMat(sink)(Keep.right)



val s3: RunnableGraph[(NotUsed, Future[Done])] =

source.toMat(sink)(Keep.both)

31
Композиция
val source: Source[Int, NotUsed] = Source.single(1)

val sink: Sink[Any, Future[Done]] = Sink.ignore



val s1: RunnableGraph[NotUsed] = source.to(sink)



val s2: RunnableGraph[Future[Done]] =

source.toMat(sink)(Keep.right)



val s3: RunnableGraph[(NotUsed, Future[Done])] =

source.toMat(sink)(Keep.both)

31
Композиция
val source: Source[Int, NotUsed] = Source.single(1)

val sink: Sink[Any, Future[Done]] = Sink.ignore



val s1: RunnableGraph[NotUsed] = source.to(sink)



val s2: RunnableGraph[Future[Done]] =

source.toMat(sink)(Keep.right)



val s3: RunnableGraph[(NotUsed, Future[Done])] =

source.toMat(sink)(Keep.both)

31
Композиция
val source: Source[Int, NotUsed] = Source.single(1)

val sink: Sink[Any, Future[Done]] = Sink.ignore



val s1: RunnableGraph[NotUsed] = source.to(sink)



val s2: RunnableGraph[Future[Done]] =

source.toMat(sink)(Keep.right)



val s3: RunnableGraph[(NotUsed, Future[Done])] =

source.toMat(sink)(Keep.both)

31
Композиция
val source: Source[Int, NotUsed] = Source.single(1)

val sink: Sink[Any, Future[Done]] = Sink.ignore



val s1: RunnableGraph[NotUsed] = source.to(sink)



val s2: RunnableGraph[Future[Done]] =

source.toMat(sink)(Keep.right)



val s3: RunnableGraph[(NotUsed, Future[Done])] =

source.toMat(sink)(Keep.both)

32
Композиция
33
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =
Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

33
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =
Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

33
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =
Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

33
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =
Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

34
Красивая картинка со схемой
List Files APIRead Line Result
run()
Stream
run()
Future StreamFuture
34
Красивая картинка со схемой
List Files APIRead Line Result
run()
Future
Stream
run()
Future StreamFuture
Пример №2
• Читать данные из очереди и обрабатывать.
36
Задача
Source Process Sink
Future
37
Красивый код на стримах
val source = ZMQSource(context,

mode = ZMQ.PULL,

timeout = 1 second,

addresses = List("tcp: //127.0.0.1:12345")

)



def process(in: ByteString): Future[Int] = ???
37
Красивый код на стримах
val source = ZMQSource(context,

mode = ZMQ.PULL,

timeout = 1 second,

addresses = List("tcp: //127.0.0.1:12345")

)



def process(in: ByteString): Future[Int] = ???
37
Красивый код на стримах
val source = ZMQSource(context,

mode = ZMQ.PULL,

timeout = 1 second,

addresses = List("tcp: //127.0.0.1:12345")

)



def process(in: ByteString): Future[Int] = ???
37
Красивый код на стримах
val source = ZMQSource(context,

mode = ZMQ.PULL,

timeout = 1 second,

addresses = List("tcp: //127.0.0.1:12345")

)



def process(in: ByteString): Future[Int] = ???
38
Красивый код на стримах
val stream = source

.mapAsync(10)(process)

.toMat(Sink.last)(Keep.right)



val result: Future[Int] = stream.run()

result.onComplete(_ => "We are done here")

38
Красивый код на стримах
val stream = source

.mapAsync(10)(process)

.toMat(Sink.last)(Keep.right)



val result: Future[Int] = stream.run()

result.onComplete(_ => "We are done here")

38
Красивый код на стримах
val stream = source

.mapAsync(10)(process)

.toMat(Sink.last)(Keep.right)



val result: Future[Int] = stream.run()

result.onComplete(_ => "We are done here")

38
Красивый код на стримах
val stream = source

.mapAsync(10)(process)

.toMat(Sink.last)(Keep.right)



val result: Future[Int] = stream.run()

result.onComplete(_ => "We are done here")

38
Красивый код на стримах
val stream = source

.mapAsync(10)(process)

.toMat(Sink.last)(Keep.right)



val result: Future[Int] = stream.run()

result.onComplete(_ => "We are done here")

39
Красивая картинка со схемой
Source Process Sink
Future
39
Красивая картинка со схемой
Source Process Sink
Future
StreamFuture
Как это остановить?
41
Проблема остановки
val stream = source

.mapAsync(10)(process)

.toMat(Sink.last)(Keep.right)



val result: Future[Int] = stream.run()

result.onComplete(_ => "We are done here")

42
Проблема остановки
Source Process Sink
Future
42
Проблема остановки
Source Process Sink
FutureControl
42
Проблема остановки
Source Process Sink
Future
StreamControl
Control
Future
43
Проблема остановки
trait Control {

/**

* Disconnect the underlying ZMQ socket, deliver the
remaining data and finally close the socket.

*/

def gracefulStop(): Unit

}
44
Проблема остановки
val source: Source[ByteString, Control] = ???
val stream: RunnableGraph[(Control, Future[Int])] =
source

.mapAsync(10)(process)

.toMat(Sink.head)(Keep.both)



val (control: Control, result: Future[Int]) = stream.run()

result.onComplete(_ => "We are done here")

control.gracefulStop()
44
Проблема остановки
val source: Source[ByteString, Control] = ???
val stream: RunnableGraph[(Control, Future[Int])] =
source

.mapAsync(10)(process)

.toMat(Sink.head)(Keep.both)



val (control: Control, result: Future[Int]) = stream.run()

result.onComplete(_ => "We are done here")

control.gracefulStop()
44
Проблема остановки
val source: Source[ByteString, Control] = ???
val stream: RunnableGraph[(Control, Future[Int])] =
source

.mapAsync(10)(process)

.toMat(Sink.head)(Keep.both)



val (control: Control, result: Future[Int]) = stream.run()

result.onComplete(_ => "We are done here")

control.gracefulStop()
44
Проблема остановки
val source: Source[ByteString, Control] = ???
val stream: RunnableGraph[(Control, Future[Int])] =
source

.mapAsync(10)(process)

.toMat(Sink.head)(Keep.both)



val (control: Control, result: Future[Int]) = stream.run()

result.onComplete(_ => "We are done here")

control.gracefulStop()
44
Проблема остановки
val source: Source[ByteString, Control] = ???
val stream: RunnableGraph[(Control, Future[Int])] =
source

.mapAsync(10)(process)

.toMat(Sink.head)(Keep.both)



val (control: Control, result: Future[Int]) = stream.run()

result.onComplete(_ => "We are done here")

control.gracefulStop()
44
Проблема остановки
val source: Source[ByteString, Control] = ???
val stream: RunnableGraph[(Control, Future[Int])] =
source

.mapAsync(10)(process)

.toMat(Sink.head)(Keep.both)



val (control: Control, result: Future[Int]) = stream.run()

result.onComplete(_ => "We are done here")

control.gracefulStop()
Пример №3
46
Механика
Flow[T]
46
Механика
Flow[T]
Request
Cancel
46
Механика
Flow[T]
Request Request
Cancel Cancel
46
Механика
Flow[T]
Request Request
T
Error
Complete
Cancel Cancel
46
Механика
Flow[T]
T
Error
Complete
Request Request
T
Error
Complete
Cancel Cancel
• Emit элемента
• Завершение
• Ошибка
• Backpressure
• Отмена
47
Что нужно знать про stages
48
Свой Source
val s: Source[Int, ActorRef] =

Source.actorPublisher[Int](Props(new MySourceActor))



class MySourceActor extends ActorPublisher[Int] {

override def receive: Receive = {

case ActorPublisherMessage.Request(n) =>

onNext(100)

onCompleteThenStop()

onErrorThenStop(new Exception)

case ActorPublisherMessage.Cancel =>

context.stop(self)

}

}

48
Свой Source
val s: Source[Int, ActorRef] =

Source.actorPublisher[Int](Props(new MySourceActor))



class MySourceActor extends ActorPublisher[Int] {

override def receive: Receive = {

case ActorPublisherMessage.Request(n) =>

onNext(100)

onCompleteThenStop()

onErrorThenStop(new Exception)

case ActorPublisherMessage.Cancel =>

context.stop(self)

}

}

48
Свой Source
val s: Source[Int, ActorRef] =

Source.actorPublisher[Int](Props(new MySourceActor))



class MySourceActor extends ActorPublisher[Int] {

override def receive: Receive = {

case ActorPublisherMessage.Request(n) =>

onNext(100)

onCompleteThenStop()

onErrorThenStop(new Exception)

case ActorPublisherMessage.Cancel =>

context.stop(self)

}

}

48
Свой Source
val s: Source[Int, ActorRef] =

Source.actorPublisher[Int](Props(new MySourceActor))



class MySourceActor extends ActorPublisher[Int] {

override def receive: Receive = {

case ActorPublisherMessage.Request(n) =>

onNext(100)

onCompleteThenStop()

onErrorThenStop(new Exception)

case ActorPublisherMessage.Cancel =>

context.stop(self)

}

}

48
Свой Source
val s: Source[Int, ActorRef] =

Source.actorPublisher[Int](Props(new MySourceActor))



class MySourceActor extends ActorPublisher[Int] {

override def receive: Receive = {

case ActorPublisherMessage.Request(n) =>

onNext(100)

onCompleteThenStop()

onErrorThenStop(new Exception)

case ActorPublisherMessage.Cancel =>

context.stop(self)

}

}

48
Свой Source
val s: Source[Int, ActorRef] =

Source.actorPublisher[Int](Props(new MySourceActor))



class MySourceActor extends ActorPublisher[Int] {

override def receive: Receive = {

case ActorPublisherMessage.Request(n) =>

onNext(100)

onCompleteThenStop()

onErrorThenStop(new Exception)

case ActorPublisherMessage.Cancel =>

context.stop(self)

}

}

48
Свой Source
val s: Source[Int, ActorRef] =

Source.actorPublisher[Int](Props(new MySourceActor))



class MySourceActor extends ActorPublisher[Int] {

override def receive: Receive = {

case ActorPublisherMessage.Request(n) =>

onNext(100)

onCompleteThenStop()

onErrorThenStop(new Exception)

case ActorPublisherMessage.Cancel =>

context.stop(self)

}

}

48
Свой Source
val s: Source[Int, ActorRef] =

Source.actorPublisher[Int](Props(new MySourceActor))



class MySourceActor extends ActorPublisher[Int] {

override def receive: Receive = {

case ActorPublisherMessage.Request(n) =>

onNext(100)

onCompleteThenStop()

onErrorThenStop(new Exception)

case ActorPublisherMessage.Cancel =>

context.stop(self)

}

}

48
Свой Source
val s: Source[Int, ActorRef] =

Source.actorPublisher[Int](Props(new MySourceActor))



class MySourceActor extends ActorPublisher[Int] {

override def receive: Receive = {

case ActorPublisherMessage.Request(n) =>

onNext(100)

onCompleteThenStop()

onErrorThenStop(new Exception)

case ActorPublisherMessage.Cancel =>

context.stop(self)

}

}

48
Свой Source
val s: Source[Int, ActorRef] =

Source.actorPublisher[Int](Props(new MySourceActor))



class MySourceActor extends ActorPublisher[Int] {

override def receive: Receive = {

case ActorPublisherMessage.Request(n) =>

onNext(100)

onCompleteThenStop()

onErrorThenStop(new Exception)

case ActorPublisherMessage.Cancel =>

context.stop(self)

}

}

49
Reactive Zmq
case object GracefulStop

case object DeliverMore

class MySourceActor(addr: String)
extends ActorPublisher[Array[Byte]] {

var conn: ZMQ.Socket = ???



override def preStart(): Unit = {

conn.connect(addr)

}



override def postStop(): Unit = {

conn.disconnect(addr)

}

49
Reactive Zmq
case object GracefulStop

case object DeliverMore

class MySourceActor(addr: String)
extends ActorPublisher[Array[Byte]] {

var conn: ZMQ.Socket = ???



override def preStart(): Unit = {

conn.connect(addr)

}



override def postStop(): Unit = {

conn.disconnect(addr)

}

49
Reactive Zmq
case object GracefulStop

case object DeliverMore

class MySourceActor(addr: String)
extends ActorPublisher[Array[Byte]] {

var conn: ZMQ.Socket = ???



override def preStart(): Unit = {

conn.connect(addr)

}



override def postStop(): Unit = {

conn.disconnect(addr)

}

49
Reactive Zmq
case object GracefulStop

case object DeliverMore

class MySourceActor(addr: String)
extends ActorPublisher[Array[Byte]] {

var conn: ZMQ.Socket = ???



override def preStart(): Unit = {

conn.connect(addr)

}



override def postStop(): Unit = {

conn.disconnect(addr)

}

49
Reactive Zmq
case object GracefulStop

case object DeliverMore

class MySourceActor(addr: String)
extends ActorPublisher[Array[Byte]] {

var conn: ZMQ.Socket = ???



override def preStart(): Unit = {

conn.connect(addr)

}



override def postStop(): Unit = {

conn.disconnect(addr)

}

49
Reactive Zmq
case object GracefulStop

case object DeliverMore

class MySourceActor(addr: String)
extends ActorPublisher[Array[Byte]] {

var conn: ZMQ.Socket = ???



override def preStart(): Unit = {

conn.connect(addr)

}



override def postStop(): Unit = {

conn.disconnect(addr)

}

49
Reactive Zmq
case object GracefulStop

case object DeliverMore

class MySourceActor(addr: String)
extends ActorPublisher[Array[Byte]] {

var conn: ZMQ.Socket = ???



override def preStart(): Unit = {

conn.connect(addr)

}



override def postStop(): Unit = {

conn.disconnect(addr)

}

50
Reactive Zmq
override def receive: Receive = {

case ActorPublisherMessage.Request(_) | DeliverMore =>

Option(conn.recv()) match {

case Some(msg) =>

onNext(msg)

if(totalDemand > 0) self ! DeliverMore

case None => self ! DeliverMore

}

case ActorPublisherMessage.Cancel | GracefulStop =>

conn.disconnect(addr)

onCompleteThenStop()

}

50
Reactive Zmq
override def receive: Receive = {

case ActorPublisherMessage.Request(_) | DeliverMore =>

Option(conn.recv()) match {

case Some(msg) =>

onNext(msg)

if(totalDemand > 0) self ! DeliverMore

case None => self ! DeliverMore

}

case ActorPublisherMessage.Cancel | GracefulStop =>

conn.disconnect(addr)

onCompleteThenStop()

}

50
Reactive Zmq
override def receive: Receive = {

case ActorPublisherMessage.Request(_) | DeliverMore =>

Option(conn.recv()) match {

case Some(msg) =>

onNext(msg)

if(totalDemand > 0) self ! DeliverMore

case None => self ! DeliverMore

}

case ActorPublisherMessage.Cancel | GracefulStop =>

conn.disconnect(addr)

onCompleteThenStop()

}

50
Reactive Zmq
override def receive: Receive = {

case ActorPublisherMessage.Request(_) | DeliverMore =>

Option(conn.recv()) match {

case Some(msg) =>

onNext(msg)

if(totalDemand > 0) self ! DeliverMore

case None => self ! DeliverMore

}

case ActorPublisherMessage.Cancel | GracefulStop =>

conn.disconnect(addr)

onCompleteThenStop()

}

50
Reactive Zmq
override def receive: Receive = {

case ActorPublisherMessage.Request(_) | DeliverMore =>

Option(conn.recv()) match {

case Some(msg) =>

onNext(msg)

if(totalDemand > 0) self ! DeliverMore

case None => self ! DeliverMore

}

case ActorPublisherMessage.Cancel | GracefulStop =>

conn.disconnect(addr)

onCompleteThenStop()

}

50
Reactive Zmq
override def receive: Receive = {

case ActorPublisherMessage.Request(_) | DeliverMore =>

Option(conn.recv()) match {

case Some(msg) =>

onNext(msg)

if(totalDemand > 0) self ! DeliverMore

case None => self ! DeliverMore

}

case ActorPublisherMessage.Cancel | GracefulStop =>

conn.disconnect(addr)

onCompleteThenStop()

}

50
Reactive Zmq
override def receive: Receive = {

case ActorPublisherMessage.Request(_) | DeliverMore =>

Option(conn.recv()) match {

case Some(msg) =>

onNext(msg)

if(totalDemand > 0) self ! DeliverMore

case None => self ! DeliverMore

}

case ActorPublisherMessage.Cancel | GracefulStop =>

conn.disconnect(addr)

onCompleteThenStop()

}

50
Reactive Zmq
override def receive: Receive = {

case ActorPublisherMessage.Request(_) | DeliverMore =>

Option(conn.recv()) match {

case Some(msg) =>

onNext(msg)

if(totalDemand > 0) self ! DeliverMore

case None => self ! DeliverMore

}

case ActorPublisherMessage.Cancel | GracefulStop =>

conn.disconnect(addr)

onCompleteThenStop()

}

50
Reactive Zmq
override def receive: Receive = {

case ActorPublisherMessage.Request(_) | DeliverMore =>

Option(conn.recv()) match {

case Some(msg) =>

onNext(msg)

if(totalDemand > 0) self ! DeliverMore

case None => self ! DeliverMore

}

case ActorPublisherMessage.Cancel | GracefulStop =>

conn.disconnect(addr)

onCompleteThenStop()

}

50
Reactive Zmq
override def receive: Receive = {

case ActorPublisherMessage.Request(_) | DeliverMore =>

Option(conn.recv()) match {

case Some(msg) =>

onNext(msg)

if(totalDemand > 0) self ! DeliverMore

case None => self ! DeliverMore

}

case ActorPublisherMessage.Cancel | GracefulStop =>

conn.disconnect(addr)

onCompleteThenStop()

}

50
Reactive Zmq
override def receive: Receive = {

case ActorPublisherMessage.Request(_) | DeliverMore =>

Option(conn.recv()) match {

case Some(msg) =>

onNext(msg)

if(totalDemand > 0) self ! DeliverMore

case None => self ! DeliverMore

}

case ActorPublisherMessage.Cancel | GracefulStop =>

conn.disconnect(addr)

onCompleteThenStop()

}

51
Reactive Zmq
val source: Source[Array[Byte], Control] =

Source.actorPublisher[Array[Byte]](

Props(new MySourceActor( ???))

).mapMaterializedValue { ref =>

new Control {

override def gracefulStop() = ref ! GracefulStop

}

}
51
Reactive Zmq
val source: Source[Array[Byte], Control] =

Source.actorPublisher[Array[Byte]](

Props(new MySourceActor( ???))

).mapMaterializedValue { ref =>

new Control {

override def gracefulStop() = ref ! GracefulStop

}

}
51
Reactive Zmq
val source: Source[Array[Byte], Control] =

Source.actorPublisher[Array[Byte]](

Props(new MySourceActor( ???))

).mapMaterializedValue { ref =>

new Control {

override def gracefulStop() = ref ! GracefulStop

}

}
51
Reactive Zmq
val source: Source[Array[Byte], Control] =

Source.actorPublisher[Array[Byte]](

Props(new MySourceActor( ???))

).mapMaterializedValue { ref =>

new Control {

override def gracefulStop() = ref ! GracefulStop

}

}
51
Reactive Zmq
val source: Source[Array[Byte], Control] =

Source.actorPublisher[Array[Byte]](

Props(new MySourceActor( ???))

).mapMaterializedValue { ref =>

new Control {

override def gracefulStop() = ref ! GracefulStop

}

}
51
Reactive Zmq
val source: Source[Array[Byte], Control] =

Source.actorPublisher[Array[Byte]](

Props(new MySourceActor( ???))

).mapMaterializedValue { ref =>

new Control {

override def gracefulStop() = ref ! GracefulStop

}

}
51
Reactive Zmq
val source: Source[Array[Byte], Control] =

Source.actorPublisher[Array[Byte]](

Props(new MySourceActor( ???))

).mapMaterializedValue { ref =>

new Control {

override def gracefulStop() = ref ! GracefulStop

}

}
52
Свой Sink
val s = Sink.actorSubscriber[Int](Props(new MySinkActor))



class MySinkActor extends ActorSubscriber {

override def receive: Receive = {

case ActorSubscriberMessage.OnNext =>

cancel()

request(100)

case ActorSubscriberMessage.OnComplete =>

case ActorSubscriberMessage.OnError =>

}
52
Свой Sink
val s = Sink.actorSubscriber[Int](Props(new MySinkActor))



class MySinkActor extends ActorSubscriber {

override def receive: Receive = {

case ActorSubscriberMessage.OnNext =>

cancel()

request(100)

case ActorSubscriberMessage.OnComplete =>

case ActorSubscriberMessage.OnError =>

}
52
Свой Sink
val s = Sink.actorSubscriber[Int](Props(new MySinkActor))



class MySinkActor extends ActorSubscriber {

override def receive: Receive = {

case ActorSubscriberMessage.OnNext =>

cancel()

request(100)

case ActorSubscriberMessage.OnComplete =>

case ActorSubscriberMessage.OnError =>

}
52
Свой Sink
val s = Sink.actorSubscriber[Int](Props(new MySinkActor))



class MySinkActor extends ActorSubscriber {

override def receive: Receive = {

case ActorSubscriberMessage.OnNext =>

cancel()

request(100)

case ActorSubscriberMessage.OnComplete =>

case ActorSubscriberMessage.OnError =>

}
52
Свой Sink
val s = Sink.actorSubscriber[Int](Props(new MySinkActor))



class MySinkActor extends ActorSubscriber {

override def receive: Receive = {

case ActorSubscriberMessage.OnNext =>

cancel()

request(100)

case ActorSubscriberMessage.OnComplete =>

case ActorSubscriberMessage.OnError =>

}
52
Свой Sink
val s = Sink.actorSubscriber[Int](Props(new MySinkActor))



class MySinkActor extends ActorSubscriber {

override def receive: Receive = {

case ActorSubscriberMessage.OnNext =>

cancel()

request(100)

case ActorSubscriberMessage.OnComplete =>

case ActorSubscriberMessage.OnError =>

}
52
Свой Sink
val s = Sink.actorSubscriber[Int](Props(new MySinkActor))



class MySinkActor extends ActorSubscriber {

override def receive: Receive = {

case ActorSubscriberMessage.OnNext =>

cancel()

request(100)

case ActorSubscriberMessage.OnComplete =>

case ActorSubscriberMessage.OnError =>

}
52
Свой Sink
val s = Sink.actorSubscriber[Int](Props(new MySinkActor))



class MySinkActor extends ActorSubscriber {

override def receive: Receive = {

case ActorSubscriberMessage.OnNext =>

cancel()

request(100)

case ActorSubscriberMessage.OnComplete =>

case ActorSubscriberMessage.OnError =>

}
52
Свой Sink
val s = Sink.actorSubscriber[Int](Props(new MySinkActor))



class MySinkActor extends ActorSubscriber {

override def receive: Receive = {

case ActorSubscriberMessage.OnNext =>

cancel()

request(100)

case ActorSubscriberMessage.OnComplete =>

case ActorSubscriberMessage.OnError =>

}
Итоги
• Стандартные комбинаторы
• Материализация
• Управление жизненным циклом
• Свои stages
54
Итоги
Серебряная пуля
• Более простая технология не подходит
• Backpressure
• Упорядоченные потоки
• Локальность
• Фиксированная топология
56
Когда стоит использовать
• Документация Akka Streams
• Альпака
• reactive-zmq
• reactive-kafka
• Первое видео про Akka Streams
57
Ссылки
Вопросы?
alexey.romanchuk@gmail.com @1esha
Backpressure
60
Событий слишком много
60
Событий слишком много
Отправитель
60
Событий слишком много
Отправитель Получатель
60
Событий слишком много
Отправитель Получатель
61
Событий слишком много
Отправитель Получатель
62
Событий слишком много
Отправитель Получатель
63
Событий слишком много
Отправитель Получатель
64
Событий слишком много
Отправитель Получатель
65
Событий слишком много
Отправитель Получатель
66
Событий слишком много
Отправитель Получатель
67
Событий слишком много
Отправитель Получатель
68
Блокирующий вызов
Отправитель Получатель
68
Блокирующий вызов
Отправитель Получатель
68
Блокирующий вызов
Отправитель Получатель
69
Pull
Отправитель Получатель
69
Pull
Отправитель Получатель
69
Pull
Отправитель Получатель
70
Negative Acknowledge
Отправитель Получатель
70
Negative Acknowledge
Отправитель Получатель
70
Negative Acknowledge
Отправитель Получатель
71
Negative Acknowledge
Отправитель Получатель
72
Dynamic pull-push
Отправитель Получатель
72
Dynamic pull-push
Отправитель Получатель
4
73
Dynamic pull-push
4
Отправитель Получатель
74
Dynamic pull-push
3
Отправитель Получатель
75
Dynamic pull-push
3
Отправитель Получатель
76
Dynamic pull-push
0
Отправитель Получатель
77
Dynamic pull-push
0
Отправитель Получатель
78
Dynamic pull-push
0
Отправитель Получатель
78
Dynamic pull-push
0
Отправитель Получатель
2
79
Dynamic pull-push
2
Отправитель Получатель
80
Dynamic pull-push
0
Отправитель Получатель
81
Balance
Balance
81
Balance
Balance
81
Balance
Balance
82
Broadcast
Broadcast
82
Broadcast
Broadcast
82
Broadcast
Broadcast
83
Zip
Zip
83
Zip
Zip
83
Zip
Zip
84
Unzip
Unzip
84
Unzip
Unzip
84
Unzip
Unzip
85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)

85
Красивый код на стримах
val stream: RunnableGraph[Future[List[TransactionId]]] =

Source

.fromIterator { () => hdfs.listStatusIterator(path) }

.filter(_.isFile)

.flatMapConcat { file =>

val s = fromInputStream(hdfs.open(file.getPath))

Source.fromIterator(() => s.getLines())

}

.throttle(10, 1 second, 0, ThrottleMode.Shaping)

.mapAsyncUnordered(50)(checkFraud)

.collect { case Some(value) => value }

.take(100)

.fold(List.empty[TransactionId])(_ :+ _)

.toMat(Sink.head)(Keep.right)


More Related Content

What's hot

The Ring programming language version 1.5.3 book - Part 10 of 184
The Ring programming language version 1.5.3 book - Part 10 of 184The Ring programming language version 1.5.3 book - Part 10 of 184
The Ring programming language version 1.5.3 book - Part 10 of 184
Mahmoud Samir Fayed
 
The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212
Mahmoud Samir Fayed
 
2013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 22013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 2
PHP Conference Argentina
 
Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8
XSolve
 
An introduction to functional programming with go
An introduction to functional programming with goAn introduction to functional programming with go
An introduction to functional programming with go
Eleanor McHugh
 
Hitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingHitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional Programming
Sergey Shishkin
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 redux
Eleanor McHugh
 
Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)
jeffz
 
Mcs011 solved assignment by divya singh
Mcs011 solved assignment by divya singhMcs011 solved assignment by divya singh
Mcs011 solved assignment by divya singh
DIVYA SINGH
 
Rのスコープとフレームと環境と
Rのスコープとフレームと環境とRのスコープとフレームと環境と
Rのスコープとフレームと環境と
Takeshi Arabiki
 
Networking Core Concept
Networking Core ConceptNetworking Core Concept
Networking Core Concept
Rays Technologies
 
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
Patrick Allaert
 
Collection Core Concept
Collection Core ConceptCollection Core Concept
Collection Core Concept
Rays Technologies
 
Dts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinDts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlin
Ahmad Arif Faizin
 
Functional Patterns for the non-mathematician
Functional Patterns for the non-mathematicianFunctional Patterns for the non-mathematician
Functional Patterns for the non-mathematician
Brian Lonsdorf
 
The Ring programming language version 1.8 book - Part 75 of 202
The Ring programming language version 1.8 book - Part 75 of 202The Ring programming language version 1.8 book - Part 75 of 202
The Ring programming language version 1.8 book - Part 75 of 202
Mahmoud Samir Fayed
 
Functional Stream Processing with Scalaz-Stream
Functional Stream Processing with Scalaz-StreamFunctional Stream Processing with Scalaz-Stream
Functional Stream Processing with Scalaz-Stream
Adil Akhter
 
The Ring programming language version 1.10 book - Part 54 of 212
The Ring programming language version 1.10 book - Part 54 of 212The Ring programming language version 1.10 book - Part 54 of 212
The Ring programming language version 1.10 book - Part 54 of 212
Mahmoud Samir Fayed
 

What's hot (18)

The Ring programming language version 1.5.3 book - Part 10 of 184
The Ring programming language version 1.5.3 book - Part 10 of 184The Ring programming language version 1.5.3 book - Part 10 of 184
The Ring programming language version 1.5.3 book - Part 10 of 184
 
The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212
 
2013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 22013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 2
 
Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8
 
An introduction to functional programming with go
An introduction to functional programming with goAn introduction to functional programming with go
An introduction to functional programming with go
 
Hitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingHitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional Programming
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 redux
 
Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)
 
Mcs011 solved assignment by divya singh
Mcs011 solved assignment by divya singhMcs011 solved assignment by divya singh
Mcs011 solved assignment by divya singh
 
Rのスコープとフレームと環境と
Rのスコープとフレームと環境とRのスコープとフレームと環境と
Rのスコープとフレームと環境と
 
Networking Core Concept
Networking Core ConceptNetworking Core Concept
Networking Core Concept
 
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
 
Collection Core Concept
Collection Core ConceptCollection Core Concept
Collection Core Concept
 
Dts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinDts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlin
 
Functional Patterns for the non-mathematician
Functional Patterns for the non-mathematicianFunctional Patterns for the non-mathematician
Functional Patterns for the non-mathematician
 
The Ring programming language version 1.8 book - Part 75 of 202
The Ring programming language version 1.8 book - Part 75 of 202The Ring programming language version 1.8 book - Part 75 of 202
The Ring programming language version 1.8 book - Part 75 of 202
 
Functional Stream Processing with Scalaz-Stream
Functional Stream Processing with Scalaz-StreamFunctional Stream Processing with Scalaz-Stream
Functional Stream Processing with Scalaz-Stream
 
The Ring programming language version 1.10 book - Part 54 of 212
The Ring programming language version 1.10 book - Part 54 of 212The Ring programming language version 1.10 book - Part 54 of 212
The Ring programming language version 1.10 book - Part 54 of 212
 

Similar to Практическое применения Akka Streams

Java 8 Stream API (Valdas Zigas)
Java 8 Stream API (Valdas Zigas)Java 8 Stream API (Valdas Zigas)
Java 8 Stream API (Valdas Zigas)
Kaunas Java User Group
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 
Kotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is coming
Kirill Rozov
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streams
Bartosz Sypytkowski
 
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data EcosystemWprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Sages
 
Fs2 - Crash Course
Fs2 - Crash CourseFs2 - Crash Course
Fs2 - Crash Course
Lukasz Byczynski
 
Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015
Leonardo Borges
 
CAVE Overview
CAVE OverviewCAVE Overview
CAVE Overview
vdumitrescu
 
Let if flow: Java 8 Streams puzzles and more
Let if flow: Java 8 Streams puzzles and moreLet if flow: Java 8 Streams puzzles and more
Let if flow: Java 8 Streams puzzles and more
Bhakti Mehta
 
Introduction to Apache Flink
Introduction to Apache FlinkIntroduction to Apache Flink
Introduction to Apache Flink
mxmxm
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)関数潮流(Function Tendency)
関数潮流(Function Tendency)
riue
 
Guava - Elements of Functional Programming
Guava - Elements of Functional Programming Guava - Elements of Functional Programming
Guava - Elements of Functional Programming
Anna Shymchenko
 
Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0
Oscar Renalias
 
FS2 for Fun and Profit
FS2 for Fun and ProfitFS2 for Fun and Profit
FS2 for Fun and Profit
Adil Akhter
 
Streaming Data Flow with Apache Flink @ Paris Flink Meetup 2015
Streaming Data Flow with Apache Flink @ Paris Flink Meetup 2015Streaming Data Flow with Apache Flink @ Paris Flink Meetup 2015
Streaming Data Flow with Apache Flink @ Paris Flink Meetup 2015
Till Rohrmann
 
ITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function ProgrammingITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function Programming
Istanbul Tech Talks
 
Reactive stream processing using Akka streams
Reactive stream processing using Akka streams Reactive stream processing using Akka streams
Reactive stream processing using Akka streams
Johan Andrén
 
To Infinity & Beyond: Protocols & sequences in Node - Part 2
To Infinity & Beyond: Protocols & sequences in Node - Part 2To Infinity & Beyond: Protocols & sequences in Node - Part 2
To Infinity & Beyond: Protocols & sequences in Node - Part 2
Bahul Neel Upadhyaya
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
Baishampayan Ghose
 
Practical RxJava for Android
Practical RxJava for AndroidPractical RxJava for Android
Practical RxJava for Android
Tomáš Kypta
 

Similar to Практическое применения Akka Streams (20)

Java 8 Stream API (Valdas Zigas)
Java 8 Stream API (Valdas Zigas)Java 8 Stream API (Valdas Zigas)
Java 8 Stream API (Valdas Zigas)
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Kotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is coming
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streams
 
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data EcosystemWprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
 
Fs2 - Crash Course
Fs2 - Crash CourseFs2 - Crash Course
Fs2 - Crash Course
 
Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015
 
CAVE Overview
CAVE OverviewCAVE Overview
CAVE Overview
 
Let if flow: Java 8 Streams puzzles and more
Let if flow: Java 8 Streams puzzles and moreLet if flow: Java 8 Streams puzzles and more
Let if flow: Java 8 Streams puzzles and more
 
Introduction to Apache Flink
Introduction to Apache FlinkIntroduction to Apache Flink
Introduction to Apache Flink
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)関数潮流(Function Tendency)
関数潮流(Function Tendency)
 
Guava - Elements of Functional Programming
Guava - Elements of Functional Programming Guava - Elements of Functional Programming
Guava - Elements of Functional Programming
 
Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0
 
FS2 for Fun and Profit
FS2 for Fun and ProfitFS2 for Fun and Profit
FS2 for Fun and Profit
 
Streaming Data Flow with Apache Flink @ Paris Flink Meetup 2015
Streaming Data Flow with Apache Flink @ Paris Flink Meetup 2015Streaming Data Flow with Apache Flink @ Paris Flink Meetup 2015
Streaming Data Flow with Apache Flink @ Paris Flink Meetup 2015
 
ITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function ProgrammingITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function Programming
 
Reactive stream processing using Akka streams
Reactive stream processing using Akka streams Reactive stream processing using Akka streams
Reactive stream processing using Akka streams
 
To Infinity & Beyond: Protocols & sequences in Node - Part 2
To Infinity & Beyond: Protocols & sequences in Node - Part 2To Infinity & Beyond: Protocols & sequences in Node - Part 2
To Infinity & Beyond: Protocols & sequences in Node - Part 2
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
 
Practical RxJava for Android
Practical RxJava for AndroidPractical RxJava for Android
Practical RxJava for Android
 

Recently uploaded

Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
The Third Creative Media
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
ToXSL Technologies
 
What’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete RoadmapWhat’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete Roadmap
Envertis Software Solutions
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
Peter Muessig
 
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
kalichargn70th171
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
Karya Keeper
 
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabhQuarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
aisafed42
 
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdfTop Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
VALiNTRY360
 
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
kalichargn70th171
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
Bert Jan Schrijver
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
rodomar2
 
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
safelyiotech
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
dakas1
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
Hornet Dynamics
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
ShulagnaSarkar2
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
Sven Peters
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
Remote DBA Services
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Peter Caitens
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
Maitrey Patel
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
Peter Muessig
 

Recently uploaded (20)

Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
 
What’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete RoadmapWhat’s New in Odoo 17 – A Complete Roadmap
What’s New in Odoo 17 – A Complete Roadmap
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
 
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
 
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabhQuarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
 
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdfTop Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
 
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
 
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
 

Практическое применения Akka Streams