You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Gary D. Gregory (Jira)" <ji...@apache.org> on 2023/06/05 20:42:00 UTC

[jira] [Closed] (POOL-412) [GenericKeyedObjectPool] ensureMinIdle not work if last idle evicted

     [ https://issues.apache.org/jira/browse/POOL-412?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Gary D. Gregory closed POOL-412.
--------------------------------
    Resolution: Information Provided

> [GenericKeyedObjectPool] ensureMinIdle not work if last idle evicted
> --------------------------------------------------------------------
>
>                 Key: POOL-412
>                 URL: https://issues.apache.org/jira/browse/POOL-412
>             Project: Commons Pool
>          Issue Type: Bug
>    Affects Versions: 2.11.1
>            Reporter: Oleksandr Porytskyi
>            Priority: Major
>
> I'm trying to use GenericKeyedObjectPool with setMinIdlePerKey(1) and setTestWhileIdle(true).  When object failed validation it is removed but never add new one.
> Evictor has two stages:
> 1. In evict() call destroy() -> deregister(key) -> poolMap.remove(k)
> For some reason it removes key if there are no more objects of it.
>  
> 2. In ensureMinIdle() -> 
> for (final K k : poolMap.keySet()) {
> ensureMinIdle(k);
> }
> poolMap does not have my key anymore so will not create object for it.
>  
> Here one test for GenericObjectPool which pass and one for GenericKeyedObjectPool which not pass for same scenario:
> {code:java}
> @Test
> void testGenericKeyedObjectPool() throws Exception {
>   BaseKeyedPooledObjectFactory<String, Object> baseKeyedPooledObjectFactory = new BaseKeyedPooledObjectFactory<>() {
>     @Override
>     public Object create(String key) throws Exception {
>       return null;
>     }
>     @Override
>     public PooledObject<Object> wrap(Object value) {
>       return new DefaultPooledObject<>(value);
>     }
>   };
>   GenericKeyedObjectPoolConfig<Object> genericKeyedObjectPoolConfig = new GenericKeyedObjectPoolConfig<>();
>   int minIdlePerKey = 1;
>   genericKeyedObjectPoolConfig.setMinIdlePerKey(minIdlePerKey);
>   genericKeyedObjectPoolConfig.setTimeBetweenEvictionRuns(Duration.ofSeconds(1));
>   genericKeyedObjectPoolConfig.setMinEvictableIdleTime(Duration.ofSeconds(5));
>   GenericKeyedObjectPool<String, Object> genericKeyedObjectPool = new GenericKeyedObjectPool<>(
>       baseKeyedPooledObjectFactory, genericKeyedObjectPoolConfig);
>   String key = "key";
>   genericKeyedObjectPool.preparePool(key);
>   Assertions.assertTimeoutPreemptively(Duration.ofMinutes(1), () -> {
>     while (genericKeyedObjectPool.getNumIdle(key) != minIdlePerKey)
>       ;
>   });
>   System.out.println("we prepared pool so we have idle");
>   Assertions.assertTimeoutPreemptively(Duration.ofMinutes(1), () -> {
>     while (genericKeyedObjectPool.getNumIdle(key) != 0)
>       ;
>   });
>   System.out.println("after eviction we have no idle");
>   Assertions.assertTimeoutPreemptively(Duration.ofMinutes(1), () -> {
>     while (genericKeyedObjectPool.getNumIdle(key) != minIdlePerKey)
>       ;
>   });
>   System.out.println("NEVER HAPPEN: after eviction ensure min idle");
> }
> @Test
> void testGenericObjectPool() throws Exception {
>   BasePooledObjectFactory<Object> basePooledObjectFactory = new BasePooledObjectFactory<>() {
>     @Override
>     public Object create() throws Exception {
>       return null;
>     }
>     @Override
>     public PooledObject<Object> wrap(Object obj) {
>       return new DefaultPooledObject<>(obj);
>     }
>   };
>   GenericObjectPoolConfig<Object> genericObjectPoolConfig = new GenericObjectPoolConfig<>();
>   int minIdle = 1;
>   genericObjectPoolConfig.setTimeBetweenEvictionRuns(Duration.ofSeconds(1));
>   genericObjectPoolConfig.setMinIdle(minIdle);
>   genericObjectPoolConfig.setMinEvictableIdleTime(Duration.ofSeconds(5));
>   GenericObjectPool<Object> genericObjectPool = new GenericObjectPool<>(basePooledObjectFactory,
>       genericObjectPoolConfig);
>   genericObjectPool.preparePool();
>   Assertions.assertTimeoutPreemptively(Duration.ofMinutes(1), () -> {
>     while (genericObjectPool.getNumIdle() != minIdle)
>       ;
>   });
>   System.out.println("we prepared pool so we have idle");
>   Assertions.assertTimeoutPreemptively(Duration.ofMinutes(1), () -> {
>     while (genericObjectPool.getNumIdle() != 0)
>       ;
>   });
>   System.out.println("after eviction we have no idle");
>   Assertions.assertTimeoutPreemptively(Duration.ofMinutes(1), () -> {
>     while (genericObjectPool.getNumIdle() != minIdle)
>       ;
>   });
>   System.out.println("after eviction ensure min idle");
> }
>  {code}
> As workaround I can't just subclass GenericKeyedObjectPool and alter deregister as it private.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)