Monix: Version 2.0.0 Final Release
Monix is a library for composing asynchronous, event-based programs. Work on version 2.0 started since December last year, after version 1.0 was released.
Today marks the release of the 2.0.0
version. Here’s what happened
since 1.0:
- the project went through a rename (from Monifu to Monix)
- the underlying protocol of
Observable
has been reviewed and changed quite significantly, making observable streams cancelable - many of the
Observable
operators where refactored and improved - the project was split into multiple sub-projects, such that users can pick and choose what they need
- the Task and Coeval types were introduced
- the project’s code coverage has been raised over 83%
- the project is in Typelevel’s Incubator, which for you it means that it plays nice with the other Typelevel projects
- it now integrates with Typelevel Cats and
with Scalaz, which are THE standard
libraries for doing functional programming and yes,
Task
,Coeval
andObservable
are provably Monads :-) - we initiated a documentation website at Monix.io, with an initial batch of useful articles, though there’s still a lot of ground left to cover for observables
Today Monix 2.0.0
is being released for Scala 2.10.6
, 2.11.8
and
2.12.0-M5
, Scala.js 0.6.11
, Cats 0.7.0
and Scalaz 7.2.5
.
You can hit the documentation, or experiment in ScalaFiddle and see Monix in your browser, or take a look at monix-sample, a client/server communication sample with both sides handled by Monix (see it running).
See the published API Documentation.
The full list of issues follows. Note that this list represents a
historical trail, but doesn’t necessarily represent the released
2.0.0
, as sometimes work that happened in an earlier issue was
changed again in a later issue.
- Issue #60 - initiated
the
docs
sub-project with tutorials type-checked as part of the test process - Issue #88 - add
Monix’s own
Task
, an alternative toFuture
and the ScalazTask
- Issue #89 - initial integration with Cats
- Issue #90 - remove functionality that isn’t relevant to the purpose of Monix and be supported
- Issue #91 - project rename and reorganization (epic API breakage)
- Issue #93 - renamed
Observable.onSubscribe
toObservable.unsafeSubscribeFn
, because it shouldn’t be used directly, unless you really, really know what you’re doing - Issue #94 - fixed comments style to ScalaDoc
- Issue #96 - removed
Observable.create
because it is unsafe - Issue #100 - enhanced the
Scheduler
interface - Issue #102 - brought back
sun.misc.Unsafe
(actually this was done in separate project, as part of issue #104) - Issue #104 - separated the
Atomic
implementations - Issue #106 - enabled code coverage reports
- Issue #111 - improved test coverage
- Issue #114 - initiated the
benchmarks
sub-project to track performance issues - Issue #115 -
Cancelable.cancel
now returnsUnit
and notBoolean
- Issue #118 - Fix
materialize
, adddematerialize
- Issue #119 - Introduced
Pipe
, renamedChannel
inConcurrentSubject
, renamedSynchronousObserver
inSyncObserver
, renamedSynchronousSubscriber
inSyncSubscriber
- Issue #121 - Clarified the contract for synchronous
pipelines, got rid of the hacks from
internal
, replacing them with macro-driven extensions forFuture[Ack]
- Issue #123 - Changed the protocol of
Observable.subscribe
, back-pressuringonComplete
andonError
is now optional andObservable.unsafeSubscribeFn
needs to return a usableCancelable
instead ofUnit
(big internal change) - Issue #125 - Modified contract of
AsyncScheduler
, added a newExecutorScheduler
- Issue #88: the
Task
implementation has been redesigned from scratch - Issue #89: Cats integration has been tried and yielded very positive results, but is being delayed
- Issue #96
and issue 99: add
MulticastStrategy
for safer building of multicast Observables - Issue #127: Introduce operators onErrorHandle and onErrorHandleWith
- Issue #128: operators
materialize, dematerialize and memoize for
Task
(andCoeval
) - Issue #113: Introduce the
bufferIntrospective
operator - Issue #123: underlying protocol
changes, did some fixes for the work that already happened for
M1
- Issue #131: renamed
Ack.Cancel
toAck.Stop
in order to differentiate it as a verb fromCancelable.cancel
, because in version2.0
they are two different actions (and it’s more semantically correct this way) - Issue #132: introduced the
Observable.onCancelTriggerError
operator - Issue #133: introduced the
Observable.doOnDownstreamStop
anddoOnCancel
(which is one reason for #131) - Issue #134:
New operator
Observable.switchIfEmpty
- Issue #136:
Clarify reactive streams, initiated
monix.execution.rstreams
for reusable subscription types and added theReactivePublisher
type-class for things that can be converted toorg.reactivestreams.Publisher
(both Observable and Task are instances) - Issue #140: Add type-class hierarchy, to be integrated with both Cats and Scalaz
- Issue #141: reimplement Task from scratch, introduce Coeval, introduce Scheduler.executionModel
- Issue #143 - on RefCountObservable cancel and stop should be idempotent
- Issue #144 - fix Observable.zip
- Issue #147 - Make
BehaviorSubject
andReplaySubject
remove subscribers that triggeredStop
while connecting, thus freeing the memory sooner, otherwise the GC cannot free the subscriber because its reference is kept captive until the nextSubject.onNext
- Issue #89 - reintroducing a minimal
Cats integration, along with tests based on
cats-laws
. We are splittingmonix.type
into its own sub-project andmonix-cats
depends on it. This ensures that the pick what you use approach also works withmonix-cats
, as people wanting justTask
should not getObservable
, yetObservable
needs integration as well. - Issue #149 - documentation related fixes
- Improved the description of
Task
Task.unit
is now a final valTask.never
now shares the reference instead of building a new instance every time- Exposing
Task.unsafeStartNow
andTask.unsafeStartAsync
, as otherwiseTask.unsafeCreate
is useless. So we should expose all of them, or none at all. FutureUtils.Extensions.dematerialize
was named “materialize” (WTF!) and is renamed- Task should inherit just from
Serializable
and not fromProduct
- Improved the description of
- Issue #150 - add a new
Task.doOnFinish
operator that executes once a task is finished. - Issue #151 - changing
Future.sequence
to be ordered in both execution and effects - Issue #152 - introduce
Task.gather
which behaves like the previoussequence
andTask.gatherUnordered
which doesn’t do ordering for results either. - Bug 153 - Task.sequence and Task.gather return a shared mutable.ListBuffer
- Bug #153: already fixed in
2.0-RC5
forTask
, but now also fixed forCoeval
- Issue #155: Coeval enhancements and fixes
- Issue #156: Adding
Observable.doOnTerminate
for executing a piece of logic whenonComplete
oronError
happens, or when the subscriber stops the streaming withStop
- Issue #158:
Observable.fromIterator
takes now an optionalonFinish
callback for resource deallocation, because theIterator
interface doesn’t provide aclose()
that could be used - Issue #163: added
Observable.fromInputStream
,fromCharsReader
andfromLinesReader
for reading fromjava.io.InputStream
,java.io.Reader
andjava.io.BufferedReader
data sources - Issue #164: Add
Observable.executeOn
, as alternative toobserveOn
- Issue #165: Simplification of the Cats integration
- Issue #157: Renaming
Observable.doOnCancel
todoOnSubscriptionCancel
because its meaning has changed since Monifu 1.x and it will cause pain - Issue #160 (breaking change):
Revamp the buffer operators on
Observable
- Issue #161 (breaking change): Revamp the ConcurrentSubject and Pipe constructors
- Issue #171:
Add Scheduler builder on the JVM that allows specifying
just the
ExecutionModel
, falling backglobal
otherwise - Issue #174: Scalaz integration (in addition to the Cats integration) for FP goddess
- Issue #175:
Reintroduce all of project
Sincron
intomonix-execution
, which means that nowmonix-execution
exposesAtomic
references. This project was split from Monix, but the decision didn’t make sense and the exposed functionality is super useful and in the spirit ofmonix-execution
- Issue #176: now that we
have
Task
, we introduceTaskApp
, a safeApp
type that allows one to specify pure programs - Issue #170:
Task.materializeAttempt
doesn’t work forBindAsync
, leading toonErrorHandleWith
not working with errors triggered inflatMap
on async tasks - Issue #184: introducing the
Consumer
type, a factory of subscribers that makes it easier to specify reusable and composable consumers and for example, it makes it possible, out of the box, to load-balance the workload between multiple subscribers in parallel; see the description - Issue #186 (related to
issue #168): adds the
Observable.interleave2
operator, similar with the one inFS2
(former scalaz-streams) - Issue #180: the
Observer.feed
function now has an overload that does not take a cancelable, because it’s awkward coming up with one if it isn’t needed; there’s also aonNextAll
extension for bothObserver
andSubscriber
which can push a whole collection of events - Issue #187: integrates
the
MonadCombine
type-class from Cats, being similar to the ScalazMonadPlus
, as somehow this was missed in the initial integration - Issue #177 reviews exposed
traits and abstract classes, making sure they inherit from
Serializable
- Issue #85: small change,
clarifies the ScalaDoc on theRefCountCancelable
type - Issue #162: implements
the
Observable.takeUntil(trigger: Observable[Any])
operator, an operator that takes from the source until another observable triggers an event - Issue #189: for
Observable
operators that return a single item (e.g.sumF
,foldLeftF
, etc.) adds variants that do the same thing, but returnTask
results instead, so now we havefoldLeftL
,sumL
, etc. that return tasks - Issue #190: changes many
observable operators, that were taking by-name parameters or initial state
parameters (e.g.
headOrElseF
,foldLeftF
, etc), to takeCoeval
params instead, in order to have fine control over the evaluation model - Issue #191: introduces
by default an implicit conversion from
Any
toCoeval.Now
, to make it easier to useCoeval
as function parameters - the default will thus simply be strict evaluation, strictness being usually the default in Scala - Issue #181: the default operators
on
CancelableFuture
are triggeringStackOverflow
exceptions - Issue #196: Add the
Consumer.create
builder - Issue #166: Generalize
Task.sequence
,Task.gather
andTask.gatherUnordered
for arbitrary collections - Issue #193: Task Applicative instance doesn’t run the tasks in parallel
- Issue #194:
Task.mapBoth
is not stack-safe - Issue #200: Add an
executeNow
extension method forScheduler
, taking a by-name callback, as initializingRunnable
instances is too annoying - Issue #201: Fixes and
optimizes
Task.gatherUnordered
- as an edge-case, it wasn’t stack safe and it has been optimized to be more efficient - Issue #202: Added
asyncOnSuccess
andasyncOnError
as extension methods forCallback
and madeTask.create
safe by forcing an asynchronous boundary when calling the callback (onSuccess/onError); also optimizesTask.chooseFirstOfList
andTestScheduler
- Issue #203: Changed
the
onOverflow
function signature forOverflowStrategy
types supporting it - it can now return anOption
and if it returnsNone
, then we don’t signal any messages downstream, thus making it easier to just log that overflow happened without extra tricks - Issue #208: Uniquely name threads generated from ThreadFactory
- Issue #210: Refactorings for performance and coherence reasons
- Issue #207: Task flatMap loop isn’t cancelable
- Issue #210: Fixed
CompositeCancelable.remove
, a bug introduced in the last release (RC10) - Issue #212: Upgraded Cats to version 0.7.0
- Issue #214: optimize Task, refactorings, some deprecations
- Issue #211:
CompositeCancelable.remove
wasn’t working after the changes in RC10, fixed it in RC11 and now added some more tests - Issue #213: Fixes
Task
/Coeval
memoize operation - Issue #215:
the instance created by
Task.gatherUnordered
keeps state and has problems running (withrunAsync
) a second time - Issue #216:
Change type-class design in
monix.types
to an encoding inspired by the Scato and Scalaz 8, cleaning up the available types; also enable 2.12.0-M5 support, although releases are not automatic, because Cats doesn’t yet support Scala 2.12
Enjoy!