Slide 1

Slide 1 text

Functional Flowing 47deg.com

Slide 2

Slide 2 text

Who am I?

Slide 3

Slide 3 text

KotlinX Flow Pull based Reasoning about Flow Streaming Resources Parallel Processing

Slide 4

Slide 4 text

Pull Based Streaming Upstream Pipeline Downstream

Slide 5

Slide 5 text

Pull Based Streaming Upstream Pipeline Downstream

Slide 6

Slide 6 text

Pull Based Streaming public fun interface FlowCollector { public suspend fun emit(value: T) }

Slide 7

Slide 7 text

Creating Flows class Circle(val count: Int) suspend fun FlowCollector.produceCircles(): Unit { var counter: Int = 0 while(true) { val circle = Circle(counter>+) println("Creating $circle") emit(circle) } }

Slide 8

Slide 8 text

Creating Flows class Circle(val count: Int) suspend fun FlowCollector.produceCircles(): Unit { var counter: Int = 0 while(true) { val circle = Circle(counter>+) println("Creating $circle") emit(circle) } } val circles: Flow = flow { produceCircles() }

Slide 9

Slide 9 text

Creating Flows class Circle(val count: Int) val circles: Flow = flow { var counter: Int = 0 while(true) { val circle = Circle(counter>+) println("Creating $circle") emit(circle) } }

Slide 10

Slide 10 text

Pipeline class Square private constructor(val circle: Circle) { companion object { suspend fun Circle.toSquare(): Square { print("Creating Square($count)") delay(1.seconds) return Square(this).also { println("Created $this") } } } }

Slide 11

Slide 11 text

Putting it all together fun main() = runBlocking { circles .take(3) .collect { circle -> circle.toSquare() } } Creating Circle@63e31ee Creating Square(0) Created Square@6adca536 Creating Circle@23223dd8

Slide 12

Slide 12 text

Reasoning about Flows suspend fun FlowCollector.produceCircles(): Unit { var counter: Int = 0 while(true) { val circle = Circle(counter>+) println("Creating $circle") emit(circle) } }

Slide 13

Slide 13 text

Reasoning about Flows class Square private constructor(val circle: Circle) { companion object { suspend fun Circle.toSquare(): Square { print("Creating Square($count)") delay(1.seconds) return Square(this).also { println("Created $this") } } } }

Slide 14

Slide 14 text

Reasoning about Flows while(true) 0 1 2 Coroutine

Slide 15

Slide 15 text

Flowing resources fun Path.readAll(): Flow

Slide 16

Slide 16 text

Flowing resources fun Path.readAll(): Flow = flow { >/ this: FlowCollector useLines { lines -> lines.forEach { line -> emit(line) } } }

Slide 17

Slide 17 text

Flowing resources suspend fun insertIntoBlobStorage(line: String): Unit

Slide 18

Slide 18 text

Flowing resources /** Java SDK */ class BlobStorage(val blobName: String) : AutoCloseable { fun uploadBlob(data: ByteArray): CompletableFuture override fun close() = Unit } suspend fun BlobStorage.insertIntoBlobStorage(line: String): UploadResult = uploadBlob(line.toByteArray(Charsets.UTF_8)).await()

Slide 19

Slide 19 text

Flowing resources suspend fun uploadData(path: String): Unit = BlobStorage(path).use { storage -> Path(path) .readAll() .collect { line -> storage.insertIntoBlobStorage(line) } }

Slide 20

Slide 20 text

Flowing resources fun blobStorage(path: String): Flow = flow { BlobStorage(path).use { emit(it) } }

Slide 21

Slide 21 text

Flowing resources suspend fun uploadData2(path: String): Flow = blobStorage().flatMapConcat { blobStorage -> Path("data.txt") .readAll() .map { line -> blobStorage.insertIntoBlobStorage(line) } }

Slide 22

Slide 22 text

Parallel Processing Read line Upload blob Coroutine …

Slide 23

Slide 23 text

Parallel Processing Read line Coroutine Upload blob Coroutine Channel(3)

Slide 24

Slide 24 text

Parallel Processing suspend fun uploadData3(path: String): Flow = blobStorage().flatMapConcat { blobStorage -> Path("data.txt") .readAll() .parMapUnordered(concurrency = 3) { line -> blobStorage.insertIntoBlobStorage(line) } }

Slide 26

Slide 26 text

Parallel Processing suspend fun uploadData3(path: String): Flow = blobStorage().flatMapConcat { blobStorage -> Path("data.txt") .readAll() .parMap(concurrency = 3) { line -> blobStorage.insertIntoBlobStorage(line) } }

Slide 27

Slide 27 text

Compose-able streaming Automatic back-pressure Conclusion Suspend everywhere

Slide 28

Slide 28 text

Thanks!