Monix: Version 2.2.1 Final Release

Version 2.2.1 is out now.

It is a major release that shouldn’t be considered binary compatible with 2.1.x, even though it is source compatible. This is due to several operators being changed in Observable and Task, but extension methods are provided for the older versions, therefore source compatibility is maintained.

As a summary: the new MVar synchronization primitive, performance improvements in Observable.concatMap and in the Task run-loop, new SchedulerService interface for shutting down schedulers, bug fixes and upgrade to Cats 0.9.0. See details below.

New Synchronization Primitive: monix.eval.MVar #

The MVar is a new synchronization primitive, a mutable location that can be empty or contains a value, asynchronously blocking reads when empty and blocking writes when full.

Use-cases:

  1. As synchronized, thread-safe mutable variables
  2. As channels, with take and put acting as “receive” and “send”
  3. As a binary semaphore, with take and put acting as “acquire” and “release”

Read the tutorial or the api documentation.

SchedulerService: for shutting down Schedulers #

Sometimes there’s a need to create a temporary Scheduler whose resources need to be discarded. The new SchedulerService is a new interface that adds shutdown and awaitTermination methods to the base Scheduler, similar in spirit with java.util.concurrent.ExecutorService.

Read the tutorial or the api documentation.

Performance Improvements #

The Task run-loop has suffered from a performance regression in version 2.1.x, due to safety reasons.

In this new release I managed to eliminate that regression and right now the Monix Task has the best throughput among all the similar data type implementations in Scala land, see github.com/rossabaker/benchmarks/pull/4.

Observable also has performance improvements in concatMap, which is now using the getAndSet platform intrinsics from Java 8 to speed up the concurrency for the handling of onComplete. If you’re into JVM concurrency, the implementation is beautiful ;-)

In addition to that, Observable has performance improvements for the bufferSliding operator, as it was revealed in a recent benchmark that it had terrible performance. Now it is fine :-)

All Issues #

The full list of changes (with descriptions below):

  • Issue #298: Don’t publish empty jars in root projects
  • Issue #300: Update to cats 0.9.0
  • Issue #301: MVar, a non-blocking Task-based implementation
  • Issue #303: Observable “doOn” operators refactoring
  • Issue #281: Fix performance regression in Task.flatMap
  • Issue #284: Move ExecutionModel to monix.execution
  • Issue #285: Rename Task.runAsync(f: Try[A] => Unit) to Task.runOnComplete
  • Issue #286: Add Task.runSyncMaybe
  • Issue #287: Add Scheduler.forkJoin builder
  • Issue #266: Add SchedulerService interface in monix.execution.schedulers
  • Issue #288: Task.create should not force async boundary
  • Issue #289: Observable.foreach should not fork
  • Issue #291: Add Observable.takeEveryNth operator
  • Issue #292: Optimize Observable.concatMap
  • Issue #294: Optimize Observable.bufferSliding
  • Issue #295: Add Observable.publishSelector, Observable.pipeThroughSelector
  • Issue #296: Add Task.deferFuture builder
  • Issue #305: Fix stack-overflow error in MVar

Upgrading #

To use the new version, include this in your build.sbt (and use %%% for Scala.js):

libraryDependencies += "io.monix" %% "monix" % "2.2.1"

The other projects from the @Monix organization have also been upgraded to depend on this new version.

shade, the Scala Memcached client:

dependencies += "io.monix" %% "shade" % "1.9.1"

monix-kafka, the Apache Kafka integration:

// For Kafka 8
libraryDependencies += "io.monix" %% "monix-kafka-8" % "0.10"

// For Kafka 9
libraryDependencies += "io.monix" %% "monix-kafka-9" % "0.10"

// For Kafka 10
libraryDependencies += "io.monix" %% "monix-kafka-10" % "0.10"

Enjoy!