Open chemicL opened 2 years ago
Scheduler
restarts make it harder to implement having onDispose()
. We should consider imposing a contract there to disallow restarts.
The deprecation of restarts is already happening via deprecation of the start()
method and introduction of init()
via https://github.com/reactor/reactor-core/issues/3202
Motivation
Disposable
interface defines thevoid dispose()
method, which is of eager nature and in most cases assumes non graceful, forceful release of underlying resources. There are cases where such an attempt is not desired. Other projects, like reactor-netty, or rsocket-java, have come up with their own abstractions for disposing resources related to connection and request management. In reactor-core, it was also necessary to support graceful disposal of implementations ofScheduler
interface (#3089).Desired solution
It looks that from the existing implementations, the following properties are desired:
To list some examples:
reactor-netty in
DisposableChannel
:Disposable#dispose()
: https://github.com/reactor/reactor-netty/blob/f1f44ae9d39d3321aa9b90c90e36a2720ce9838f/reactor-netty-core/src/main/java/reactor/netty/DisposableChannel.java#L70disposeNow()
anddisposeNow(Duration)
blocking methods that delegate to the forcefuldispose()
: https://github.com/reactor/reactor-netty/blob/f1f44ae9d39d3321aa9b90c90e36a2720ce9838f/reactor-netty-core/src/main/java/reactor/netty/DisposableChannel.java#L89Mono<Void> onDispose()
method: https://github.com/reactor/reactor-netty/blob/f1f44ae9d39d3321aa9b90c90e36a2720ce9838f/reactor-netty-core/src/main/java/reactor/netty/DisposableChannel.java#L127reactor-netty in
LoopResources
:Disposable#dispose()
method: https://github.com/reactor/reactor-netty/blob/cc9aeb2901ed6f727e3e3d5c6bb604d3a3daa1ac/reactor-netty-core/src/main/java/reactor/netty/resources/LoopResources.java#L167Mono<Void> disposeLater()
that delegates toMono<Void> disposeLater(Duration quietPeriod, Duration timeout)
with some default timeout values inLoopResources
: https://github.com/reactor/reactor-netty/blob/cc9aeb2901ed6f727e3e3d5c6bb604d3a3daa1ac/reactor-netty-core/src/main/java/reactor/netty/resources/LoopResources.java#L178Mono<Void> disposeLater()
inConnectionProvider
and lazily implements it inPooledConnectionProvider
: https://github.com/reactor/reactor-netty/blob/0497c91cc093a3ee04855c77434bd40e7d8c7300/reactor-netty-core/src/main/java/reactor/netty/resources/PooledConnectionProvider.java#L186disposeGracefully(Duration)
from reactor-pool (https://github.com/reactor/reactor-pool/blob/5369c64527c4bf4c94d0c3a301236420e5c7af09/src/main/java/reactor/pool/decorators/GracefulShutdownInstrumentedPool.java#L53), which provides a timeout and utilities over thedisposeLater()
fromPool
: https://github.com/reactor/reactor-pool/blob/6e50a6fa82872bc5fe76a7821989de4359e376e5/src/main/java/reactor/pool/Pool.java#L172rsocket-java uses the
DisposableChannel
from reactor-netty with its ownCloseable
interface:Mono<Void> onClose()
method is the essence of theCloseable
interface which allows listening for terminationCloseableChannel
delegates to thedispose()
method ofDisposableChannel
: https://github.com/rsocket/rsocket-java/blob/c80b3cb6437046f3ccc79136a66299448f58c561/rsocket-transport-netty/src/main/java/io/rsocket/transport/netty/server/CloseableChannel.java#L74onDispose()
fromonClose()
: https://github.com/rsocket/rsocket-java/blob/c80b3cb6437046f3ccc79136a66299448f58c561/rsocket-transport-netty/src/main/java/io/rsocket/transport/netty/server/CloseableChannel.java#L84I would argue it's possible to unify these efforts using following methods:
Mono<Void> disposeGracefully()
as part of a newDisposable.Graceful
interface,Mono<Void> onDispose()
potentially added toDisposable
(breaking change) or a new interface, e.g.ListenableDisposable
, which would become a parent ofDisposable.Graceful
.The current
Disposable
already hasvoid dispose()
boolean isDisposed()
Together, they would form a base for extension using concepts specific to a particular use case, e.g. the quietPeriod and deadline in case of reactor-netty, could be expressed as
Mono<Void> disposeGracefully(Duration deadline, Duration quietPeriod)
.Considered alternatives
One alternative would be to assume different use cases have different needs and the unification effort is pointless. However, without a common denominator, the existing APIs differ even within the same project, potentially leading to inconsistencies and lack of easy-to-predict behaviors.