Releases: monix/monix
v3.4.1
This is a minor bug-fixing release for the 3.x series.
Updated dependencies (#1554):
- Scala compiler updated to 2.12.15, 2.13.8 and 3.1.2;
- Typelevel Cats updated to 2.7.0;
- Typelevel Cats-Effect updated to 2.5.4;
- Updated compiler and sbt plugins to latest versions;
Fixes:
Trampoline.trampolineContext
no longer ignores its parent BlockContext (#1544)- Only include JCTools in
executionShadedJCTools
(#1514)
This release was made possible by:
- Alexandru Nedelcu (@alexandru)
- Gabriele Petronella (@gabro)
- Roman Janusz (@ghik)
v3.4.0
The release is binary and source compatible with 3.x series, and was cross-built for the following Scala and ScalaJS versions:
- Scala
2.12
,2.13
and3.0
- Scala.js
1.5.1
WARN: we're dropping compatibility with Scala 2.11
and ScalaJS 0.6.x
. If you still need those you'll have to stay on version 3.3.0
.
Changes in this release:
- Dropped support for Scala
2.11
and Scala.js0.6.x
- Dependency updates:
- Cats
2.6.1
- Cats-Effect
2.5.1
- JCTools
3.3.0
- Cats
- Adds support for Scala 3 (#1326, #1327, #1328, #1329, #1344, #1323)
- Adds
Observable.whileBusyAggregateEvents
(#1320) - Fix tracing in
Coeval
andTask
via a more accurate filter (#1353) - Adds
Observable.throttleLatest
(#1396) - Implement pagination for
Observable
(#1381)
This release was made possible by the work and feedback of:
- Alexandru Nedelcu (@alexandru)
- Dominik Wosiński (@Wosin)
- Lars Hupel (@larsrh)
- Luke Stephenson (@lukestephenson)
- Oleg Pyzhcov (@oleg-py)
- Pau Alarcón (@paualarco)
- Piotr Gawryś (@Avasil)
v3.3.0
The release is binary and source compatible with 3.x.x line.
It is released for the following Scala and ScalaJS versions:
- Scala 2.11: ScalaJS 0.6.x
- Scala 2.12: ScalaJS 0.6.x and 1.3.x
- Scala 2.13: ScalaJS 0.6.x and 1.3.x
Note that most likely, this is going to be the last release on ScalaJS 0.6.x.
We can consider doing backports on-demand.
Highlights
Better Stack Traces
This release includes a highly requested feature of better stack traces for Task
and Coeval
!
Big thanks to @RaasAhsan and @djspiewak for providing the original implementation that we have ported.
They are enabled by default, but it is configurable.
Refer to Stack Traces section for more details.
We have measured about 10-30% performance hit in CACHED mode (the default) in microbenchmarks.
If you have any performance tests, we would greatly appreciate any reports!
If the hit is too big, you can disable the stack traces with -Dmonix.eval.stackTracingMode=none
.
For the following code:
package test.app
import monix.eval.Task
import monix.execution.Scheduler
import cats.implicits._
import scala.concurrent.duration._
object TestTracingApp extends App {
implicit val s = Scheduler.global
def customMethod: Task[Unit] =
Task.now(()).guarantee(Task.sleep(10.millis))
val tracingTestApp: Task[Unit] = for {
_ <- Task.shift
_ <- Task.unit.attempt
_ <- (Task(println("Started the program")), Task.unit).parTupled
_ <- customMethod
_ <- if (true) Task.raiseError(new Exception("boom")) else Task.unit
} yield ()
tracingTestApp.onErrorHandleWith(ex => Task(ex.printStackTrace())).runSyncUnsafe
}
The default (cached) stack trace is going to be:
java.lang.Exception: boom
at test.app.TestTracingApp$.$anonfun$tracingTestApp$5(TestTracingApp.scala:36)
at guarantee @ test.app.TestTracingApp$.customMethod(TestTracingApp.scala:29)
at flatMap @ test.app.TestTracingApp$.$anonfun$tracingTestApp$4(TestTracingApp.scala:35)
at parTupled @ test.app.TestTracingApp$.$anonfun$tracingTestApp$2(TestTracingApp.scala:34)
at parTupled @ test.app.TestTracingApp$.$anonfun$tracingTestApp$2(TestTracingApp.scala:34)
at flatMap @ test.app.TestTracingApp$.$anonfun$tracingTestApp$2(TestTracingApp.scala:34)
at flatMap @ test.app.TestTracingApp$.$anonfun$tracingTestApp$1(TestTracingApp.scala:33)
at flatMap @ test.app.TestTracingApp$.delayedEndpoint$test$app$TestTracingApp$1(TestTracingApp.scala:32)
Before 3.3.0
and with stack traces disabled, stack traces are a mess:
java.lang.Exception: boom
at test.app.TestTracingApp$.$anonfun$tracingTestApp$5(TestTracingApp.scala:36)
at monix.eval.internal.TaskRunLoop$.startFull(TaskRunLoop.scala:188)
at monix.eval.internal.TaskRestartCallback.syncOnSuccess(TaskRestartCallback.scala:101)
at monix.eval.internal.TaskRestartCallback$$anon$1.run(TaskRestartCallback.scala:118)
at monix.execution.internal.Trampoline.monix$execution$internal$Trampoline$$immediateLoop(Trampoline.scala:66)
at monix.execution.internal.Trampoline.startLoop(Trampoline.scala:32)
at monix.execution.schedulers.TrampolineExecutionContext$JVMNormalTrampoline.super$startLoop(TrampolineExecutionContext.scala:142)
at monix.execution.schedulers.TrampolineExecutionContext$JVMNormalTrampoline.$anonfun$startLoop$1(TrampolineExecutionContext.scala:142)
at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:94)
at monix.execution.schedulers.TrampolineExecutionContext$JVMNormalTrampoline.startLoop(TrampolineExecutionContext.scala:142)
at monix.execution.internal.Trampoline.execute(Trampoline.scala:40)
at monix.execution.schedulers.TrampolineExecutionContext.execute(TrampolineExecutionContext.scala:57)
at monix.execution.schedulers.BatchingScheduler.execute(BatchingScheduler.scala:50)
at monix.execution.schedulers.BatchingScheduler.execute$(BatchingScheduler.scala:47)
at monix.execution.schedulers.AsyncScheduler.execute(AsyncScheduler.scala:31)
at monix.eval.internal.TaskRestartCallback.onSuccess(TaskRestartCallback.scala:72)
at monix.eval.internal.TaskRunLoop$.startFull(TaskRunLoop.scala:183)
at monix.eval.internal.TaskRestartCallback.syncOnSuccess(TaskRestartCallback.scala:101)
at monix.eval.internal.TaskRestartCallback.onSuccess(TaskRestartCallback.scala:74)
at monix.eval.internal.TaskSleep$SleepRunnable.run(TaskSleep.scala:71)
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Better Task => Future interop when using Local
Running Task
isolates Local
, which was not available in the Future
, resulting in runToFuture
.
This release enables it and unblocks compelling use cases, such as reading proper request context in Akka HTTP Directive.
We've created an AkkaHTTP Example that demonstrates it.
Latest behavior is:
implicit val s: Scheduler = Scheduler.Implicits.traced
val local = Local(0)
for {
_ <- Task(local.update(1)).runToFuture
value <- Future(local.get)
} yield println(s"Local value in Future $value")
println(s"Local value on the current thread = $value")
// => Local value on the current thread = 0
// => Local value in Future = 1
Task
still isolates the Local
, but the Future
continuation keeps the same reference and can read it.
Before the change, Local
would be 0
in the Future
.
More information about Local
can be found in the new Local documentation.
Relevant updates
- #1205: Observable.mergePrioritizedList
- #1209: Bring back Observable.transform and Transformer alias
- #1198: Fix flatMapIterable calling recursively itself
- #1213: Propagate Local isolation in runToFuture
- #1217: Fix performance regression in bufferSliding
- #1244: Add support for compression: Gzip and deflate
- #1262: Fix bug in Task.runSyncUnsafe related to ContextSwitch
- #1265: Implement Observable#bufferWhile and bufferWhileInclusive
- #1267: Implement Asynchronous Stack Traces for Task
- #1276: Add Task/Coeval convenience methods like .when
- #1282: Add 'as' in Task and Coeval
- #1284: Add left/right builders for Task and Coeval
- #1286: Add none/some builders for Task and Coeval
- #1291: tapEval, tapError methods at Task and Coeval
- #1293: removing no-op onComplete() in Observable.takeByTimespan
- #1299: Fix a bug in Local.value
- #1307: Observable.fromIteratorBuffered
People who made this release possible
- Adrian (@adrian-salajan)
- Alexandru Nedelcu (@alexelcu)
- ctoomey (@ctoomey)
- Dmitro Pochapsky (@pchpsky)
- Georgy Khotyan (@GKhotyan)
- James Yoo (@jyoo980)
- Kasper Kondzielski (@ghostbuster91)
- Pau Alarcón (@paualarco)
- Piotr Gawryś (@Avasil)
- Sandeep Kota (@sandeepkota)
- tafit3 (@tafit3)
- Vladyslav (@VladPodilnyk)
v3.2.2
The release is binary and source compatible with 3.x.x line.
It is released for the following Scala and ScalaJS versions:
- Scala 2.11: ScalaJS 0.6.x
- Scala 2.12: ScalaJS 0.6.x and 1.0.x
- Scala 2.13: ScalaJS 0.6.x and 1.0.x
Relevant updates:
- #1197: Fixes a memory leak in bracket, introduced in 3.2.0
- #1195: Fixes non-deterministic behavior in Observable.zip of sources different size
- #1190: Now Observable.groupBy correctly signals error as a failed stream instead of normal completion
- #1188: Fixes an issue in ForeachAsyncConsumer where it wasn't properly propagaing errors in some cases
- #1187: Fixes an issue where Observable.doAfterSubscribe was not executing its finalizer
- #1186: Observable.interval method now schedules the first tick asynchronously
- #1184: Huge performance improvement in CharsReader, InputStream and LinesReaderObservable
- #1154: Observable.fromInputStream and fromCharsReader now respects the chunkSize
- #1181: Fix MatchError in Iterant.fromReactivePublisher
People who made this release possible:
- Akosh Farkash (@aakoshh)
- Alexander (@ppressives)
- fnqista (@fnqista)
- Kasper Kondzielski (@ghostbuster91)
- Pau Alarcón (@paualarco)
- Piotr Gawryś (@Avasil)
- Vasily Kirichenko (@vasily-kirichenko)
- Viktor Lövgren (@vlovgr)
v3.2.1
v3.2.0
The release is binary and source compatible with 3.x.x line.
It is released for the following Scala and ScalaJS versions:
- Scala 2.11: ScalaJS 0.6.x
- Scala 2.12: ScalaJS 0.6.x and 1.0.x
- Scala 2.13: ScalaJS 0.6.x and 1.0.x
Relevant updates:
- #1087: Bracket should not evaluate "use" if Task was canceled during "acquire"
- #1098: Allow to pass Long in Observable.drop(n)
- #1101: Canceled tasks in Half-Open state should return to Open state in CircuitBreaker
- #1107: Add CommutativeApplicative[Task.Par] instance
- #1106 and #1125: Add Observable.concatMapIterable
- #1117: SyncEffect instance for Coeval
- #1120: Cancel should always wait for the finalizer
- #1126: bufferIntrospective should signal Stop upstream when it is back-pressured
- #1135: Observable.intervalAtFixedRate under-millisecond interval fix
- #1132: Add Iterant.withFilter
- #1129: Add Observable.withFilter
- #1145: Deprecate gather, gatherN, gatherUnordered in favor of parSequence, parSequenceN, parSequenceUnordered
- #1152: Add Consumer.toList
People that made this release possible:
- Allan Timothy Leong (@allantl)
- Eugene Platonov (@jozic)
- Fabien Chaillou (@fchaillou)
- Gabriel Claramunt (@gclaramunt)
- Mantas Indrašius (@mantasindrasius)
- TapanVaishnav (@TapanVaishnav)
- najder-k (@najder-k)
- Oleg Pyzhcov (@oleg-py)
- Pau Alarcón (@paualarco)
- Piotr Gawryś (@Avasil)
- Ross A. Baker (@rossabaker)
- Viet Yen Nguyen (@nguyenvietyen)
- Viktor Dychko (@dychko)
v3.1.0
Version 3.1.0 (November 8, 2019)
The release is binary and source compatible with 3.0.0.
Important updates:
- #1008: Fixed stack safety issue of Observable.combineLatestList for big lists
- #1010: flatMapLoop for Task and Coeval
- #1012: ConcurrentQueue.isEmpty
- #1014: Observable.timeoutOnSlowDownstreamTo
- #1016: Observable.takeUntilEval
- #1057: Fix default scheduleOnce implementation
- #1062: Solves a memory leak which sometimes occurred when using Task with localContextPropagation and non-TracingScheduler
- #1063: Ensure async boundary in TaskCreate if LCP is enabled
- #1064 and #1070: Earlier cancelation in Observable.mapParallel if any task fails
- #1065: Add mapAccumulate to Observable
People that made this release possible:
- Alexandru Nedelcu (@alexandru)
- Allan Timothy Leong (@allantl)
- fdilg (@fdilg)
- Jan Bracker (@jbracker)
- Moritz Bust (@busti)
- mudsam (@mudsam)
- Oleg Pyzhcov (@oleg-py)
- Paweł Kiersznowski (@pk044)
- Piotr Gawryś (@Avasil)
- tanaka takaya (@takayahilton)
- TapanVaishnav (@TapanVaishnav)
v3.0.0
This is the final release of Monix 3.0.0.
Important updates:
Chores:
- #996: improve Observable.publishSelector scaladoc
- #1017: disable Scalafmt checks in build
- #1006: Update sbt to 1.3.0
- #1013: Update sbt-sonatype to 3.6
People that made this release possible:
- Alexandru Nedelcu (@alexandru)
- Oleg Pyzhcov (@oleg-py)
- Piotr Gawryś (@Avasil)
- The Cats and Cats-Effect contributors that worked on and released 2.0.0
v3.0.0-RC5
This is a bug fix release — fixing a critical issue:
- #991 (PR #993):
NullPointerException
inTask
when used in combination withLocal
- #992 (PR #998): hide
InterceptableRunnable
exposed accidentally, refactor it for efficiency - #997: bumped Scala version to 2.12.9 and Scala.js to 0.6.28
This release is binary compatible with 3.0.0-RC4
.
v3.0.0-RC4
Version 3.0.0-RC4 (August 25, 2019)
Last release before 3.0.0
which will be released as soon as Cats-Effect 2.0.0 is available. At the time of writing release notes, it is only waiting on Cats 2.0.0 which is about to release next RC which will become stable version if no critical issues are discovered.
Any other development for this release is now frozen except if we discover critical bugs like memory leaks. All other changes will target 3.1.0
.
3.0.0
will be binary and source compatible with 3.0.0-RC4
for Scala 2.12. Monix itself will be also binary compatible for 2.11 but it will have a dependency on Cats-Effect which is not. See Cats-Effect release notes for more details.
We wish we could release 3.0.0
already but if we released now, we would have to release 4.0.0
for Cats-Effect 2.0 because of 2.11 incompatibility there so we decided to hold on.
It was a rough road but currently we have multiple active maintainers that can do releases going forward, instead of just Alex so we hope it can give you a confidence for the future! :)
Note that Cats-Effect 2.0 is very small release and mostly targeted at support for Scala 2.13 and bug fixes - the upgrade should be limited to bumping version without changing a single line of code.
This release depends on Cats-Effect 1.4.0 and Cats 1.6.1
This release is binary compatible with 3.0.0-RC3
on Scala 2.12.
On Scala 2.11 there is an incompatibility caused by introduction of Scheduler.features
:
exclude[ReversedMissingMethodProblem]("monix.execution.Scheduler.features")
Main changes
Local
There are several fixes related to Local
usage.
- Using
TracingScheduler
will also automatically enable local context propagation inTask
so
running it withrunToFutureOpt
or setting env variable is no longer a necessity. Local.isolate
has a overload for isolatingFuture
which is safer than regularLocal.isolate
.
The Local
model since 3.0.0-RC3
shares by default. To isolate modifications of Local
by
other concurrently running Future
, you have to call Local.isolate
.
In case of Task
, there is a TaskLocal.isolate
version. It is automatically called whenever you run Task
so if your use case is setting correlationId
or similar, it probably won't require any explicit isolation because
your HTTP library will most likely run the Task
per request.
Task Builders
There are two major improvements:
- Now all
Task
builders (Task.create
,Task.async
,Task.fromFuture
etc.) will return aTask
that continues on defaultScheduler
which is the one supplied during execution unless overriden byexecuteOn
. - Callback in
Task.create
is now thread-safe against contract violation (calling it more than once) so does not require synchronization on the user side.
Sub-project: monix-execution
-
PR #946: Expose less implementation details in Local
-
PR #948: Make Task.memoize play well with Local
-
PR #953: Make default scheduler remove cancelled tasks
-
PR #960: Scheduler.features
-
PR #971: Callback tryOnSuccess/tryOnFailure
-
PR #973: Fix Local.isolate corner case
-
PR #977: Use type classes instead of overloads in Local.isolate/bind
Sub-project: monix-eval
-
PR #913: Optimize Task.guarantee
-
PR #921 & PR #917: Callbacks in Task.create are now thread-safe and
always return to the main Scheduler. -
PR #933: Adds >> syntax to Task
-
PR #935: Adds >> syntax to Coeval
-
PR #934: Implement doOnFinish in terms of guaranteeCase
-
PR #951: Add void to Task + Coeval
-
PR #952: Implement ContextShift.evalOn in terms of Task.executeOn
-
PR #954: Add gatherN + wanderN
-
PR #972: Rename
Task.forkAndForget
toTask.startAndForget
Sub-project: monix-reactive
-
PR #906: Fix race in MapParallelOrderedObservable
-
PR #918: switchMap should wait for last child to complete
-
PR #919: propagate cancellation to tasks in async Consumers
-
PR #932: Remove try-catch for EvalOnceObservable implementation
-
PR #941: Added some polymorphic methods for Observable
-
PR #945: Add collectWhile observable
-
PR #958: Add Observable.throttle
-
PR #963: Added fromAsyncStateActionF
-
PR #970: Observable.unfold
-
PR #989: Observable.unfoldEval and Observable.unfoldEvalF
Sub-project: monix-tail
- PR #965: fixes resource handling in Iterant.repeat, adds Iterant.retryIfEmpty
Chores
-
PR #936: Add defaults values for benchmarking
-
Tons of updates by https://github.com/fthomas/scala-steward
Thanks
People that made this release possible, in alphabetical order:
- Alexandru Nedelcu (@alexandru)
- Allan Timothy Leong (@allantl)
- BambooTuna (@BambooTuna)
- Carlo (@entangled90)
- Oleg Pyzhcov (@oleg-py)
- Paul K (@pk044)
- Piotr Gawryś (@Avasil)
- Rahil Bohra (@rahilb)
- Richard Tarczaly (@arlequin-nyc)
- Ryo Fukumuro (@rfkm)
- TapanVaishnav (@TapanVaishnav)
- Valentin Willscher (@valenterry)