You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Stale composite type cache after ALTER TYPE on a recycled pooled connection #171
tokio-postgres's InnerClient.cached_typeinfo.types (a HashMap<Oid, Type>) is warmed by prepare and never invalidated. RecyclingMethod::Fast (the plugin's pool recycle method, src/client.rs) does no cleanup query. So if a composite type is ALTERed (same OID, new field layout) between two queries on the same recycled connection, the second query reads a stale cached Type and CompositeValue::from_sql produces wrong JSON (old field names for new fields, or misaligned field-to-value decoding).
Root cause
prepare calls get_type which resolves a composite's Kind::Composite(fields) and caches the Type keyed by OID in InnerClient.cached_typeinfo.types (tokio-postgres prepare.rs:97, client.rs:138).
RecyclingMethod::Fast only checks Client::is_closed() on recycle — no DEALLOCATE ALL, no cache reset.
ALTER TYPE my_composite ADD ATTRIBUTE new_field text keeps the same OID but changes the field layout. The next prepare's get_type finds the OID in client.type_(oid) (cache hit) and returns the staleType with the old field list.
CompositeValue::from_sql (src/extract.rs) reads fields from the stale cached Type and iterates them against the new wire data → wrong JSON.
Enum types are less affected: EnumLabel::from_sql reads raw bytes as UTF-8 and ignores the cached variant list. Composite types are directly affected because their decoder consumes the cached field list as schema.
Pre-#166, the cache was only warmed on the empty-rows fallback path (rare). PR #168 warms it on every direct result-set query via the pre-resolve prepare, making the stale-read window far wider. The underlying issue (no cache invalidation + RecyclingMethod::Fast) is a tokio-postgres/deadpool limitation the plugin inherited, not introduced by #168.
Suggested fix direction
Call client.clear_type_cache() on connection recycle (if tokio-postgres 0.7 exposes it publicly — needs verification).
Or use a RecyclingMethod::Verified variant that resets session state (at a round-trip cost).
Or track the type-cache version and invalidate on ALTER TYPE — likely impractical.
The cleanest long-term fix is upstream (tokio-postgres invalidating the cache when the server reports a type change), but that's a tokio-postgres issue.
Scope
Pre-existing tokio-postgres limitation. Widened by #168's per-query cache warming. Filed as a follow-up so the direct-connection hang fix can land without expanding scope into connection-recycle / cache-invalidation.
Activity
chore: release 1.0.0-rc.12 (#178)