Message-ID: From: "davecramer (@davecramer)" To: "pgjdbc/pgjdbc" Date: Thu, 14 May 2026 09:57:13 +0000 Subject: Re: [pgjdbc/pgjdbc] PR #3062: feat: type cache rework, codec API, and composite-type round-trip In-Reply-To: References: List-Id: X-GitHub-Author-Login: davecramer X-GitHub-Comment-Id: 4449647421 X-GitHub-Comment-Type: issue_comment X-GitHub-Issue: 3062 X-GitHub-Repo: pgjdbc/pgjdbc X-GitHub-Type: comment X-GitHub-Url: https://github.com/pgjdbc/pgjdbc/pull/3062#issuecomment-4449647421 Content-Type: text/plain; charset=utf-8 why does this require Caffeine The PR uses Caffeine as the backing cache for TypeInfoCache (OID→PgType and name→PgType lookups) and CodecRegistry (OID→Codec lookups). The rationale from the design spec: 1. Size-based eviction — The type cache can grow unbounded if a connection encounters many user-defined types (composites, enums, domains). Caffeine provides LRU eviction without hand-rolling one. 2. Concurrent access — Caffeine's Cache is thread-safe without external synchronization, which matters because TypeInfoCache is shared per-connection and the codec lookup happens on every getObject()/setObject() call. 3. Avoids ConcurrentHashMap.computeIfAbsent deadlock — The spec explicitly calls out that computeIfAbsent can deadlock if the mapping function accesses the same map (which happens when resolving a composite type triggers resolution of its field types). Caffeine's get(key, loader) doesn't have this problem. Could it be done without Caffeine? Yes — a plain ConcurrentHashMap with the get() + putIfAbsent() pattern (which the spec already uses for fieldsByOid) would work. You'd lose automatic size-based eviction, but for a per-connection cache that gets cleared on epoch bump anyway, unbounded growth is unlikely to be a real problem in practice. The epoch-based invalidation already clears everything on DDL. The tradeoff is ~300KB added to the shaded JAR (Caffeine 2.9.3) for what is essentially a convenience over manual ConcurrentHashMap management. Whether that's worth it depends on how much you value the eviction policy vs. JAR size. For most server-side applications it's negligible; for Lambda cold starts or Android it's noticeable.