You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Oleksandr Porytskyi (Jira)" <ji...@apache.org> on 2023/04/22 13:29:00 UTC

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

Oleksandr Porytskyi created POOL-412:
----------------------------------------

             Summary: [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


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)