Skip to content

Cache the keycache location resolution instead of redoing it per operation#223

Open
djw8605 wants to merge 1 commit into
scitokens:masterfrom
djw8605:perf/keycache-location-cache
Open

Cache the keycache location resolution instead of redoing it per operation#223
djw8605 wants to merge 1 commit into
scitokens:masterfrom
djw8605:perf/keycache-location-cache

Conversation

@djw8605

@djw8605 djw8605 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Problem

resolve_cache_location() runs for every keycache operation — at least once per token validation, twice for validations that also store keys. Each call performs:

  1. getpwuid_r (password-database lookup),
  2. two mkdir calls,
  3. a full SQLite open / CREATE TABLE IF NOT EXISTS / close round trip (initialize_cachedb),

…after which the caller opens the database a second time to do the actual query. That's two SQLite opens plus a DDL statement on the hot path of every validation, even with a warm cache.

Fix

  • Split the existing logic into resolve_cache_location_uncached() and a caching wrapper.
  • The cache is invalidated via a generation counter that configuration changes affecting the location (keycache.cache_home, keycache.allow_in_memory) bump.
  • Failed resolutions are not cached, so transient permission/disk problems keep being retried.

Also sets the SQLite busy timeout in get_all_issuers_from_db() — the only DB path missing it — so a concurrent write no longer makes the background refresher silently return a partial issuer list.

Behavior note

A change to $XDG_CACHE_HOME after the first resolution is no longer picked up automatically (setting keycache.cache_home still invalidates immediately). Mutating the environment mid-process was of dubious reliability before.

Testing

  • ctest unit, env_config, and monitoring suites pass — including SetGetConfiguredCacheHome/GetKeycacheLocation, which change the cache home mid-run and exercise the invalidation path.

🤖 Generated with Claude Code

…ation

resolve_cache_location() was called for every keycache operation --
at least once per token validation -- and each call performed
getpwuid_r, two mkdir calls, and a full SQLite open / CREATE TABLE /
close round trip via initialize_cachedb(), after which the caller
opened the database a second time to do actual work.

Cache the successful resolution behind a generation counter that
configuration changes affecting the location (keycache.cache_home,
keycache.allow_in_memory) bump for invalidation.  Failed resolutions
are not cached, so transient permission/disk problems are retried.

One behavior note: a change to  after the first
resolution is no longer picked up automatically (a cache-home config
change still invalidates); environment mutation mid-process was of
dubious reliability before.

Also set the SQLite busy timeout in get_all_issuers_from_db() -- the
only DB path without it -- so a concurrent write no longer makes the
background refresher silently see a partial issuer list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant