FS2 is a library for purely functional, effectful, and polymorphic stream processing library in the Scala programming language. Its design goals are compositionality, expressiveness, resource safety, and speed. The name is a modified acronym for Functional Streams for Scala (FSS, or FS2).
FS2 is available for Scala 2.12, Scala 2.13, and Scala.js.
FS2 is built upon two major functional libraries for Scala, Cats, and Cats-Effect.
Regardless of those dependencies, FS2 core types (streams and pulls) are polymorphic in the effect type (as long as it is compatible with cats-effect
typeclasses),
and thus FS2 can be used with other effect libraries, such as Monix.
Prior to the 0.9 release in 2016, FS2 was known as scalaz-stream
, which was based on the scalaz
library.
Quick links:
- Microsite
- About the library
- How to get latest version
- API docs: fs2-core, fs2-io, fs2-reactive-streams, fs2-experimental
- Docs and getting help
The latest version is 2.2.x. See the badge at the top of the README for the exact version number.
If upgrading from the 1.0 series, see the release notes for 2.0.0 for help with upgrading.
// available for 2.12, 2.13
libraryDependencies += "co.fs2" %% "fs2-core" % "2.2.1" // For cats 2 and cats-effect 2
// optional I/O library
libraryDependencies += "co.fs2" %% "fs2-io" % "2.2.1"
// optional reactive streams interop
libraryDependencies += "co.fs2" %% "fs2-reactive-streams" % "2.2.1"
// optional experimental library
libraryDependencies += "co.fs2" %% "fs2-experimental" % "2.2.1"
The fs2-core library is also supported on Scala.js:
libraryDependencies += "co.fs2" %%% "fs2-core" % "2.2.1"
There are detailed migration guides for migrating from older versions.
FS2 is a streaming I/O library. The design goals are compositionality, expressiveness, resource safety, and speed. Here's a simple example of its use:
import cats.effect.{Blocker, ExitCode, IO, IOApp, Resource}
import cats.implicits._
import fs2.{io, text, Stream}
import java.nio.file.Paths
object Converter extends IOApp {
val converter: Stream[IO, Unit] = Stream.resource(Blocker[IO]).flatMap { blocker =>
def fahrenheitToCelsius(f: Double): Double =
(f - 32.0) * (5.0/9.0)
io.file.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blocker, 4096)
.through(text.utf8Decode)
.through(text.lines)
.filter(s => !s.trim.isEmpty && !s.startsWith("//"))
.map(line => fahrenheitToCelsius(line.toDouble).toString)
.intersperse("\n")
.through(text.utf8Encode)
.through(io.file.writeAll(Paths.get("testdata/celsius.txt"), blocker))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
}
This will construct a program that reads lines incrementally from testdata/fahrenheit.txt
, skipping blank lines and commented lines. It then parses temperatures in degrees Fahrenheit, converts these to Celsius, UTF-8 encodes the output, and writes incrementally to testdata/celsius.txt
, using constant memory. The input and output files will be closed upon normal termination or if exceptions occur.
Note that this example is specialised to IO
for simplicity, but Stream
is fully polymorphic in the effect type (the F[_]
in Stream[F, A]
), as long as F[_]
is compatible with the cats-effect
typeclasses.
The library supports a number of other interesting use cases:
- Zipping and merging of streams: A streaming computation may read from multiple sources in a streaming fashion, zipping or merging their elements using an arbitrary function. In general, clients have a great deal of flexibility in what sort of topologies they can define, due to
Stream
being a first class entity with a very rich algebra of combinators. - Dynamic resource allocation: A streaming computation may allocate resources dynamically (for instance, reading a list of files to process from a stream built off a network socket), and the library will ensure these resources get released upon normal termination or if exceptions occur.
- Nondeterministic and concurrent processing: A computation may read from multiple input streams simultaneously, using whichever result comes back first, and a pipeline of transformations can allow for nondeterminism and queueing at each stage. Due to several concurrency combinators and data structures, streams can be used as light-weight, declarative threads to build complex concurrent behaviour compositionally.
These features mean that FS2 goes beyond streaming I/O to offer a very general and declarative model for arbitrary control flow.
- There are Scaladoc API documentations for the core library, which defines and implements the core types for streams and pulls, as well as the type aliases for pipes and sinks. The
io
library provides FS2 bindings for NIO-based file I/O and TCP/UDP networking. - The official guide is a good starting point for learning more about the library.
- The documentation page is intended to serve as a list of all references, including conference presentation recordings, academic papers, and blog posts, on the use and implementation of
fs2
. - The FAQ has frequently asked questions. Feel free to open issues or PRs with additions to the FAQ!
- Also feel free to come discuss and ask/answer questions in the gitter channel and/or on StackOverflow using the tag FS2. Gitter will generally get you a quicker answer.
If you have a project you'd like to include in this list, either open a PR or let us know in the gitter channel and we'll add a link to it here.
- canoe: A purely functional library for building Telegram chatbots.
- chromaprint: A Scala implementation of the Chromaprint/AcoustID audio fingerprinting algorithm, built with fs2 streams / Cats Effect.
- circe-fs2: Streaming JSON manipulation with circe.
- doobie: Pure functional JDBC built on fs2.
- fs2-aws: FS2 streams to interact with AWS utilities
- fs2-blobstore: Minimal, idiomatic, stream-based Scala interface for S3, GCS, SFTP and other key/value store implementations.
- fs2-cassandra: Cassandra bindings for fs2.
- fs2-columns: a
Chunk
that uses shapeless to storecase class
data column-wise. - fs2-cron: FS2 streams based on cron expressions.
- fs2-crypto: TLS support for fs2.
- fs2-elastic: Simple client for Elasticsearch.
- fs2-google-pubsub: A Google Cloud Pub/Sub implementation using fs2 and cats-effect.
- fs2-grpc: gRPC implementation for FS2 / Cats Effect.
- fs2-http: Http server and client library implemented in fs2.
- fs2-jms: JMS connectors for FS2 streams
- fs2-kafka
- fd4s/fs2-kafka: Functional Kafka Streams for Scala.
- spinoco/fs2-kafka: Simple client for Apache Kafka.
- fs2-mail: Fully asynchronous java non-blocking email client using fs2.
- fs2-rabbit: RabbitMQ stream-based client built on top of Fs2.
- fs2-reactive-streams: A reactive streams implementation for fs2.
- fs2-redis: Redis stream-based client built on top of Fs2 / Cats Effect.
- fs2-ssh: A wrapper around Apache SSHD targeting cats-effect and fs2.
- fs2-zk: Simple Apache Zookeeper bindings for fs2.
- fs2-ftp: Simple client for Ftp/Ftps/Sftp using fs2 and cats-effect.
- http4s: Minimal, idiomatic Scala interface for HTTP services using fs2.
- mongosaur: fs2-based MongoDB driver.
- scarctic: fs2-based driver for MAN/AHL's Arctic data store.
- scodec-protocols: A library for working with libpcap files. Contains many interesting pipes (e.g., working with time series and playing back streams at various rates).
- scodec-stream: A library for streaming binary decoding and encoding, built using fs2 and scodec.
- streamz: A library that supports the conversion of Akka Stream
Source
s,Flow
s andSink
s to and from FS2Stream
s,Pipe
s andSink
s, respectively. It also supports the usage of Apache Camel endpoints in FS2Stream
s and Akka StreamSource
s,Flow
s andSubFlow
s. - upperbound: A purely functional, interval-based rate limiter with support for backpressure.
- vinyldns: A DNS governance system using fs2 for throttling updates to DNS backends.
Special thanks to YourKit for supporting this project's ongoing performance tuning efforts with licenses to their excellent product.
See the Code of Conduct.