SlideShare a Scribd company logo
1 of 59
Download to read offline
Stream or not to Stream?

Fs2 is the answer
Few words about me…
•Senior Software Engineer at
•Scala developer since 2012
• @LukaszByczynski
Motivation
Pump in ML data to HDFS
• Instead of keeping files on S3 (compressed JSONs)
we would like to have them on HDFS stored with
optimized format like Parquet
• We need to support full and incremental dumps from
our data ocean (Vertica)
• Simplify the current solution and provide
“predictable” memory usage.
Parquet File
Parquet File
Parquet file on HDFS
Why to Stream?
• compositionality
• resource safety
• expressiveness
• “infinite” input sources
• speed / back pressure
• async boundaries
What to choose?
+ stable
+ enterprise ready
+ documentation
+ python ready
- impure
- heavyweight
- lack of control
- YAGNI
Spark
+ stable
+ enterprise ready
+ documentation
- impure
- complex API
- slow?
- actors?
Akka
+ nice rx-like API
+ fast
+ stable
+/- pure
- bus factor == 1
- documentation
Monix
+ super fast*
+ pure
- bus factor == 2
- mindshift
- documentation
- early preview
- sacrifice 

half of community
ZIO
Stream
+ fast
+ pure
+ stable
+/- documentation
+/- mindshift
- not enterprise
Fs2
Fs2 API
Chunk[+O]
Strict, finite sequence of values that allows index-
based random access of elements.
Stream[F, +O]
A stream producing output of type O and which may
evaluate F effects. If F is Pure, the stream evaluates
no effects
Pull[F[_],+O, +R]
Reads values from one or more streams, returns a
result of type R, and produces a Stream[F,O] when
calling stream method.
Pipe[F, I, O]
Stream[F, I] b> Stream[F, O]
Sink[F, I]
Pipe[F, I, Unit]
Who uses it?
doobie http4s
Show me the code…
compositionality
val composed = Stream.range(1, 4) ++ Stream("a", "b", "c")
println(composed.compile.toList)
val zipped = Stream
.range(1, 4)
.zip(Stream("a", "b", "c"))
.map { case (l, r) b> s"$l$r" }
println(zipped.compile.toList)
compositionality
val composed = Stream.range(1, 4) ++ Stream("a", "b", "c")
println(composed.compile.toList)
val zipped = Stream
.range(1, 4)
.zip(Stream("a", "b", "c"))
.map { case (l, r) b> s"$l$r" }
println(zipped.compile.toList)
compositionality
val composed = Stream.range(1, 4) ++ Stream("a", "b", "c")
println(composed.compile.toList)
val zipped = Stream
.range(1, 4)
.zip(Stream("a", "b", "c"))
.map { case (l, r) b> s"$l$r" }
println(zipped.compile.toList)
resource safety
Stream
.bracket(IO(Files.createTempFile("aaaa", "bbbb")))(f b> IO(f.toFile.delete()))
.evalMap(f b> IO(println(f)))
.compile
.drain
.as(ExitCode.Success)
resource safety
Stream
.bracket(IO(Files.createTempFile("aaaa", "bbbb")))(f b> IO(f.toFile.delete()))
.evalMap(f b> IO(println(f)))
.compile
.drain
.as(ExitCode.Success)
resource safety
Stream
.bracket(IO(Files.createTempFile("aaaa", "bbbb")))(f b> IO(f.toFile.delete()))
.evalMap(f b> IO(println(f)))
.compile
.drain
.as(ExitCode.Success)
expressiveness
private val blockingEc = Resource
.make(
IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)))
)(ec b> IO(ec.shutdown()))
val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b>
def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0)
io.file
.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s b> !s.trim.isEmpty && !s.startsWith("//"))
.map(line b> fahrenheitToCelsius(line.toDouble).toString)
.intersperse("n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
expressiveness
private val blockingEc = Resource
.make(
IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)))
)(ec b> IO(ec.shutdown()))
val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b>
def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0)
io.file
.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s b> !s.trim.isEmpty && !s.startsWith("//"))
.map(line b> fahrenheitToCelsius(line.toDouble).toString)
.intersperse("n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
expressiveness
private val blockingEc = Resource
.make(
IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)))
)(ec b> IO(ec.shutdown()))
val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b>
def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0)
io.file
.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s b> !s.trim.isEmpty && !s.startsWith("//"))
.map(line b> fahrenheitToCelsius(line.toDouble).toString)
.intersperse("n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
expressiveness
private val blockingEc = Resource
.make(
IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)))
)(ec b> IO(ec.shutdown()))
val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b>
def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0)
io.file
.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s b> !s.trim.isEmpty && !s.startsWith("//"))
.map(line b> fahrenheitToCelsius(line.toDouble).toString)
.intersperse("n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
expressiveness
private val blockingEc = Resource
.make(
IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)))
)(ec b> IO(ec.shutdown()))
val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b>
def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0)
io.file
.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s b> !s.trim.isEmpty && !s.startsWith("//"))
.map(line b> fahrenheitToCelsius(line.toDouble).toString)
.intersperse("n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
expressiveness
private val blockingEc = Resource
.make(
IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)))
)(ec b> IO(ec.shutdown()))
val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b>
def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0)
io.file
.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s b> !s.trim.isEmpty && !s.startsWith("//"))
.map(line b> fahrenheitToCelsius(line.toDouble).toString)
.intersperse("n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
expressiveness
private val blockingEc = Resource
.make(
IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)))
)(ec b> IO(ec.shutdown()))
val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b>
def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0)
io.file
.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s b> !s.trim.isEmpty && !s.startsWith("//"))
.map(line b> fahrenheitToCelsius(line.toDouble).toString)
.intersperse("n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
expressiveness
private val blockingEc = Resource
.make(
IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)))
)(ec b> IO(ec.shutdown()))
val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b>
def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0)
io.file
.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s b> !s.trim.isEmpty && !s.startsWith("//"))
.map(line b> fahrenheitToCelsius(line.toDouble).toString)
.intersperse("n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
expressiveness
private val blockingEc = Resource
.make(
IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)))
)(ec b> IO(ec.shutdown()))
val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b>
def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0)
io.file
.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s b> !s.trim.isEmpty && !s.startsWith("//"))
.map(line b> fahrenheitToCelsius(line.toDouble).toString)
.intersperse("n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
expressiveness
private val blockingEc = Resource
.make(
IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)))
)(ec b> IO(ec.shutdown()))
val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b>
def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0)
io.file
.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s b> !s.trim.isEmpty && !s.startsWith("//"))
.map(line b> fahrenheitToCelsius(line.toDouble).toString)
.intersperse("n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
expressiveness
private val blockingEc = Resource
.make(
IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)))
)(ec b> IO(ec.shutdown()))
val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b>
def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0)
io.file
.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s b> !s.trim.isEmpty && !s.startsWith("//"))
.map(line b> fahrenheitToCelsius(line.toDouble).toString)
.intersperse("n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
“infinite” input sources
val tick = System.currentTimeMillis()
Stream
.repeatEval(IO(System.currentTimeMillis()))
.take(100)
.fold(0l)((_, r) b> r)
.compile
.lastOrError
.flatMap { result b>
IO(println(result - tick))
}
.as(ExitCode.Success)
“infinite” input sources
val tick = System.currentTimeMillis()
Stream
.repeatEval(IO(System.currentTimeMillis()))
.take(100)
.fold(0l)((_, r) b> r)
.compile
.lastOrError
.flatMap { result b>
IO(println(result - tick))
}
.as(ExitCode.Success)
“infinite” input sources
val tick = System.currentTimeMillis()
Stream
.repeatEval(IO(System.currentTimeMillis()))
.take(100)
.fold(0l)((_, r) b> r)
.compile
.lastOrError
.flatMap { result b>
IO(println(result - tick))
}
.as(ExitCode.Success)
“infinite” input sources
val tick = System.currentTimeMillis()
Stream
.repeatEval(IO(System.currentTimeMillis()))
.take(100)
.fold(0l)((_, r) b> r)
.compile
.lastOrError
.flatMap { result b>
IO(println(result - tick))
}
.as(ExitCode.Success)
async boundaries
val threadPool = Executors.newSingleThreadExecutor
val singleCs = IO.contextShift(ExecutionContext.fromExecutor(threadPool))
Stream
.range(1, 10)
.covary[IO]
.parEvalMap(4)(i b> printWithThreadName(s"Value $i") >> IO.pure(i))
.fold(0)(_ + _)
.compile
.lastOrError
.flatMap(result b> IO.shift(singleCs) >> printWithThreadName(s"Result: $result"))
.flatMap(_ b> IO(threadPool.shutdown()))
.as(ExitCode.Success)
async boundaries
val threadPool = Executors.newSingleThreadExecutor
val singleCs = IO.contextShift(ExecutionContext.fromExecutor(threadPool))
Stream
.range(1, 10)
.covary[IO]
.parEvalMap(4)(i b> printWithThreadName(s"Value $i") >> IO.pure(i))
.fold(0)(_ + _)
.compile
.lastOrError
.flatMap(result b> IO.shift(singleCs) >> printWithThreadName(s"Result: $result"))
.flatMap(_ b> IO(threadPool.shutdown()))
.as(ExitCode.Success)
async boundaries
val threadPool = Executors.newSingleThreadExecutor
val singleCs = IO.contextShift(ExecutionContext.fromExecutor(threadPool))
Stream
.range(1, 10)
.covary[IO]
.parEvalMap(4)(i b> printWithThreadName(s"Value $i") >> IO.pure(i))
.fold(0)(_ + _)
.compile
.lastOrError
.flatMap(result b> IO.shift(singleCs) >> printWithThreadName(s"Result: $result"))
.flatMap(_ b> IO(threadPool.shutdown()))
.as(ExitCode.Success)
async boundaries
val threadPool = Executors.newSingleThreadExecutor
val singleCs = IO.contextShift(ExecutionContext.fromExecutor(threadPool))
Stream
.range(1, 10)
.covary[IO]
.parEvalMap(4)(i b> printWithThreadName(s"Value $i") >> IO.pure(i))
.fold(0)(_ + _)
.compile
.lastOrError
.flatMap(result b> IO.shift(singleCs) t> printWithThreadName(s"Result: $result"))
.flatMap(_ b> IO(threadPool.shutdown()))
.as(ExitCode.Success)
async boundaries
val threadPool = Executors.newSingleThreadExecutor
val singleCs = IO.contextShift(ExecutionContext.fromExecutor(threadPool))
Stream
.range(1, 10)
.covary[IO]
.parEvalMap(4)(i b> printWithThreadName(s"Value $i") >> IO.pure(i))
.fold(0)(_ + _)
.compile
.lastOrError
.flatMap(result b> IO.shift(singleCs) t> printWithThreadName(s"Result: $result"))
.flatMap(_ b> IO(threadPool.shutdown()))
.as(ExitCode.Success)
Demo
Summary
Best practices
Try to keep all streaming code 

very close to interpreter layer
Best practices
There is one exception, if your
application based on Streaming solution
(ex. Http4s) you can return Stream as
the result of operation
(there are benefits !)
Best practices
There is one exception, if your
application based on Streaming solution
(ex. Http4s) you can return Stream as
the result of operation
(there are benefits !)
Best practices
Try to avoid complex pipelines
as long as possible
Best practices
If you need to do that,
consider using other solutions like Akka
(they integrate well)
https://github.com/krasserm/streamz
Best practices
Comprehension and simplicity
is the key to readability
Q&A

More Related Content

What's hot

Introducing redis
Introducing redisIntroducing redis
Introducing redisNuno Caneco
 
Debugging of (C)Python applications
Debugging of (C)Python applicationsDebugging of (C)Python applications
Debugging of (C)Python applicationsRoman Podoliaka
 
leboncoin DataEngineering / Terraform - beginner to advanced
leboncoin DataEngineering / Terraform - beginner to advancedleboncoin DataEngineering / Terraform - beginner to advanced
leboncoin DataEngineering / Terraform - beginner to advancedleboncoin engineering
 
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
 
PHP applications/environments monitoring: APM & Pinba
PHP applications/environments monitoring: APM & PinbaPHP applications/environments monitoring: APM & Pinba
PHP applications/environments monitoring: APM & PinbaPatrick Allaert
 
Neo4j: Import and Data Modelling
Neo4j: Import and Data ModellingNeo4j: Import and Data Modelling
Neo4j: Import and Data ModellingNeo4j
 
What's new in Redis v3.2
What's new in Redis v3.2What's new in Redis v3.2
What's new in Redis v3.2Itamar Haber
 
R data-import, data-export
R data-import, data-exportR data-import, data-export
R data-import, data-exportFAO
 
Apache Spark Structured Streaming + Apache Kafka = ♡
Apache Spark Structured Streaming + Apache Kafka = ♡Apache Spark Structured Streaming + Apache Kafka = ♡
Apache Spark Structured Streaming + Apache Kafka = ♡Bartosz Konieczny
 
apache pig performance optimizations talk at apachecon 2010
apache pig performance optimizations talk at apachecon 2010apache pig performance optimizations talk at apachecon 2010
apache pig performance optimizations talk at apachecon 2010Thejas Nair
 
Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout source{d}
 
Practical pig
Practical pigPractical pig
Practical pigtrihug
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015Michiel Borkent
 
Writing MapReduce Programs using Java | Big Data Hadoop Spark Tutorial | Clou...
Writing MapReduce Programs using Java | Big Data Hadoop Spark Tutorial | Clou...Writing MapReduce Programs using Java | Big Data Hadoop Spark Tutorial | Clou...
Writing MapReduce Programs using Java | Big Data Hadoop Spark Tutorial | Clou...CloudxLab
 
Data science at the command line
Data science at the command lineData science at the command line
Data science at the command lineSharat Chikkerur
 
第2回 Hadoop 輪読会
第2回 Hadoop 輪読会第2回 Hadoop 輪読会
第2回 Hadoop 輪読会Toshihiro Suzuki
 
The elements of a functional mindset
The elements of a functional mindsetThe elements of a functional mindset
The elements of a functional mindsetEric Normand
 

What's hot (20)

Introducing redis
Introducing redisIntroducing redis
Introducing redis
 
Debugging of (C)Python applications
Debugging of (C)Python applicationsDebugging of (C)Python applications
Debugging of (C)Python applications
 
Gur1009
Gur1009Gur1009
Gur1009
 
leboncoin DataEngineering / Terraform - beginner to advanced
leboncoin DataEngineering / Terraform - beginner to advancedleboncoin DataEngineering / Terraform - beginner to advanced
leboncoin DataEngineering / Terraform - beginner to advanced
 
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
 
PHP applications/environments monitoring: APM & Pinba
PHP applications/environments monitoring: APM & PinbaPHP applications/environments monitoring: APM & Pinba
PHP applications/environments monitoring: APM & Pinba
 
Neo4j: Import and Data Modelling
Neo4j: Import and Data ModellingNeo4j: Import and Data Modelling
Neo4j: Import and Data Modelling
 
What's new in Redis v3.2
What's new in Redis v3.2What's new in Redis v3.2
What's new in Redis v3.2
 
R data-import, data-export
R data-import, data-exportR data-import, data-export
R data-import, data-export
 
High Performance tDiary
High Performance tDiaryHigh Performance tDiary
High Performance tDiary
 
Apache Spark Structured Streaming + Apache Kafka = ♡
Apache Spark Structured Streaming + Apache Kafka = ♡Apache Spark Structured Streaming + Apache Kafka = ♡
Apache Spark Structured Streaming + Apache Kafka = ♡
 
apache pig performance optimizations talk at apachecon 2010
apache pig performance optimizations talk at apachecon 2010apache pig performance optimizations talk at apachecon 2010
apache pig performance optimizations talk at apachecon 2010
 
Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout
 
Practical pig
Practical pigPractical pig
Practical pig
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
Writing MapReduce Programs using Java | Big Data Hadoop Spark Tutorial | Clou...
Writing MapReduce Programs using Java | Big Data Hadoop Spark Tutorial | Clou...Writing MapReduce Programs using Java | Big Data Hadoop Spark Tutorial | Clou...
Writing MapReduce Programs using Java | Big Data Hadoop Spark Tutorial | Clou...
 
Data science at the command line
Data science at the command lineData science at the command line
Data science at the command line
 
Apache Spark Workshop
Apache Spark WorkshopApache Spark Workshop
Apache Spark Workshop
 
第2回 Hadoop 輪読会
第2回 Hadoop 輪読会第2回 Hadoop 輪読会
第2回 Hadoop 輪読会
 
The elements of a functional mindset
The elements of a functional mindsetThe elements of a functional mindset
The elements of a functional mindset
 

Similar to Stream or not to Stream?


Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Easy, scalable, fault tolerant stream processing with structured streaming - ...
Easy, scalable, fault tolerant stream processing with structured streaming - ...Easy, scalable, fault tolerant stream processing with structured streaming - ...
Easy, scalable, fault tolerant stream processing with structured streaming - ...Databricks
 
Easy, scalable, fault tolerant stream processing with structured streaming - ...
Easy, scalable, fault tolerant stream processing with structured streaming - ...Easy, scalable, fault tolerant stream processing with structured streaming - ...
Easy, scalable, fault tolerant stream processing with structured streaming - ...Databricks
 
Introduction to Spark with Scala
Introduction to Spark with ScalaIntroduction to Spark with Scala
Introduction to Spark with ScalaHimanshu Gupta
 
Apache Spark - Loading & Saving data | Big Data Hadoop Spark Tutorial | Cloud...
Apache Spark - Loading & Saving data | Big Data Hadoop Spark Tutorial | Cloud...Apache Spark - Loading & Saving data | Big Data Hadoop Spark Tutorial | Cloud...
Apache Spark - Loading & Saving data | Big Data Hadoop Spark Tutorial | Cloud...CloudxLab
 
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIsBig Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIsMatt Stubbs
 
JRuby with Java Code in Data Processing World
JRuby with Java Code in Data Processing WorldJRuby with Java Code in Data Processing World
JRuby with Java Code in Data Processing WorldSATOSHI TAGOMORI
 
OCF.tw's talk about "Introduction to spark"
OCF.tw's talk about "Introduction to spark"OCF.tw's talk about "Introduction to spark"
OCF.tw's talk about "Introduction to spark"Giivee The
 
Introduction to Scalding and Monoids
Introduction to Scalding and MonoidsIntroduction to Scalding and Monoids
Introduction to Scalding and MonoidsHugo Gävert
 
Apache: Big Data - Starting with Apache Spark, Best Practices
Apache: Big Data - Starting with Apache Spark, Best PracticesApache: Big Data - Starting with Apache Spark, Best Practices
Apache: Big Data - Starting with Apache Spark, Best Practicesfelixcss
 
Real-Time Web Programming with PrismTech Vortex Web
Real-Time Web Programming with PrismTech Vortex WebReal-Time Web Programming with PrismTech Vortex Web
Real-Time Web Programming with PrismTech Vortex WebADLINK Technology IoT
 
Building Real-Time Web Applications with Vortex-Web
Building Real-Time Web Applications with Vortex-WebBuilding Real-Time Web Applications with Vortex-Web
Building Real-Time Web Applications with Vortex-WebAngelo Corsaro
 
Making Structured Streaming Ready for Production
Making Structured Streaming Ready for ProductionMaking Structured Streaming Ready for Production
Making Structured Streaming Ready for ProductionDatabricks
 
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...Guido Schmutz
 
Writing Continuous Applications with Structured Streaming PySpark API
Writing Continuous Applications with Structured Streaming PySpark APIWriting Continuous Applications with Structured Streaming PySpark API
Writing Continuous Applications with Structured Streaming PySpark APIDatabricks
 
Lego: A brick system build by scala
Lego: A brick system build by scalaLego: A brick system build by scala
Lego: A brick system build by scalalunfu zhong
 
Writing Continuous Applications with Structured Streaming Python APIs in Apac...
Writing Continuous Applications with Structured Streaming Python APIs in Apac...Writing Continuous Applications with Structured Streaming Python APIs in Apac...
Writing Continuous Applications with Structured Streaming Python APIs in Apac...Databricks
 

Similar to Stream or not to Stream?
 (20)

Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Easy, scalable, fault tolerant stream processing with structured streaming - ...
Easy, scalable, fault tolerant stream processing with structured streaming - ...Easy, scalable, fault tolerant stream processing with structured streaming - ...
Easy, scalable, fault tolerant stream processing with structured streaming - ...
 
Easy, scalable, fault tolerant stream processing with structured streaming - ...
Easy, scalable, fault tolerant stream processing with structured streaming - ...Easy, scalable, fault tolerant stream processing with structured streaming - ...
Easy, scalable, fault tolerant stream processing with structured streaming - ...
 
Introduction to Spark with Scala
Introduction to Spark with ScalaIntroduction to Spark with Scala
Introduction to Spark with Scala
 
Apache Spark - Loading & Saving data | Big Data Hadoop Spark Tutorial | Cloud...
Apache Spark - Loading & Saving data | Big Data Hadoop Spark Tutorial | Cloud...Apache Spark - Loading & Saving data | Big Data Hadoop Spark Tutorial | Cloud...
Apache Spark - Loading & Saving data | Big Data Hadoop Spark Tutorial | Cloud...
 
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIsBig Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
 
JRuby with Java Code in Data Processing World
JRuby with Java Code in Data Processing WorldJRuby with Java Code in Data Processing World
JRuby with Java Code in Data Processing World
 
Introduction to Apache Spark
Introduction to Apache SparkIntroduction to Apache Spark
Introduction to Apache Spark
 
OCF.tw's talk about "Introduction to spark"
OCF.tw's talk about "Introduction to spark"OCF.tw's talk about "Introduction to spark"
OCF.tw's talk about "Introduction to spark"
 
Introduction to Scalding and Monoids
Introduction to Scalding and MonoidsIntroduction to Scalding and Monoids
Introduction to Scalding and Monoids
 
Apache: Big Data - Starting with Apache Spark, Best Practices
Apache: Big Data - Starting with Apache Spark, Best PracticesApache: Big Data - Starting with Apache Spark, Best Practices
Apache: Big Data - Starting with Apache Spark, Best Practices
 
Real-Time Web Programming with PrismTech Vortex Web
Real-Time Web Programming with PrismTech Vortex WebReal-Time Web Programming with PrismTech Vortex Web
Real-Time Web Programming with PrismTech Vortex Web
 
Building Real-Time Web Applications with Vortex-Web
Building Real-Time Web Applications with Vortex-WebBuilding Real-Time Web Applications with Vortex-Web
Building Real-Time Web Applications with Vortex-Web
 
Osd ctw spark
Osd ctw sparkOsd ctw spark
Osd ctw spark
 
Making Structured Streaming Ready for Production
Making Structured Streaming Ready for ProductionMaking Structured Streaming Ready for Production
Making Structured Streaming Ready for Production
 
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...
 
Writing Continuous Applications with Structured Streaming PySpark API
Writing Continuous Applications with Structured Streaming PySpark APIWriting Continuous Applications with Structured Streaming PySpark API
Writing Continuous Applications with Structured Streaming PySpark API
 
Lego: A brick system build by scala
Lego: A brick system build by scalaLego: A brick system build by scala
Lego: A brick system build by scala
 
Writing Continuous Applications with Structured Streaming Python APIs in Apac...
Writing Continuous Applications with Structured Streaming Python APIs in Apac...Writing Continuous Applications with Structured Streaming Python APIs in Apac...
Writing Continuous Applications with Structured Streaming Python APIs in Apac...
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
 

Recently uploaded

CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfIdiosysTechnologies1
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....kzayra69
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 

Recently uploaded (20)

CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdf
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 

Stream or not to Stream?


  • 1. Stream or not to Stream?
 Fs2 is the answer
  • 2. Few words about me… •Senior Software Engineer at •Scala developer since 2012 • @LukaszByczynski
  • 4. Pump in ML data to HDFS • Instead of keeping files on S3 (compressed JSONs) we would like to have them on HDFS stored with optimized format like Parquet • We need to support full and incremental dumps from our data ocean (Vertica) • Simplify the current solution and provide “predictable” memory usage.
  • 8. Why to Stream? • compositionality • resource safety • expressiveness • “infinite” input sources • speed / back pressure • async boundaries
  • 10. + stable + enterprise ready + documentation + python ready - impure - heavyweight - lack of control - YAGNI Spark
  • 11. + stable + enterprise ready + documentation - impure - complex API - slow? - actors? Akka
  • 12. + nice rx-like API + fast + stable +/- pure - bus factor == 1 - documentation Monix
  • 13. + super fast* + pure - bus factor == 2 - mindshift - documentation - early preview - sacrifice 
 half of community ZIO Stream
  • 14. + fast + pure + stable +/- documentation +/- mindshift - not enterprise Fs2
  • 16.
  • 17.
  • 18. Chunk[+O] Strict, finite sequence of values that allows index- based random access of elements.
  • 19. Stream[F, +O] A stream producing output of type O and which may evaluate F effects. If F is Pure, the stream evaluates no effects
  • 20. Pull[F[_],+O, +R] Reads values from one or more streams, returns a result of type R, and produces a Stream[F,O] when calling stream method.
  • 21. Pipe[F, I, O] Stream[F, I] b> Stream[F, O]
  • 24. Show me the code…
  • 25. compositionality val composed = Stream.range(1, 4) ++ Stream("a", "b", "c") println(composed.compile.toList) val zipped = Stream .range(1, 4) .zip(Stream("a", "b", "c")) .map { case (l, r) b> s"$l$r" } println(zipped.compile.toList)
  • 26. compositionality val composed = Stream.range(1, 4) ++ Stream("a", "b", "c") println(composed.compile.toList) val zipped = Stream .range(1, 4) .zip(Stream("a", "b", "c")) .map { case (l, r) b> s"$l$r" } println(zipped.compile.toList)
  • 27. compositionality val composed = Stream.range(1, 4) ++ Stream("a", "b", "c") println(composed.compile.toList) val zipped = Stream .range(1, 4) .zip(Stream("a", "b", "c")) .map { case (l, r) b> s"$l$r" } println(zipped.compile.toList)
  • 28. resource safety Stream .bracket(IO(Files.createTempFile("aaaa", "bbbb")))(f b> IO(f.toFile.delete())) .evalMap(f b> IO(println(f))) .compile .drain .as(ExitCode.Success)
  • 29. resource safety Stream .bracket(IO(Files.createTempFile("aaaa", "bbbb")))(f b> IO(f.toFile.delete())) .evalMap(f b> IO(println(f))) .compile .drain .as(ExitCode.Success)
  • 30. resource safety Stream .bracket(IO(Files.createTempFile("aaaa", "bbbb")))(f b> IO(f.toFile.delete())) .evalMap(f b> IO(println(f))) .compile .drain .as(ExitCode.Success)
  • 31. expressiveness private val blockingEc = Resource .make( IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))) )(ec b> IO(ec.shutdown())) val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b> def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0) io.file .readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096) .through(text.utf8Decode) .through(text.lines) .filter(s b> !s.trim.isEmpty && !s.startsWith("//")) .map(line b> fahrenheitToCelsius(line.toDouble).toString) .intersperse("n") .through(text.utf8Encode) .through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC)) } def run(args: List[String]): IO[ExitCode] = converter.compile.drain.as(ExitCode.Success)
  • 32. expressiveness private val blockingEc = Resource .make( IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))) )(ec b> IO(ec.shutdown())) val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b> def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0) io.file .readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096) .through(text.utf8Decode) .through(text.lines) .filter(s b> !s.trim.isEmpty && !s.startsWith("//")) .map(line b> fahrenheitToCelsius(line.toDouble).toString) .intersperse("n") .through(text.utf8Encode) .through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC)) } def run(args: List[String]): IO[ExitCode] = converter.compile.drain.as(ExitCode.Success)
  • 33. expressiveness private val blockingEc = Resource .make( IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))) )(ec b> IO(ec.shutdown())) val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b> def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0) io.file .readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096) .through(text.utf8Decode) .through(text.lines) .filter(s b> !s.trim.isEmpty && !s.startsWith("//")) .map(line b> fahrenheitToCelsius(line.toDouble).toString) .intersperse("n") .through(text.utf8Encode) .through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC)) } def run(args: List[String]): IO[ExitCode] = converter.compile.drain.as(ExitCode.Success)
  • 34. expressiveness private val blockingEc = Resource .make( IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))) )(ec b> IO(ec.shutdown())) val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b> def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0) io.file .readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096) .through(text.utf8Decode) .through(text.lines) .filter(s b> !s.trim.isEmpty && !s.startsWith("//")) .map(line b> fahrenheitToCelsius(line.toDouble).toString) .intersperse("n") .through(text.utf8Encode) .through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC)) } def run(args: List[String]): IO[ExitCode] = converter.compile.drain.as(ExitCode.Success)
  • 35. expressiveness private val blockingEc = Resource .make( IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))) )(ec b> IO(ec.shutdown())) val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b> def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0) io.file .readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096) .through(text.utf8Decode) .through(text.lines) .filter(s b> !s.trim.isEmpty && !s.startsWith("//")) .map(line b> fahrenheitToCelsius(line.toDouble).toString) .intersperse("n") .through(text.utf8Encode) .through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC)) } def run(args: List[String]): IO[ExitCode] = converter.compile.drain.as(ExitCode.Success)
  • 36. expressiveness private val blockingEc = Resource .make( IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))) )(ec b> IO(ec.shutdown())) val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b> def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0) io.file .readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096) .through(text.utf8Decode) .through(text.lines) .filter(s b> !s.trim.isEmpty && !s.startsWith("//")) .map(line b> fahrenheitToCelsius(line.toDouble).toString) .intersperse("n") .through(text.utf8Encode) .through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC)) } def run(args: List[String]): IO[ExitCode] = converter.compile.drain.as(ExitCode.Success)
  • 37. expressiveness private val blockingEc = Resource .make( IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))) )(ec b> IO(ec.shutdown())) val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b> def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0) io.file .readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096) .through(text.utf8Decode) .through(text.lines) .filter(s b> !s.trim.isEmpty && !s.startsWith("//")) .map(line b> fahrenheitToCelsius(line.toDouble).toString) .intersperse("n") .through(text.utf8Encode) .through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC)) } def run(args: List[String]): IO[ExitCode] = converter.compile.drain.as(ExitCode.Success)
  • 38. expressiveness private val blockingEc = Resource .make( IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))) )(ec b> IO(ec.shutdown())) val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b> def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0) io.file .readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096) .through(text.utf8Decode) .through(text.lines) .filter(s b> !s.trim.isEmpty && !s.startsWith("//")) .map(line b> fahrenheitToCelsius(line.toDouble).toString) .intersperse("n") .through(text.utf8Encode) .through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC)) } def run(args: List[String]): IO[ExitCode] = converter.compile.drain.as(ExitCode.Success)
  • 39. expressiveness private val blockingEc = Resource .make( IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))) )(ec b> IO(ec.shutdown())) val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b> def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0) io.file .readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096) .through(text.utf8Decode) .through(text.lines) .filter(s b> !s.trim.isEmpty && !s.startsWith("//")) .map(line b> fahrenheitToCelsius(line.toDouble).toString) .intersperse("n") .through(text.utf8Encode) .through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC)) } def run(args: List[String]): IO[ExitCode] = converter.compile.drain.as(ExitCode.Success)
  • 40. expressiveness private val blockingEc = Resource .make( IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))) )(ec b> IO(ec.shutdown())) val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b> def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0) io.file .readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096) .through(text.utf8Decode) .through(text.lines) .filter(s b> !s.trim.isEmpty && !s.startsWith("//")) .map(line b> fahrenheitToCelsius(line.toDouble).toString) .intersperse("n") .through(text.utf8Encode) .through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC)) } def run(args: List[String]): IO[ExitCode] = converter.compile.drain.as(ExitCode.Success)
  • 41. expressiveness private val blockingEc = Resource .make( IO(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2))) )(ec b> IO(ec.shutdown())) val converter: Stream[IO, Unit] = Stream.resource(blockingExecutionContext).flatMap { blockingEC b> def fahrenheitToCelsius(f: Double): Double = (f - 32.0) * (5.0 / 9.0) io.file .readAll[IO](Paths.get("testdata/fahrenheit.txt"), blockingEC, 4096) .through(text.utf8Decode) .through(text.lines) .filter(s b> !s.trim.isEmpty && !s.startsWith("//")) .map(line b> fahrenheitToCelsius(line.toDouble).toString) .intersperse("n") .through(text.utf8Encode) .through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blockingEC)) } def run(args: List[String]): IO[ExitCode] = converter.compile.drain.as(ExitCode.Success)
  • 42. “infinite” input sources val tick = System.currentTimeMillis() Stream .repeatEval(IO(System.currentTimeMillis())) .take(100) .fold(0l)((_, r) b> r) .compile .lastOrError .flatMap { result b> IO(println(result - tick)) } .as(ExitCode.Success)
  • 43. “infinite” input sources val tick = System.currentTimeMillis() Stream .repeatEval(IO(System.currentTimeMillis())) .take(100) .fold(0l)((_, r) b> r) .compile .lastOrError .flatMap { result b> IO(println(result - tick)) } .as(ExitCode.Success)
  • 44. “infinite” input sources val tick = System.currentTimeMillis() Stream .repeatEval(IO(System.currentTimeMillis())) .take(100) .fold(0l)((_, r) b> r) .compile .lastOrError .flatMap { result b> IO(println(result - tick)) } .as(ExitCode.Success)
  • 45. “infinite” input sources val tick = System.currentTimeMillis() Stream .repeatEval(IO(System.currentTimeMillis())) .take(100) .fold(0l)((_, r) b> r) .compile .lastOrError .flatMap { result b> IO(println(result - tick)) } .as(ExitCode.Success)
  • 46. async boundaries val threadPool = Executors.newSingleThreadExecutor val singleCs = IO.contextShift(ExecutionContext.fromExecutor(threadPool)) Stream .range(1, 10) .covary[IO] .parEvalMap(4)(i b> printWithThreadName(s"Value $i") >> IO.pure(i)) .fold(0)(_ + _) .compile .lastOrError .flatMap(result b> IO.shift(singleCs) >> printWithThreadName(s"Result: $result")) .flatMap(_ b> IO(threadPool.shutdown())) .as(ExitCode.Success)
  • 47. async boundaries val threadPool = Executors.newSingleThreadExecutor val singleCs = IO.contextShift(ExecutionContext.fromExecutor(threadPool)) Stream .range(1, 10) .covary[IO] .parEvalMap(4)(i b> printWithThreadName(s"Value $i") >> IO.pure(i)) .fold(0)(_ + _) .compile .lastOrError .flatMap(result b> IO.shift(singleCs) >> printWithThreadName(s"Result: $result")) .flatMap(_ b> IO(threadPool.shutdown())) .as(ExitCode.Success)
  • 48. async boundaries val threadPool = Executors.newSingleThreadExecutor val singleCs = IO.contextShift(ExecutionContext.fromExecutor(threadPool)) Stream .range(1, 10) .covary[IO] .parEvalMap(4)(i b> printWithThreadName(s"Value $i") >> IO.pure(i)) .fold(0)(_ + _) .compile .lastOrError .flatMap(result b> IO.shift(singleCs) >> printWithThreadName(s"Result: $result")) .flatMap(_ b> IO(threadPool.shutdown())) .as(ExitCode.Success)
  • 49. async boundaries val threadPool = Executors.newSingleThreadExecutor val singleCs = IO.contextShift(ExecutionContext.fromExecutor(threadPool)) Stream .range(1, 10) .covary[IO] .parEvalMap(4)(i b> printWithThreadName(s"Value $i") >> IO.pure(i)) .fold(0)(_ + _) .compile .lastOrError .flatMap(result b> IO.shift(singleCs) t> printWithThreadName(s"Result: $result")) .flatMap(_ b> IO(threadPool.shutdown())) .as(ExitCode.Success)
  • 50. async boundaries val threadPool = Executors.newSingleThreadExecutor val singleCs = IO.contextShift(ExecutionContext.fromExecutor(threadPool)) Stream .range(1, 10) .covary[IO] .parEvalMap(4)(i b> printWithThreadName(s"Value $i") >> IO.pure(i)) .fold(0)(_ + _) .compile .lastOrError .flatMap(result b> IO.shift(singleCs) t> printWithThreadName(s"Result: $result")) .flatMap(_ b> IO(threadPool.shutdown())) .as(ExitCode.Success)
  • 51. Demo
  • 53. Best practices Try to keep all streaming code 
 very close to interpreter layer
  • 54. Best practices There is one exception, if your application based on Streaming solution (ex. Http4s) you can return Stream as the result of operation (there are benefits !)
  • 55. Best practices There is one exception, if your application based on Streaming solution (ex. Http4s) you can return Stream as the result of operation (there are benefits !)
  • 56. Best practices Try to avoid complex pipelines as long as possible
  • 57. Best practices If you need to do that, consider using other solutions like Akka (they integrate well) https://github.com/krasserm/streamz
  • 58. Best practices Comprehension and simplicity is the key to readability
  • 59. Q&A