[ 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)