4848import org .apache .hc .core5 .http .URIScheme ;
4949import org .apache .hc .core5 .http .io .HttpConnectionFactory ;
5050import org .apache .hc .core5 .io .CloseMode ;
51+ import org .apache .hc .core5 .pool .PoolConcurrencyPolicy ;
52+ import org .apache .hc .core5 .pool .PoolReusePolicy ;
5153import org .apache .hc .core5 .util .TimeValue ;
5254import org .apache .hc .core5 .util .Timeout ;
5355import org .junit .jupiter .api .Test ;
5456
5557class TestPoolingHttpClientConnectionManagerOffLockDisposal {
5658
59+ // Simulates slow close only for GRACEFUL
5760 static final class SleeperConnection implements ManagedHttpClientConnection {
5861 private volatile boolean open = true ;
5962 private volatile Timeout soTimeout = Timeout .DISABLED ;
@@ -189,27 +192,38 @@ private static ConnectionEndpoint lease(final PoolingHttpClientConnectionManager
189192 return mgr .lease (id , route , Timeout .ofSeconds ((int ) sec ), state ).get (Timeout .ofSeconds ((int ) sec ));
190193 }
191194
192- // measure only the lease latency; release happens outside this timing window
195+ // Measure only the lease latency; release happens outside this window
193196 private static long leaseAndMeasure (final PoolingHttpClientConnectionManager mgr ,
194197 final String id , final HttpRoute route , final Object state ,
195198 final long sec ) throws Exception {
196199 final long start = System .nanoTime ();
197200 final ConnectionEndpoint ep = lease (mgr , id , route , state , sec );
198201 final long elapsed = (System .nanoTime () - start ) / 1_000_000L ;
199- // keep-alive so it returns to AVAILABLE; drain happens on a later call
200- mgr .release (ep , state , TimeValue .ofSeconds (30 ));
202+ mgr .release (ep , state , TimeValue .ofSeconds (30 )); // keep-alive, goes back to AVAILABLE
201203 return elapsed ;
202204 }
203205
206+ private static PoolingHttpClientConnectionManager newMgrStrict (final long sleeperMs ) {
207+ return PoolingHttpClientConnectionManagerBuilder .create ()
208+ .setOffLockDisposalEnabled (true )
209+ .setConnPoolPolicy (PoolReusePolicy .LIFO )
210+ .setPoolConcurrencyPolicy (PoolConcurrencyPolicy .STRICT )
211+ .setConnectionFactory (sleeperFactory (sleeperMs ))
212+ .build ();
213+ }
214+
215+ private static PoolingHttpClientConnectionManager newMgrLax (final long sleeperMs ) {
216+ return PoolingHttpClientConnectionManagerBuilder .create ()
217+ .setOffLockDisposalEnabled (true )
218+ .setConnPoolPolicy (PoolReusePolicy .LIFO )
219+ .setPoolConcurrencyPolicy (PoolConcurrencyPolicy .LAX )
220+ .setConnectionFactory (sleeperFactory (sleeperMs ))
221+ .build ();
222+ }
223+
204224 @ Test
205225 void strictEviction_offLock_otherThreadLeasesFast () throws Exception {
206- final PoolingHttpClientConnectionManager mgr =
207- new PoolingHttpClientConnectionManager (
208- new NoopOperator (),
209- org .apache .hc .core5 .pool .PoolConcurrencyPolicy .STRICT ,
210- org .apache .hc .core5 .pool .PoolReusePolicy .LIFO ,
211- TimeValue .NEG_ONE_MILLISECOND ,
212- sleeperFactory (1200 ));
226+ final PoolingHttpClientConnectionManager mgr = newMgrStrict (1200 );
213227
214228 final HttpRoute rA = new HttpRoute (new HttpHost (URIScheme .HTTP .id , "a.example" , 80 ));
215229 final HttpRoute rB = new HttpRoute (new HttpHost (URIScheme .HTTP .id , "b.example" , 80 ));
@@ -220,7 +234,6 @@ void strictEviction_offLock_otherThreadLeasesFast() throws Exception {
220234 mgr .setMaxPerRoute (rB , 1 );
221235 mgr .setMaxPerRoute (rC , 1 );
222236
223- // Seed AVAILABLE A and B
224237 final ConnectionEndpoint epA0 = lease (mgr , "seedA" , rA , null , 2 );
225238 mgr .release (epA0 , null , TimeValue .ofSeconds (30 ));
226239 final ConnectionEndpoint epB0 = lease (mgr , "seedB" , rB , null , 2 );
@@ -256,13 +269,7 @@ void strictEviction_offLock_otherThreadLeasesFast() throws Exception {
256269
257270 @ Test
258271 void leaseNotBlocked_LAX_stateMismatchDiscard_offLockDisposal () throws Exception {
259- final PoolingHttpClientConnectionManager mgr =
260- new PoolingHttpClientConnectionManager (
261- new NoopOperator (),
262- org .apache .hc .core5 .pool .PoolConcurrencyPolicy .LAX ,
263- org .apache .hc .core5 .pool .PoolReusePolicy .LIFO ,
264- TimeValue .NEG_ONE_MILLISECOND ,
265- sleeperFactory (1200 ));
272+ final PoolingHttpClientConnectionManager mgr = newMgrLax (1200 );
266273
267274 final HttpRoute route = new HttpRoute (new HttpHost (URIScheme .HTTP .id , "lax.example" , 80 ));
268275 mgr .setMaxTotal (2 );
@@ -281,6 +288,7 @@ void leaseNotBlocked_LAX_stateMismatchDiscard_offLockDisposal() throws Exception
281288 return (System .nanoTime () - start ) / 1_000_000L ;
282289 };
283290
291+ // T2: concurrent lease "B" should be fast
284292 final Callable <Long > t2Lease = () -> {
285293 Thread .sleep (50 );
286294 return leaseAndMeasure (mgr , "t2" , route , "B" , 2 );
0 commit comments