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
Observablehas been reviewed and changed quite significantly, making observable streams cancelable - many of the
Observableoperators 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,CoevalandObservableare 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
docssub-project with tutorials type-checked as part of the test process - Issue #88 - add
Monix’s own
Task, an alternative toFutureand 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.onSubscribetoObservable.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.createbecause it is unsafe - Issue #100 - enhanced the
Schedulerinterface - Issue #102 - brought back
sun.misc.Unsafe(actually this was done in separate project, as part of issue #104) - Issue #104 - separated the
Atomicimplementations - Issue #106 - enabled code coverage reports
- Issue #111 - improved test coverage
- Issue #114 - initiated the
benchmarkssub-project to track performance issues - Issue #115 -
Cancelable.cancelnow returnsUnitand notBoolean - Issue #118 - Fix
materialize, adddematerialize - Issue #119 - Introduced
Pipe, renamedChannelinConcurrentSubject, renamedSynchronousObserverinSyncObserver, renamedSynchronousSubscriberinSyncSubscriber - 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-pressuringonCompleteandonErroris now optional andObservable.unsafeSubscribeFnneeds to return a usableCancelableinstead ofUnit(big internal change) - Issue #125 - Modified contract of
AsyncScheduler, added a newExecutorScheduler - Issue #88: the
Taskimplementation 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
MulticastStrategyfor 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
bufferIntrospectiveoperator - Issue #123: underlying protocol
changes, did some fixes for the work that already happened for
M1 - Issue #131: renamed
Ack.CanceltoAck.Stopin order to differentiate it as a verb fromCancelable.cancel, because in version2.0they are two different actions (and it’s more semantically correct this way) - Issue #132: introduced the
Observable.onCancelTriggerErroroperator - Issue #133: introduced the
Observable.doOnDownstreamStopanddoOnCancel(which is one reason for #131) - Issue #134:
New operator
Observable.switchIfEmpty - Issue #136:
Clarify reactive streams, initiated
monix.execution.rstreamsfor reusable subscription types and added theReactivePublishertype-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
BehaviorSubjectandReplaySubjectremove subscribers that triggeredStopwhile 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.typeinto its own sub-project andmonix-catsdepends on it. This ensures that the pick what you use approach also works withmonix-cats, as people wanting justTaskshould not getObservable, yetObservableneeds integration as well. - Issue #149 - documentation related fixes
- Improved the description of
Task Task.unitis now a final valTask.nevernow shares the reference instead of building a new instance every time- Exposing
Task.unsafeStartNowandTask.unsafeStartAsync, as otherwiseTask.unsafeCreateis useless. So we should expose all of them, or none at all. FutureUtils.Extensions.dematerializewas named “materialize” (WTF!) and is renamed- Task should inherit just from
Serializableand not fromProduct
- Improved the description of
- Issue #150 - add a new
Task.doOnFinishoperator that executes once a task is finished. - Issue #151 - changing
Future.sequenceto be ordered in both execution and effects - Issue #152 - introduce
Task.gatherwhich behaves like the previoussequenceandTask.gatherUnorderedwhich 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-RC5forTask, but now also fixed forCoeval - Issue #155: Coeval enhancements and fixes
- Issue #156: Adding
Observable.doOnTerminatefor executing a piece of logic whenonCompleteoronErrorhappens, or when the subscriber stops the streaming withStop - Issue #158:
Observable.fromIteratortakes now an optionalonFinishcallback for resource deallocation, because theIteratorinterface doesn’t provide aclose()that could be used - Issue #163: added
Observable.fromInputStream,fromCharsReaderandfromLinesReaderfor reading fromjava.io.InputStream,java.io.Readerandjava.io.BufferedReaderdata sources - Issue #164: Add
Observable.executeOn, as alternative toobserveOn - Issue #165: Simplification of the Cats integration
- Issue #157: Renaming
Observable.doOnCanceltodoOnSubscriptionCancelbecause 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 backglobalotherwise - Issue #174: Scalaz integration (in addition to the Cats integration) for FP goddess
- Issue #175:
Reintroduce all of project
Sincronintomonix-execution, which means that nowmonix-executionexposesAtomicreferences. 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 safeApptype that allows one to specify pure programs - Issue #170:
Task.materializeAttemptdoesn’t work forBindAsync, leading toonErrorHandleWithnot working with errors triggered inflatMapon async tasks - Issue #184: introducing the
Consumertype, 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.interleave2operator, similar with the one inFS2(former scalaz-streams) - Issue #180: the
Observer.feedfunction 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 aonNextAllextension for bothObserverandSubscriberwhich can push a whole collection of events - Issue #187: integrates
the
MonadCombinetype-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 theRefCountCancelabletype - 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
Observableoperators that return a single item (e.g.sumF,foldLeftF, etc.) adds variants that do the same thing, but returnTaskresults 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 takeCoevalparams instead, in order to have fine control over the evaluation model - Issue #191: introduces
by default an implicit conversion from
AnytoCoeval.Now, to make it easier to useCoevalas function parameters - the default will thus simply be strict evaluation, strictness being usually the default in Scala - Issue #181: the default operators
on
CancelableFutureare triggeringStackOverflowexceptions - Issue #196: Add the
Consumer.createbuilder - Issue #166: Generalize
Task.sequence,Task.gatherandTask.gatherUnorderedfor arbitrary collections - Issue #193: Task Applicative instance doesn’t run the tasks in parallel
- Issue #194:
Task.mapBothis not stack-safe - Issue #200: Add an
executeNowextension method forScheduler, taking a by-name callback, as initializingRunnableinstances 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
asyncOnSuccessandasyncOnErroras extension methods forCallbackand madeTask.createsafe by forcing an asynchronous boundary when calling the callback (onSuccess/onError); also optimizesTask.chooseFirstOfListandTestScheduler - Issue #203: Changed
the
onOverflowfunction signature forOverflowStrategytypes supporting it - it can now return anOptionand 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.removewasn’t working after the changes in RC10, fixed it in RC11 and now added some more tests - Issue #213: Fixes
Task/Coevalmemoize operation - Issue #215:
the instance created by
Task.gatherUnorderedkeeps state and has problems running (withrunAsync) a second time - Issue #216:
Change type-class design in
monix.typesto 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!