FifoCache evicts an unrelated entry when an existing key is re-put
MyBatis version
master (c5e06b1), also present in 3.5.x
Description
FifoCache.cycleKeyList appends the key to the internal Deque on every putObject, without checking whether the key is already tracked. Re-putting an existing key (a normal cache refresh) therefore adds a duplicate entry to the key list while the delegate cache size stays the same. Once the list exceeds size, the cache evicts the oldest key — even though the actual number of cached entries never exceeded the limit — and after several refreshes of the same key, a single eviction pass can remove an entry while duplicates of the refreshed key still occupy list slots, shrinking the effective capacity.
Steps to reproduce
FifoCache cache = new FifoCache(new PerpetualCache("default"));
cache.setSize(2);
cache.putObject(0, 0);
cache.putObject(1, 1);
cache.putObject(0, 0); // refresh existing key
assertNotNull(cache.getObject(1)); // fails: key 1 was evicted, only 2 distinct keys existExpected result
Re-putting an existing key must not evict another entry; eviction should occur only when the number of distinct cached keys exceeds the configured size. Replacing the Deque with a LinkedHashSet preserves FIFO order by first insertion and fixes this. I will submit a PR with a failing test and fix.
Source: mybatis/mybatis-3