SlideShare ist ein Scribd-Unternehmen logo
1 von 248
Downloaden Sie, um offline zu lesen
Практика 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
• Слайды этой презентации - goo.gl/F7EYoE
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)


Weitere ähnliche Inhalte

Was ist angesagt?

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 184Mahmoud 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 212Mahmoud Samir Fayed
 
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 8XSolve
 
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 goEleanor McHugh
 
Hitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingHitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingSergey 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 reduxEleanor 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 singhDIVYA SINGH
 
Rのスコープとフレームと環境と
Rのスコープとフレームと環境とRのスコープとフレームと環境と
Rのスコープとフレームと環境とTakeshi Arabiki
 
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, ItalyPatrick Allaert
 
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 kotlinAhmad Arif Faizin
 
Functional Patterns for the non-mathematician
Functional Patterns for the non-mathematicianFunctional Patterns for the non-mathematician
Functional Patterns for the non-mathematicianBrian 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 202Mahmoud Samir Fayed
 
Functional Stream Processing with Scalaz-Stream
Functional Stream Processing with Scalaz-StreamFunctional Stream Processing with Scalaz-Stream
Functional Stream Processing with Scalaz-StreamAdil 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 212Mahmoud Samir Fayed
 

Was ist angesagt? (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
 

Andere mochten auch

«Построение Read Model-ей с использованием потоков событий» — Денис Иванов, 2ГИС
«Построение Read Model-ей с использованием потоков событий» — Денис Иванов, 2ГИС«Построение Read Model-ей с использованием потоков событий» — Денис Иванов, 2ГИС
«Построение Read Model-ей с использованием потоков событий» — Денис Иванов, 2ГИС2ГИС Технологии
 
«Тестируем мобильное приложение в суровых реалиях Интернета» – Андрей Усов, 2ГИС
«Тестируем мобильное приложение в суровых реалиях Интернета» – Андрей Усов, 2ГИС«Тестируем мобильное приложение в суровых реалиях Интернета» – Андрей Усов, 2ГИС
«Тестируем мобильное приложение в суровых реалиях Интернета» – Андрей Усов, 2ГИС2ГИС Технологии
 
Winium — это как Selenium, только под Windows
Winium — это как Selenium, только под WindowsWinium — это как Selenium, только под Windows
Winium — это как Selenium, только под WindowsSQALab
 
«Система развёртывания многокомпонентного сервиса» — Алексей Салов, YaC 2013
«Система развёртывания многокомпонентного сервиса» — Алексей Салов, YaC 2013«Система развёртывания многокомпонентного сервиса» — Алексей Салов, YaC 2013
«Система развёртывания многокомпонентного сервиса» — Алексей Салов, YaC 20132ГИС Технологии
 
«Карта в браузере: путь от спутникового снимка до пользователя» – Илья Тарату...
«Карта в браузере: путь от спутникового снимка до пользователя» – Илья Тарату...«Карта в браузере: путь от спутникового снимка до пользователя» – Илья Тарату...
«Карта в браузере: путь от спутникового снимка до пользователя» – Илья Тарату...2ГИС Технологии
 
«Badger — инструмент для мониторинга качества продуктов» – Ирина Шрейдер, 2ГИС
«Badger — инструмент для мониторинга качества продуктов» – Ирина Шрейдер, 2ГИС«Badger — инструмент для мониторинга качества продуктов» – Ирина Шрейдер, 2ГИС
«Badger — инструмент для мониторинга качества продуктов» – Ирина Шрейдер, 2ГИС2ГИС Технологии
 
«Автоматизация тестовой инфраструктуры в 2ГИС» — Антон Голицын, 2ГИС
«Автоматизация тестовой инфраструктуры в 2ГИС» — Антон Голицын, 2ГИС«Автоматизация тестовой инфраструктуры в 2ГИС» — Антон Голицын, 2ГИС
«Автоматизация тестовой инфраструктуры в 2ГИС» — Антон Голицын, 2ГИС2ГИС Технологии
 
«5 историй про метрики в 2ГИС» — Игнат Аникеев, 2ГИС
«5 историй про метрики в 2ГИС» — Игнат Аникеев, 2ГИС«5 историй про метрики в 2ГИС» — Игнат Аникеев, 2ГИС
«5 историй про метрики в 2ГИС» — Игнат Аникеев, 2ГИС2ГИС Технологии
 
«Как работают менеджеры продукта в 2ГИС»  – Павел Мочалкин, 2ГИС
 «Как работают менеджеры продукта в 2ГИС»  – Павел Мочалкин, 2ГИС «Как работают менеджеры продукта в 2ГИС»  – Павел Мочалкин, 2ГИС
«Как работают менеджеры продукта в 2ГИС»  – Павел Мочалкин, 2ГИС2ГИС Технологии
 
«Путь от монолита на PHP к микросервисам на Scala» – Денис Иванов, 2ГИС
«Путь от монолита на PHP к микросервисам на Scala» – Денис Иванов, 2ГИС «Путь от монолита на PHP к микросервисам на Scala» – Денис Иванов, 2ГИС
«Путь от монолита на PHP к микросервисам на Scala» – Денис Иванов, 2ГИС 2ГИС Технологии
 
«Рефакторим орг. структуру» – Степан Колесников, 2ГИС
«Рефакторим орг. структуру» – Степан Колесников, 2ГИС «Рефакторим орг. структуру» – Степан Колесников, 2ГИС
«Рефакторим орг. структуру» – Степан Колесников, 2ГИС 2ГИС Технологии
 
«Функциональное тестирование высоконагруженных проектов» – Илья Пастушков, 2ГИС
«Функциональное тестирование высоконагруженных проектов» – Илья Пастушков, 2ГИС «Функциональное тестирование высоконагруженных проектов» – Илья Пастушков, 2ГИС
«Функциональное тестирование высоконагруженных проектов» – Илья Пастушков, 2ГИС 2ГИС Технологии
 
«Девиации и патологии в отношениях с руководителями и подчинёнными» — Степан ...
«Девиации и патологии в отношениях с руководителями и подчинёнными» — Степан ...«Девиации и патологии в отношениях с руководителями и подчинёнными» — Степан ...
«Девиации и патологии в отношениях с руководителями и подчинёнными» — Степан ...2ГИС Технологии
 
«Реактивные грабли» — Дмитрий Кулижников, 2ГИС
«Реактивные грабли» — Дмитрий Кулижников, 2ГИС«Реактивные грабли» — Дмитрий Кулижников, 2ГИС
«Реактивные грабли» — Дмитрий Кулижников, 2ГИС2ГИС Технологии
 
Масштабирование базы данных через шардирование и партиционирование — Денис Ив...
Масштабирование базы данных через шардирование и партиционирование — Денис Ив...Масштабирование базы данных через шардирование и партиционирование — Денис Ив...
Масштабирование базы данных через шардирование и партиционирование — Денис Ив...2ГИС Технологии
 
«Непростой релиз» – Анжела Проселкова, 2ГИС
 «Непростой релиз» – Анжела Проселкова, 2ГИС  «Непростой релиз» – Анжела Проселкова, 2ГИС
«Непростой релиз» – Анжела Проселкова, 2ГИС 2ГИС Технологии
 
Роман Янке
Роман ЯнкеРоман Янке
Роман ЯнкеCodeFest
 

Andere mochten auch (17)

«Построение Read Model-ей с использованием потоков событий» — Денис Иванов, 2ГИС
«Построение Read Model-ей с использованием потоков событий» — Денис Иванов, 2ГИС«Построение Read Model-ей с использованием потоков событий» — Денис Иванов, 2ГИС
«Построение Read Model-ей с использованием потоков событий» — Денис Иванов, 2ГИС
 
«Тестируем мобильное приложение в суровых реалиях Интернета» – Андрей Усов, 2ГИС
«Тестируем мобильное приложение в суровых реалиях Интернета» – Андрей Усов, 2ГИС«Тестируем мобильное приложение в суровых реалиях Интернета» – Андрей Усов, 2ГИС
«Тестируем мобильное приложение в суровых реалиях Интернета» – Андрей Усов, 2ГИС
 
Winium — это как Selenium, только под Windows
Winium — это как Selenium, только под WindowsWinium — это как Selenium, только под Windows
Winium — это как Selenium, только под Windows
 
«Система развёртывания многокомпонентного сервиса» — Алексей Салов, YaC 2013
«Система развёртывания многокомпонентного сервиса» — Алексей Салов, YaC 2013«Система развёртывания многокомпонентного сервиса» — Алексей Салов, YaC 2013
«Система развёртывания многокомпонентного сервиса» — Алексей Салов, YaC 2013
 
«Карта в браузере: путь от спутникового снимка до пользователя» – Илья Тарату...
«Карта в браузере: путь от спутникового снимка до пользователя» – Илья Тарату...«Карта в браузере: путь от спутникового снимка до пользователя» – Илья Тарату...
«Карта в браузере: путь от спутникового снимка до пользователя» – Илья Тарату...
 
«Badger — инструмент для мониторинга качества продуктов» – Ирина Шрейдер, 2ГИС
«Badger — инструмент для мониторинга качества продуктов» – Ирина Шрейдер, 2ГИС«Badger — инструмент для мониторинга качества продуктов» – Ирина Шрейдер, 2ГИС
«Badger — инструмент для мониторинга качества продуктов» – Ирина Шрейдер, 2ГИС
 
«Автоматизация тестовой инфраструктуры в 2ГИС» — Антон Голицын, 2ГИС
«Автоматизация тестовой инфраструктуры в 2ГИС» — Антон Голицын, 2ГИС«Автоматизация тестовой инфраструктуры в 2ГИС» — Антон Голицын, 2ГИС
«Автоматизация тестовой инфраструктуры в 2ГИС» — Антон Голицын, 2ГИС
 
«5 историй про метрики в 2ГИС» — Игнат Аникеев, 2ГИС
«5 историй про метрики в 2ГИС» — Игнат Аникеев, 2ГИС«5 историй про метрики в 2ГИС» — Игнат Аникеев, 2ГИС
«5 историй про метрики в 2ГИС» — Игнат Аникеев, 2ГИС
 
«Как работают менеджеры продукта в 2ГИС»  – Павел Мочалкин, 2ГИС
 «Как работают менеджеры продукта в 2ГИС»  – Павел Мочалкин, 2ГИС «Как работают менеджеры продукта в 2ГИС»  – Павел Мочалкин, 2ГИС
«Как работают менеджеры продукта в 2ГИС»  – Павел Мочалкин, 2ГИС
 
«Путь от монолита на PHP к микросервисам на Scala» – Денис Иванов, 2ГИС
«Путь от монолита на PHP к микросервисам на Scala» – Денис Иванов, 2ГИС «Путь от монолита на PHP к микросервисам на Scala» – Денис Иванов, 2ГИС
«Путь от монолита на PHP к микросервисам на Scala» – Денис Иванов, 2ГИС
 
«Рефакторим орг. структуру» – Степан Колесников, 2ГИС
«Рефакторим орг. структуру» – Степан Колесников, 2ГИС «Рефакторим орг. структуру» – Степан Колесников, 2ГИС
«Рефакторим орг. структуру» – Степан Колесников, 2ГИС
 
«Функциональное тестирование высоконагруженных проектов» – Илья Пастушков, 2ГИС
«Функциональное тестирование высоконагруженных проектов» – Илья Пастушков, 2ГИС «Функциональное тестирование высоконагруженных проектов» – Илья Пастушков, 2ГИС
«Функциональное тестирование высоконагруженных проектов» – Илья Пастушков, 2ГИС
 
«Девиации и патологии в отношениях с руководителями и подчинёнными» — Степан ...
«Девиации и патологии в отношениях с руководителями и подчинёнными» — Степан ...«Девиации и патологии в отношениях с руководителями и подчинёнными» — Степан ...
«Девиации и патологии в отношениях с руководителями и подчинёнными» — Степан ...
 
«Реактивные грабли» — Дмитрий Кулижников, 2ГИС
«Реактивные грабли» — Дмитрий Кулижников, 2ГИС«Реактивные грабли» — Дмитрий Кулижников, 2ГИС
«Реактивные грабли» — Дмитрий Кулижников, 2ГИС
 
Масштабирование базы данных через шардирование и партиционирование — Денис Ив...
Масштабирование базы данных через шардирование и партиционирование — Денис Ив...Масштабирование базы данных через шардирование и партиционирование — Денис Ив...
Масштабирование базы данных через шардирование и партиционирование — Денис Ив...
 
«Непростой релиз» – Анжела Проселкова, 2ГИС
 «Непростой релиз» – Анжела Проселкова, 2ГИС  «Непростой релиз» – Анжела Проселкова, 2ГИС
«Непростой релиз» – Анжела Проселкова, 2ГИС
 
Роман Янке
Роман ЯнкеРоман Янке
Роман Янке
 

Ähnlich wie «Практическое применение Akka Streams» — Алексей Романчук, 2ГИС

Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Kotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKirill Rozov
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streamsBartosz 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 EcosystemSages
 
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 2015Leonardo Borges
 
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 moreBhakti Mehta
 
Introduction to Apache Flink
Introduction to Apache FlinkIntroduction to Apache Flink
Introduction to Apache Flinkmxmxm
 
関数潮流(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.0Oscar Renalias
 
FS2 for Fun and Profit
FS2 for Fun and ProfitFS2 for Fun and Profit
FS2 for Fun and ProfitAdil 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 2015Till 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 ProgrammingIstanbul 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 2Bahul Neel Upadhyaya
 
Practical RxJava for Android
Practical RxJava for AndroidPractical RxJava for Android
Practical RxJava for AndroidTomáš Kypta
 

Ähnlich wie «Практическое применение Akka Streams» — Алексей Романчук, 2ГИС (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
 

Kürzlich hochgeladen

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfOverkill Security
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 

Kürzlich hochgeladen (20)

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 

«Практическое применение Akka Streams» — Алексей Романчук, 2ГИС