Releases: reactor/reactor-core
v3.4.0-RC1
Reactor-Core 3.4.0.-RC1
is part of 2020.0.0-RC1
Release Train (codename Europium
).
This first Release Candidate brings further changes to the Sinks
API introduced in M2
This release note focuses on RC1-specific changes, but RC1 also contains all the changes released in 3.2.20.RELEASE and 3.3.10.RELEASE.
⚠️ Update considerations and deprecations
Processors and sinks update considerations
The most impactful change is the switch in focus from an API that emulates Subscriber
(with void return types) to a lower level API that can consistently provide immediate feedback to a signalling attempt via the returned Emission
. Now the later is prefixed with tryEmit
. An emit
API is offered as an initial problematic attempt at a higher level abstraction, but it had to be @Deprecated
. See #2374 for potential ways to rewrite code that used to call onNext
/next
/emitNext
-without-checking-returned-Emission in previous versions.
@simonbasle is also preparing a retrospective write up of all the changes through which the sinks API went in #2382.
emitXxx
replaced with tryEmitXxx
- See #2319 : Split emitXxx/tryEmitXxx, more consistent use of hooks.
new Emission.FAIL_xxx
error codes
Emission.FAIL_NON_SERIALIZED
(see #2342 Failing fast on non-serialized access to Sink)Emission.FAIL_ZERO_SUBSCRIBER
(see #2338 Add new Emission FAIL_ZERO_SUBSCRIBER error code)
"safe" onBackpressureError()
not exposed anymore
- See #2375 : Remove
Sinks.many().multicast().onBackpressureError()
.
emitXxx
part of the API to be removed / heavily reworked
- See #2374 : Deprecate Sinks
emit{Next,Error,Complete}
methods.
🐞 Bug fixes
- These are incremental improvements over the
tryEmitNext
API (previouslyemitNext
in M2):
✨ New features and improvements
- #2312 Add user provided state to
Retry
- #2325 Add method to snapshot factory+global schedulers, used by VTS (#2326)
- #2328 Make ParallelFlux.subscribe(array) public to allow delegation
Sinks
related improvements over M2:- [Polish] Add inners[] param to Operators dropMulticast private methods
📖 Documentation, Tests and Build
- [doc] As the custom javadoc tags are not displayed in all IDEs, turned discard/errorMode javadoc tags into plain paragraphs (#2136)
- [build] #2353 Use
api
for reactive streams api dependency import - several typos and inconsistencies fixed by various contributors
- [doc] #2317 Add examples to deprecation notes of processors
- [test] Avoid potential infinite busy looping in tests
- [doc] Polish javadoc of the multicast onBackpressureBuffer Sinks (#2373)
- [doc] Polish variable names in snippet (#2351)
👍 Thanks to the following contributors that also participated to this release
v3.3.10.RELEASE
Reactor-Core 3.3.10.RELEASE
is part of Dysprosium-SR12
Release Train.
This maintenance release contains one small enhancement to DirectProcessor
/EmitterProcessor
.
This version also contains all changes from v3.2.20.RELEASE.
🪲 Bug fixes
- #2356 Have Direct/EmitterProcessor implement currentContext()
📖 Documentation, Tests and Build
- [build] #2308 align reactor-tools test output with others projects
v3.2.20.RELEASE
Reactor-Core 3.2.20.RELEASE
is part of Californium-SR21
Release Train.
This is a maintenance release with a couple bugfixes, as well as build polish.
🪲 Bug fixes
- #2318 Prevent FlatMapInner to request if fused in SYNC mode
- #2362 Prevent ConcurrentModificationEx on bufferPredicate discard
📖 Documentation, Tests and Build
- [build] Various polish of Gradle build (deprecation warnings #2274, wrapper validation #2348)
- [test] #2343 migrate tests to JUnit 5
- [build] #2332 remove optional-dependency plugin from Gradle build
- [reactor-test] Allow add/addAll in AssertQueueSubscription test util (46324db)
👍 Thanks to the following contributors that also participated to this release
v3.4.0-M2
Reactor-Core 3.4.0.-M2
is part of 2020.0.0-M2
Release Train (codename Europium
).
This second milestone brings several important changes:
- further evolution of the way processors and sinks are obtained and used (following up on the changes initiated in M1)
- improvements of the
Context
related APIs - improvements on the
Flux
andMono
metrics
This release note focuses on M2-specific changes, but M2 also contains all the changes released in 3.2.19.RELEASE, 3.3.8.RELEASE and 3.3.9.RELEASE.
⚠️ Update considerations and deprecations
Metrics update considerations
The name()
operator is no longer used in metrics as a tag but as a prefix for the meter names (#1928):
This allows to use custom tags via the tag()
operator, while ensuring unique enough meter names that all bear the same set of tags
The [name].flow.duration
meter has a status
tag that now differentiate between completed
and completedEmpty
(#2313)
This allows to detect eg. empty Mono
s, but code relying on the completed
status should be updated to also take completedEmpty
into account.
The [name].subscribed
and [name].requested
meters have had their unit dropped (#1807):
The unit is part of the name in some backends like prometheus, but the unit was redundant. So the requested amount
and subscribers
unit suffixes have been dropped (separator may vary depending on the metrics backend).
Processors and sinks update considerations
The FluxIdentityProcessor
and Processors
classes that were introduced in M1 have been rolled back, and Sinks
reworked (#2218)
The ultimate goal is to remove the need for processors (or greatly diminish it) and adding processor-related APIs was deemed counterproductive...
The sinks from operators (FluxSinks
and MonoSink
in create
) no longer have a common interface with the "standalone" sinks. The hierarchy has been simplified and we now have 4 uncorrelated interfaces: FluxSink
and MonoSink
(back to what they were in 3.3, oriented towards subscription-like usage) versus Sinks.One
and Sinks.Many
(both oriented towards publisher-like usage).
Sinks
allow building the later two, with a tiered approach:
- chose
many()
vsone()
vsempty()
- Then on
many()
, chose a flavor (unicast()
,multicast()
,replay()
) - Finally, fine tune the flavor to obtain a sink (eg.
Sinks.many().multicast().onBackpressureError()
)
These can also be converted to processors efficiently, as their (private) implementation also implement FluxProcessor
/MonoProcessor
. NB: to convert from a Sinks.Many
/Sinks.One
to a processor where a processor is still relevant, use FluxProcessor.fromSink
and MonoProcessor.fromSink
.
The MonoProcessor
class used to be concrete but final
. It is now abstract
(#1053, #2296)
Most of its implementation has been moved to package-private NextProcessor
. This will allow to introduce more flavors of MonoProcessor
, focusing that class on signaling a Processor<A, B>
that is also a Mono<B>
.
A new flavor VoidProcessor
, has been also immediately added. It backs Sinks.empty()
with less overhead than the old MonoProcessor
.
Sinks.Many
and Sinks.One
APIs
Contrary to operator sinks, these two sinks are to be used more like publisher than like subscribers.
That is to say, they are expected to be passed down asFlux()
or asMono()
, so generally should accommodate multiple subscribers (except for Sinks.many().unicast()
).
As a result they expose a different and more restrained API. Most relevant methods are the emitXxx
methods, which are not fluent but return an Emission
enum.
They can be seen as a "best effort" API, indicating failure through the enum rather than an exception (comparable to Queue#offer
vs Queue#add
in the JDK).
Emission
enum should be checked to detect error cases.
For instance, the EmitterProcessor
used to sleep when its configured buffer was full and users continued trying to emit, effectively busy-looping until the internal queue would accept the pushed valued. This is effectively blocking, and can be problematic (#2049).
The equivalent sink, Sinks.many().multicast().onBackpressureBuffer()
, doesn't sleep/block but immediately returns Emission.FAIL_OVERFLOW
.
Note that to get the old behavior, one can manually loop on the emitNext
attempt until it returns Emission.OK
, sleeping for a few nanoseconds when it returns FAIL_OVERFLOW
. But caller could also decide to fail after a number of retries rather than an infinite loop for instance...
Context
APIs
ContextView
introduction (#2279)
Knowing when a Context
can be "written" vs when it cannot is complicated by the fact that operators that aim at exposing the contextual data only for reading still expose the full Context
API, with write methods.
In M2, we introduce ContextView
, a superinterface to Context
that only bears the read methods of the context.
Operators that expose the context for the purpose of reading from it (and where trying to put
or remove
data would effectively be a no-op) now have an alternative exposing the ContextView
, deprecating the old way:
deferWithContext(Function<Context, P>)
is superseded bydeferContextual(Function<ContextView, P>)
- we introduce
transformDeferredContextual(BiFunction<P1, ContextView, P2>)
Signal#getContext()
is superseded bySignal#getContextView()
Mono.subscriberContext()
is deprecated. No replacement is planned asdeferContextual(Mono::just)
is a readily available replacement.
A Context
is already a ContextView
. In case an API presents a ContextView
but one really need a Context
instead, use Context.of(ContextView)
.
Improve naming of context operators (#2148)
In 3.3, context operators are a bit confusing since they're only differentiated by their inputs. In 3.4 we deprecate these confusing names and provide alternatives:
Mono.subscriberContext()
is to be removed. UseMono.deferContextual(Mono::just)
instead, or even better try to rewrite the code to fully utilize the capacities ofdeferContextual
andtransformDeferredContextual
operators (which could allow reading from theContextView
only once).subscriberContext(Context)
is superseded bycontextWrite(ContextView)
(which better conveys that the entries in the input are added to the currentContext
)subscriberContext(Function<Context, Context>)
is superseded bycontextWrite(Function<Context, Context>)
Other update considerations
- Methods and classes deprecated in 3.3 have been removed (#2277)
- to help with the
retryWhen
migration from legacy throwable-based function, a second adapter has been added (in both M2 and 3.3 latest release):Retry.withThrowable(Function<Flux<Throwable>, Publisher<?>>)
- to help with the
subscribe(..., Consumer<Subscription>)
variant has been deprecated (#1825):- too often, people misuse it to capture or log the
Subscription
but forget torequest
it, resulting in hangs
- too often, people misuse it to capture or log the
Mono.subscribe(valueHandler, errorHandler)
now passed errors in thevalueHandler
to theerrorHandler
(#1995)- All instances of
Scheduler
are now expected to requirestart()
call before usage (#1789)- the impact is limited as
Schedulers.Factory
-produced instances are started automatically bySchedulers
factory methods (eg.Schedulers.parallel()
or evenSchedulers.newBoundedElastic()
)
- the impact is limited as
- when encountering
onError
signal AFTERonComplete
/onError
, operators will now default to only logging the extraneousThrowable
(#1431)- Same with a sequence that is
subscribe
without a error handler (#2176). - This can be tuned by setting a
Hooks.onErrorDropped
. The old behavior of throwing would cause issues and used to break the rules of Reactive Streams
- Same with a sequence that is
- All operators that take a
Duration
now do their best to deal with it in nanosecond precision (#1734)- However this means that the maximum interpretable
Duration
is nowDuration.ofNanos(Long.MAX_VALUE)
(down fromofMillis(Long.MAX_VALUE)
. This leaves us with 296 years as the maximum duration, which should be enough for all intents and purposes...
- However this means that the maximum interpretable
Schedulers.newElastic
andSchedulers.elastic()
are now deprecated, to be removed in 3.5
✨ New features and improvements
- fix #2253 redesign how MetricsRegistry is configured: one can now centrally chose the registry to use instead of micrometer's
globalRegistry
- fix #2058 identify operators with scheduler through new scannable property (#2123)
- Allow "0" prefetch value in
concatMap
(#2202) - fix #2220 Log context access in FINE(ST) level and with correct prefix
- Lazily instantiate exception in Mono#repeatWhenEmpty (#2221)
📖 Documentation, Tests and Build
- various cleanups in code, documentation, tests and build
- [doc] Document Android 21 desugaring options (#2232)
👍 Thanks to the following contributors that also participated to this release
v3.3.9.RELEASE
{TODO}
v3.3.8.RELEASE
Reactor-Core 3.3.8.RELEASE
is part of Dysprosium-SR10
Release Train.
This maintenance release is a recommended update for all Reactor 3 users.
This version also contains all changes from v3.2.19.RELEASE.
🪲 Bug fixes
- Handle
null
publisher inMonoDelayUntil
(#2245) - fix #2260 Avoid onSubscribe race in FluxTimeout (#2266)
📖 Documentation, Tests and Build
- [doc] Fix Scheduler Javadoc (#2190)
- [doc] fix #2199 Fix typo in reference guide
- [build] fix #2264 add blockhound to testset
- [doc] Fix small error in TupleUtils asciidoc (#2201)
- [polish] fix #2246 Remove usage of globalRegistry in metrics tests
- [polish] FluxUsingWhenTest awaitility + order of capturing subscription
- [doc] fix #2257 Improve flatMapIterable prefetch javadoc
👍 Thanks to the following contributors that also participated to this release
v3.2.19.RELEASE
Reactor-Core 3.2.19.RELEASE
is part of Californium-SR20
Release Train.
This is a maintenance release with a couple bugfixes, as well as build polish.
🪲 Bug fixes
- fix #2196: don't hang on repeatWhenEmpty + discard handler
- fix #2186 Align MonoCollect and MonoCollectList to avoid race condition leading to NullPointerException
📖 Documentation, Tests and Build
- [polish] In README Gradle snippet, put maven central repo first (#2248)
- [doc] fix #2212 Improve bufferTimeout() marble
- [build] fix #2251 refactor how micrometer integration is tested
- [build] Rework linking between check, japicmp and downloadBaseline tasks (#2226)
- [build] Bump Kotlin to 1.3.72 (#2247)
- [build] Polish travis CI build to use external script for JDK downloads (#2255)
- [build] fix #2241 Get rid of overcomplicated travis-build.sh but show progress
- [build] fix #2262 Make the fact that optional are not in pom anymore explicit
- [build] Fix input package rule for OSGi metadata generator (#2185)
👍 Thanks to the following contributors that also participated to this release
v3.3.7.RELEASE
reactor-core 3.3.7.RELEASE
is part of Dysprosium-SR9
Release Train.
✨ New features and improvements
🪲 Bug fixes
- Align MonoCollect and MonoCollectList to avoid race condition which leads to NullPointerException (#2186)
- Handle nulls from collectors in
Flux.collect()
(#2181)
📖 Documentation, Tests and Build
- [test] Improve thread regrowth test of boundedElastic/Elastic by considering negative values that might be produced as 0 (no regrowth, aka no increase in the number of active threads from the scheduler).
- [build] Ensure tools fat jar is the one published (#2189)
- [build] Fix input package rule for OSGi metadata generator (#2185)
👍 Thanks to the following contributors that also participated to this release
v3.4.0-M1
Reactor-Core 3.4.0-M1
is the first MILESTONE in the 2020.0.0-M1
Release Train (codename Europium
).
Note that in terms of content this milestone is also aligned with what was released in 3.3.7.RELEASE
⚠️ Update considerations and deprecations
- Introduce
Sinks
and deprecate concrete processors (#2188)- more detailed migration notes to come
- Deprecate
Schedulers.elastic
for 3.5 removal (#1893)- This further enforces the use of the
boundedElastic
flavor
- This further enforces the use of the
- Remove schedulers deprecated in 3.3 (#2208)
✨ New features and improvements
- Handle nulls from collectors in
Flux.collect()
(#2181) - Have
push(emitter
) delegate topush(emitter, backpressure)
(#2177) - Align implementations of
MonoCollect
to be comparable toMonoCollectList
(#2186) - Bump the perf baseline to 3.3.6
🪲 Bug fixes
- Fix input package rule for OSGi metadata generator (#2185)
📖 Documentation, Tests and Build
- [build] master is 3.4 Europium, introduce new versioning scheme (#2140)
- [build] Ensure tools fat jar is the one published (#2189)
- [doc] Make
ParallelFlux
runOn
methods doc consistent about work stealing (#2170) - [doc] Fix 'decided' typo in
coreFeatures.adoc
(#2174)
👍 Thanks to the following contributors that also participated to this release
@jonenst , @rstoyanchev , @Inego , @gurkerl83
v3.3.6.RELEASE
Reactor-Core 3.3.6.RELEASE
is part of Dysprosium-SR8
Release Train.
✨ New features and improvements
- Ensure
DeferredSubscription
makes requests serially if there is racing between set / requestN (according to RS spec Rule 2.7)(#2164) - Ensure
FluxSwitchOnFirst
serializes requests (according to RS spec Rule 2.7) (#2161) - Ensures next element is dropped if
UnicastProcessor
disposed to avoid racing betweenonNext
anddispose
(#2180) - Use
ZoneId.of(String)
to avoid blocking disk load during first access ofSchedulers.boundedElastic()
(#2143)
🪲 Bug fixes
- Accommodate
ASYNC
fusion inMono.metrics()
to avoidNullPointerException
or hanging in certain cases (#2160 ) - Fix volatile read of first element and
ConditionalSubscriber
classcast inFluxSwitchOnFirst
(#2166) - Change the
Subscription
set byreportThrowInSubscribe
to an instance compatible withQueueSubscription
, preventing fused cases where a ClassCastException would be thrown. (#2152 )
📖 Documentation, Tests and Build
- [test] Fix
publishOn
scan test, hiccup before assertingBUFFERED
- [doc] Better describe
Mono.first()
andMono.or()
behavior (#2159) - [doc] Fix typo
Retry.fromFunction()
instead offrom()
(#2172) - [doc] Fix
RetrySpec
doc:throwablePredicate
is actually filter (#2162) - [doc] Document
onCancel
/onDipose
limited to 1 use (#2015) - [doc] Remove wrong curly braces in
generate
code example (#2110) - [build] Have blockHoundTest fork JVM on every case (see #2144)
- [build] Consistently use tabs for gradle file indentation (#2157)
- [publication] Publish Gradle metadata, without optional dependencies (#2151)
👍 Thanks to the following contributors that also participated to this release
@alex-dukhno , @chakas , @berry120 , @OlegDokuka , @PyvesB , @josemalonsom