Reactor Core v3.4.0 Release Notes
Release Date: 2020-10-27 // about 4 years ago-
๐ Reactor-Core
3.4.0
is part of2020.0.0
Release Train (codenameEuropium
).๐ This is the first GA release of Europium ๐
This note focuses on
3.4.0
proper, curating changes from across all milestones.
๐ Note that the 3.4.0 effort was started right after3.3.5.RELEASE
, so this version also contains changes from 3.3.6 to 3.3.11 (see the end of the notes for links).๐ฑ โ ๏ธ Known Issues
- ๐ป the
firstWithValue
new operator has an undocumented way of checking the cause of failure for individual sources, but it uses a suppressed exception rather than a cause. Please refrain from using that, as we'll switch toinitCause
in3.4.1
(and properly document the behavior, setting it in stone) => #2459
โก๏ธ โ ๏ธ Update considerations
๐ฑ โ ๏ธ ๐๏ธ Removals
- โฑ Schedulers deprecated back in 3.3 have been removed (
WorkQueueProcessor
andTopicProcessor
, #2208) - ๐ Previously deprecated methods and types have been removed (see #2277)
๐ฑ โ ๏ธ โ Deprecations
- โฑ
Schedulers.elastic()
and variants are deprecated, to be removed in 3.5 (#1893) - ๐
FluxProcessor
(as well as all concrete implementations of it) are now deprecated and will be removed in 3.5 (#2188, #2431)- see the main focus section below for more details
- ๐ [api-change]
MonoProcessor
is made abstract and deprecated, to be removed in 3.5 (#2188, #1053 / f04bede, #2431)- see the main focus section below for more details
- ๐
Flux.subscribe(Consumer<Subscription>)
variant is deprecated, to be removed in 3.5 (#1825) - ๐ฆ
first
is deprecated to be renamed tofirstWithSignal
(seefirstWithValue
in the new features below). The old deprecated method will be removed in 3.5 (#2173) Context
changes (#2282):- Operators exposing the
Context
at points where there is no use attempting to use write methods are deprecated and will be removed in 3.5 (#2293, 7d6c862) - these all receive a
ContextView
-based variant (see new features below) deferWithContext
=>deferContextual
with aContextView
Signal.getContext()
=>Signal.getContextView()
- Operators modifying the
Context
are renamed to be clearer. Old names are deprecated and will be removed in 3.5 (see new feature below, #2148, eed93d6)
- Operators exposing the
๐ฑ โ ๏ธ โป๏ธ Behavior Changes
- Most operators that take a
Duration
and convert it to milliseconds now use nanosecond precision (#1734) - ๐
Operators.onErrorDropped
no longer throws, but only logs the dropped exception (#1431) - ๐ฆ When an
onError
signal reaches the last (lambda based) subscriber in a chain which doesn't have an error handler, the exception is no longer thrown but only logged (#2176) - โฑ Vanilla implementations of
Scheduler
now initiate their backing infrastructure and applySchedulers
decorator instart()
rather than the constructor (#1778)start()
is also now implicitly called when instantiating aScheduler
via theSchedulers.Factory
- Allows to avoid
this
leaking from constructor - โ ๏ธ Custom implementations should similarly initialized and optionally decorate in
start()
EmitterProcessor
with a full backpressure queue no longer blocks until data is requested, but fails fast (#2049)- Metrics changes
- Change in how metric meters/tags are named in accordance with the
name
operator (#1928, #2302) flow
tag has been removed entirely- using the
name({String})
operator will replacereactor.
prefix in meter names with the user-provided{String}.
- โ ๏ธ using custom tags via the
tags(String...)
operator, but notname(String)
still creates a sparse set of tags in the application which could be rejected by some metrics backend - Change name of some meters that used to include (redundant) unit names (#1807)
reactor_requested_requested_amount
=>{name}_requested
reactor_subscribed_subscribers
=>{name}_subscribed
- notice these meters also take the user-provided
{name}
into account from the above change - Differentiate empty vs valued sequences in metrics via the
status
tag, introducingcompletedEmpty
value (#1803)
- Change in how metric meters/tags are named in accordance with the
๐ฑ โ ๏ธ โจ Main focus:
Sinks
๐
Sinks
are a new API constructed to replace theFluxProcessor
andMonoProcessor
APIs, which have been deprecated (#2431, #1053).We distinguish
Sinks.Many<T>
(aFlux
-like sink),Sinks.One<T>
(aMono
-like sink) andSinks.Empty
(aMono<Void>
-like sink).These sinks are constructed through specs under the
Sinks
class. They expose a two-faced API:- methods starting with
tryEmit
are atomic, never throw (#2319, #2329, #2336, #2426) and immediately return anEmitResult
enum (originally named Emission) indicating various variations of success or error (#2319, #2338) - 0๏ธโฃ methods starting with
emit
attempt to provide an easier facade over the above, take anEmitFailureHandler
allowing to fine tune some aspects of the default behavior (#2377)
0๏ธโฃ By default, the instances are "serialized", detecting parallel usage and failing fast in
tryEmit
(#2342, #2410, #2365, 19fc1ba, #2412).
The vanilla reactor sink implementations ofemit
API terminate with the equivalent of anemitError
when parallel usage is detected (#2365) but by using theEmitFailureHandler
to drive the sink to retry, possibly with a small amount of sleeping, it should be possible to optimistically get rid of the contention.It is also possible to get a low-overhead, low-protection instance of vanilla sinks by using the
Sinks.unsafe()
spec (#2418).
This doesn't detect parallel usage, so it must be used in a responsible way (in a context where the Reactive Streams contract is already externally enforced).Sinks also expose a
asFlux()
view (orasMono()
, as relevant) for them to be passed to downstream and subscribed, and also expose a bit of state throughcurrentSubscriberCount()
getter (#2372) and by beingScannable
(at a minimum forTERMINATED
andCANCELLED
attributes, #2394).Compared to existing processors, most flavors have a sink equivalent except
DirectProcessor
, with two close cousins underSinks.many().multicast()
(#2392, #2451):directAllOrNothing
will ignoretryEmitNext
attempts when at least one subscriber doesn't have enough demand,directBestEffort
will instead push to the subset of subscribers with demand and drop from the perspective of slow subscribers.
๐ This differs from
DirectProcessor
in the sense that both these sinks are kept open in such a situation, so slow subscribers that increase their request will start seeing values pushed after that (instead of being immediately terminated in DirectProcessor).There is also a new flavor: an
onBackpressureError()
variant of the unicast Sink (#2347)๐ ๐ Bugfixes
๐ See links to Dysprosium releases (3.3.6 to 3.3.11) at the end.
๐ฑ โจ New features
concatMap
now has a variant with 0 prefetch (#2202)- ๐
All
Scannable
operators answer the newAttr.RUN_STYLE
attribute with aRunStyle
enum (#2058, #2123)- the enum allows to identify operators that run synchronously. Attribute is accessible both at
Publisher
andSubscriber
level RunStyle.SYNC
guarantees the operator doesn't change threadsRunStyle.ASYNC
indicates the operator MAY change threadsRunStyle.UNKNOWN
(the default) indicates there's no available information (eg. due to the operator wrapping an arbitraryPublisher
)
- the enum allows to identify operators that run synchronously. Attribute is accessible both at
- ๐ง A Reactor-wide Micrometer
MetricsRegistry
other than the global one can now be configured (#2253, 64fd556)- Use
Metrics.MicrometerConfiguration#useRegistry
for that purpose - The above will attempt to load Micrometer classes, so Micrometer MUST be on the classpath
- Use
- ๐ New reactive context features (#2282):
Context
now extends a simplifiedContextView
API which only expose the read methods (#2279, #2293)- the goal is to avoid exposing a seemingly writable (copy-on-write)
Context
when the only meaningful operations are read operations - exposed in
Signal#getContextView()
,deferContextual
operator (variant to deferWithContext) and newtransformDeferredContextual
operator - Added
transformDeferredContextual
operator that takes aBiFunction
, allowing to access theContextView
in the transformation (#2280 then renamed in #2293) Mono.subscribe(valueConsumer, errorConsumer, ...)
errorConsumer
now gets notified of exceptions thrown by the valueConsumer
(#1995)- Renamed
Context
operators with clearer names (#2148, eed93d6) Mono.subscriberContext()
is not aliased, we now advise to useMono.deferContextual(Mono::just)
to get the exact same behaviorsubscriberContext(Context)
is replaced bycontextWrite(ContextView)
(notice the use ofContextView
)- subscriberContext(Function) is replaced by
contextWrite(Function)
- โ Added method to snapshot factory+global schedulers (#2325, #2326, f9c7993)
- use
Schedulers.setFactoryWithSnapshot(Factory)
to get aSnapshot
object while replacing theFactory
- reset the old factory by using
resetFrom(Snapshot)
- this is used by the reactor-test
VirtualTimeScheduler
to reset previously customized factories
- use
- The
ParallelFlux.subscribe(array)
method is now public to allow delegation in wrappers (#2328) - ๐ฆ The
Retry
object driving#retryWhen
operator can now store user-provided state in the form of aContextView
, which is exposed throughRetrySignal
(#2312, bd8db8a) - The
GroupedFlux#key()
method is now marked as@NonNull
(#2397) - โ Added
firstWithValue
factory operator (#2173, 41c937f)- like
first
, it let multiple sources compete - except it prioritizes valued sources: empty sources are considered irrelevant
- if no source completes with a value, a
NoSuchElementException
is thrown
- like
๐ Improvements
- Have push(emitter) delegate to push(emitter, backpressure) (#2177)
- ๐ป Lazily instantiate exception in Mono#repeatWhenEmpty (#2221)
- ๐ฒ
log()
will log context access at FINE(ST) level and now uses the more correctcurrentContext
prefix (#2220) Mono#materialize()
now takes into account that the source IS aMono
, so it doesn'tcancel()
it when materializing itsonNext
(#2424, 765bfe8)- this could be considered a behavior change, but the previous behavior was unnecessary. cancelling the result of the materialization still propagates to the source.
๐ ๐ Documentation, Tests and Build
- [doc] fix #2170 Make parallel runOn methods doc consistent about work stealing
- [doc] Document Android 21 desugaring options (#2232)
- ๐ [build] #2237 remove most compilation warnings
- [doc] fix #2136 Turn discard/errorMode javadoc tags into plain paragraphs
- ๐ [build] fix #2400 use a different name for the jcstress jar
- ๐ [build] Remove compilation warnings related to jsr305 (85da74b)
๐ ๐ Thanks to the following contributors that also participated to this release
@AayushyaVajpayee, @camsteffen, @cnabro, @hamidshahid, @Inego, @jonenst, @josemalonsom, @OlegDokuka, @robotmrv, @seants, @smaldini, @steppedreckoner, @yschimke
๐ Links to Dysprosium release notes during 3.4.0 development effort
๐ All changes from these releases have been forward-merged into
3.4.0
:- ๐
v3.3.6.RELEASE
- ๐
v3.3.7.RELEASE
- ๐
v3.3.8.RELEASE
- ๐
v3.3.9.RELEASE
- ๐
v3.3.10.RELEASE
- ๐
v3.3.11.RELEASE
- ๐ป the