public class SimpleDequePool<POOLABLE> extends Object
SimpleDequePool
is based on Deque
for idle resources and pending Pool.acquire()
Monos,
allowing both to be ordered either LIFO or FIFO.
It uses non-blocking drain loops to deliver resources to borrowers, which means that a resource could
be handed off on any of the following threads
:
Pool.acquire()
Mono
was subscribedPoolBuilder.acquisitionScheduler(Scheduler)
property of the builder can be used.InstrumentedPool.PoolMetrics
Disposable.Composite, Disposable.Swap
Modifier and Type | Field and Description |
---|---|
protected static AtomicReferenceFieldUpdater<SimpleDequePool,Deque> |
IDLE_RESOURCES |
Modifier and Type | Method and Description |
---|---|
Mono<PooledRef<POOLABLE>> |
acquire()
Manually acquire a
POOLABLE from the pool upon subscription and become responsible for its release. |
Mono<PooledRef<POOLABLE>> |
acquire(Duration timeout)
Manually acquire a
POOLABLE from the pool upon subscription and become responsible for its release. |
int |
acquiredSize()
Measure the current number of resources that have been successfully
acquired and are in active use, outside of the
control of the pool until they're released back to it. |
int |
allocatedSize()
Measure the current number of allocated resources in the
Pool , acquired
or idle. |
PoolConfig<POOLABLE> |
config()
Return the pool's
configuration . |
Mono<Void> |
disposeLater()
|
int |
getMaxAllocatedSize()
Get the maximum number of live resources this
Pool will allow. |
int |
getMaxPendingAcquireSize()
Get the maximum number of
Pool.acquire() this Pool can queue in
a pending state when no available resource is immediately handy (and the Pool
cannot allocate more resources). |
int |
idleSize()
Measure the current number of idle resources in the
Pool . |
boolean |
isDisposed() |
boolean |
isInactiveForMoreThan(Duration duration)
A convenience way to check the pool is inactive, in the sense that
InstrumentedPool.PoolMetrics.acquiredSize() ,
InstrumentedPool.PoolMetrics.idleSize() , InstrumentedPool.PoolMetrics.pendingAcquireSize() and InstrumentedPool.PoolMetrics.allocatedSize() are all at zero
and that the last recorded interaction with the pool (InstrumentedPool.PoolMetrics.secondsSinceLastInteraction() )
was more than or exactly duration ago. |
InstrumentedPool.PoolMetrics |
metrics() |
int |
pendingAcquireSize()
Measure the current number of "pending"
acquire Monos in
the Pool . |
long |
secondsSinceLastInteraction()
Measure the duration in seconds since the pool was last interacted with in a meaningful way.
|
Mono<Integer> |
warmup()
Warms up the
Pool , if needed. |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
dispose, withPoolable
protected static final AtomicReferenceFieldUpdater<SimpleDequePool,Deque> IDLE_RESOURCES
public Mono<PooledRef<POOLABLE>> acquire()
Pool
POOLABLE
from the pool upon subscription and become responsible for its release.
The object is wrapped in a PooledRef
which can be used for manually releasing the object back to the pool
or invalidating it. As a result, you MUST maintain a reference to it throughout the code that makes use of the
underlying resource.
This is typically the case when one needs to wrap the actual resource into a decorator version, where the reference
to the PooledRef
can be stored. On the other hand, if the resource and its usage directly expose reactive
APIs, you might want to prefer to use Pool.withPoolable(Function)
.
The resulting Mono
emits the PooledRef
as the POOLABLE
becomes available. Cancelling the
Subscription
before the POOLABLE
has been emitted will either avoid object
acquisition entirely or will translate to a release
of the POOLABLE
.
Once the resource is emitted though, it is the responsibility of the caller to release the poolable object via
the PooledRef
release methods
when the resource is not used anymore
(directly OR indirectly, eg. the results from multiple statements derived from a DB connection type of resource
have all been processed).
Mono
, each subscription to which represents an individual act of acquiring a pooled object and
manually managing its lifecycle from there onPool.withPoolable(Function)
public Mono<PooledRef<POOLABLE>> acquire(Duration timeout)
Pool
POOLABLE
from the pool upon subscription and become responsible for its release.
The provided Duration
acts as a timeout that only applies if the acquisition is added to the pending
queue, i.e. there is no idle resource and no new resource can be created currently, so one needs to wait
for a release before a resource can be delivered. For a timeout that covers both this pending case and the
time it would take to allocate a new resource, simply apply the Mono.timeout(Duration)
operator to
the returned Mono. For a timeout that only applies to resource allocation, build the pool with the standard
Mono.timeout(Duration)
operator chained to the allocator
.
The object is wrapped in a PooledRef
which can be used for manually releasing the object back to the pool
or invalidating it. As a result, you MUST maintain a reference to it throughout the code that makes use of the
underlying resource.
This is typically the case when one needs to wrap the actual resource into a decorator version, where the reference
to the PooledRef
can be stored. On the other hand, if the resource and its usage directly expose reactive
APIs, you might want to prefer to use Pool.withPoolable(Function)
.
The resulting Mono
emits the PooledRef
as the POOLABLE
becomes available. Cancelling the
Subscription
before the POOLABLE
has been emitted will either avoid object
acquisition entirely or will translate to a release
of the POOLABLE
.
Once the resource is emitted though, it is the responsibility of the caller to release the poolable object via
the PooledRef
release methods
when the resource is not used anymore
(directly OR indirectly, eg. the results from multiple statements derived from a DB connection type of resource
have all been processed).
Mono
, each subscription to which represents an individual act of acquiring a pooled object and
manually managing its lifecycle from there onPool.withPoolable(Function)
public int acquiredSize()
InstrumentedPool.PoolMetrics
acquired
and are in active use, outside of the
control of the pool until they're released back to it. This number is
only incremented after the resource has been successfully allocated and
is about to be handed off to the subscriber of Pool.acquire()
.acquiredSize
in interface InstrumentedPool.PoolMetrics
public Mono<Void> disposeLater()
Pool
Mono
that represents a lazy asynchronous shutdown of this Pool
.
Shutdown doesn't happen until the Mono
is subscribed
.
Otherwise, it performs the same steps as in the imperative counterpart, Pool.dispose()
.
If the pool has been already shut down, returns Mono.empty()
. Completion of
the Mono
indicates completion of the shutdown process.
public int idleSize()
InstrumentedPool.PoolMetrics
Pool
.
Note that some resources might be lazily evicted when they're next considered
for an incoming Pool.acquire()
call. Such resources would still count
towards this method.
idleSize
in interface InstrumentedPool.PoolMetrics
public Mono<Integer> warmup()
Pool
Pool
, if needed. This typically instructs the pool to check for a minimum size and allocate
necessary objects when the minimum is not reached. The resulting Mono
emits the number of extra resources
it created as a result of the allocation minimum
.
Note that no work nor allocation is performed until the Mono
is subscribed to.
Implementations MAY include more behavior, but there is no restriction on the way this method is called by users (it should be possible to call it at any time, as many times as needed or not at all).
Mono
that triggers resource warmup and emits the number of warmed up resourcespublic int pendingAcquireSize()
InstrumentedPool.PoolMetrics
acquire Monos
in
the Pool
.
An acquire is in the pending state when it is attempted at a point when no idle resource is available in the pool, and no new resource can be created.
public boolean isDisposed()
public PoolConfig<POOLABLE> config()
Pool
configuration
.config
in interface Pool<POOLABLE>
PoolConfig
public InstrumentedPool.PoolMetrics metrics()
metrics
in interface InstrumentedPool<POOLABLE>
InstrumentedPool.PoolMetrics
object to be used to get live gauges about the Pool
public int allocatedSize()
InstrumentedPool.PoolMetrics
Pool
, acquired
or idle.allocatedSize
in interface InstrumentedPool.PoolMetrics
Pool
public int getMaxAllocatedSize()
InstrumentedPool.PoolMetrics
Pool
will allow.
A Pool
might be unbounded, in which case this method returns Integer.MAX_VALUE
.
getMaxAllocatedSize
in interface InstrumentedPool.PoolMetrics
Pool
public int getMaxPendingAcquireSize()
InstrumentedPool.PoolMetrics
Pool.acquire()
this Pool
can queue in
a pending state when no available resource is immediately handy (and the Pool
cannot allocate more resources).
A Pool
pending queue might be unbounded, in which case this method returns
Integer.MAX_VALUE
.
getMaxPendingAcquireSize
in interface InstrumentedPool.PoolMetrics
Pool
public long secondsSinceLastInteraction()
InstrumentedPool.PoolMetrics
InstrumentedPool.PoolMetrics.acquiredSize()
, InstrumentedPool.PoolMetrics.idleSize()
, InstrumentedPool.PoolMetrics.pendingAcquireSize()
and InstrumentedPool.PoolMetrics.allocatedSize()
)
are also at zero.
The lower the duration, the greater the chances that an interaction could be occurring in parallel to this call. This is why the duration is truncated to the second. A pool implementation that cannot yet support this measurement MAY choose to return -1 seconds instead.
Interactions include background eviction, disposal of the pool, explicit pool warmup, resource acquisition and release (in the default implementation, any interaction triggering the drain loop)...
secondsSinceLastInteraction
in interface InstrumentedPool.PoolMetrics
InstrumentedPool.PoolMetrics.isInactiveForMoreThan(Duration)
public boolean isInactiveForMoreThan(Duration duration)
InstrumentedPool.PoolMetrics
InstrumentedPool.PoolMetrics.acquiredSize()
,
InstrumentedPool.PoolMetrics.idleSize()
, InstrumentedPool.PoolMetrics.pendingAcquireSize()
and InstrumentedPool.PoolMetrics.allocatedSize()
are all at zero
and that the last recorded interaction with the pool (InstrumentedPool.PoolMetrics.secondsSinceLastInteraction()
)
was more than or exactly duration
ago.isInactiveForMoreThan
in interface InstrumentedPool.PoolMetrics
InstrumentedPool.PoolMetrics.secondsSinceLastInteraction()