Skip to content

Make the user config cache expiry configurable - #49

Merged
dawid-nowak merged 1 commit into
mainfrom
user-config-cache-expiry
Jul 2, 2026
Merged

Make the user config cache expiry configurable#49
dawid-nowak merged 1 commit into
mainfrom
user-config-cache-expiry

Conversation

@lucarlig

@lucarlig lucarlig commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Problem

The control-plane dataplane publisher rewrites UserConfig keys in Redis every 60s (70s key TTL), but RedisUserConfigStore caches entries in-process with the shared LRU_CACHE_EXPIRY_DURATION of 1 hour, hardcoded in const_values.rs. Any subject already in the cache keeps serving stale config for up to an hour after a change, so newly created or modified virtual servers stay unreachable through the dataplane until a restart.

Reproduced in the cf-integration harness:

  1. Created a new virtual server via the control-plane API.
  2. The publisher wrote it into the owner's Redis UserConfig within one cycle (verified by decoding the msgpack value).
  3. The dataplane kept answering initialize with JSON-RPC -32002 No configuration for 148s+ (more than two publish cycles).
  4. Restarting only the dataplane container made the identical request succeed immediately.

This is also the root cause of the test_mcp_rbac_transport.py per-server endpoint failures: servers and users created at test runtime can never become visible to a running dataplane inside the test window.

See cf-integration reports/2026-07-02-dataplane-change-list.md for the full evidence.

Change

New config option, range 0..max seconds:

--user-config-cache-expiry-seconds
CONTEXTFORGE_GATEWAY_RS_USER_CONFIG_CACHE_EXPIRY_SECONDS
  • Default 60, matching the publisher cadence — worst-case staleness drops from ~60 minutes to ~1 minute.
  • 0 disables caching entirely (the store holds no LRU) and reads Redis on every request — intended for tests that create virtual servers/users at runtime.
  • Only the user config store is affected; session stores keep the existing 1 hour LRU_CACHE_EXPIRY_DURATION, so session lifetimes are unchanged.
  • Cache-hit path now falls through to Redis when an entry expired between lookups instead of returning NoDataForKey.

Verification

cargo fmt --check, clippy --workspace --all-targets -D warnings, deny check advisories licenses, nextest run --workspace (50/50), build --workspace, and bench --no-run all pass.

@lucarlig
lucarlig force-pushed the user-config-cache-expiry branch from c1504c7 to fe8e709 Compare July 2, 2026 09:20
@lucarlig lucarlig changed the title Use a 1 minute expiry for the user config cache Make the user config cache expiry configurable Jul 2, 2026
@lucarlig
lucarlig marked this pull request as ready for review July 2, 2026 09:25
dawid-nowak
dawid-nowak previously approved these changes Jul 2, 2026
The control-plane dataplane publisher rewrites UserConfig keys in Redis
every 60s with a 70s TTL, but RedisUserConfigStore cached entries with
the shared LRU_CACHE_EXPIRY_DURATION of 1 hour, hardcoded in
const_values.rs. Any subject already in the cache kept serving stale
config for up to an hour after a change, so newly created or modified
virtual servers stayed unreachable through the dataplane until a
restart. Reproduced in cf-integration: a new virtual server was present
in Redis within one publish cycle while the dataplane kept answering
-32002 No configuration for 148s+; restarting the dataplane made the
same request succeed immediately.

Add user_config_cache_expiry_seconds to the config surface
(--user-config-cache-expiry-seconds /
CONTEXTFORGE_GATEWAY_RS_USER_CONFIG_CACHE_EXPIRY_SECONDS), defaulting
to 60 to match the publisher cadence. 0 disables caching entirely and
reads Redis on every request, which is useful for tests that create
virtual servers at runtime. Session stores keep the 1 hour expiry so
session lifetimes are unaffected.

Signed-off-by: lucarlig <luca.carlig@ibm.com>
@dawid-nowak
dawid-nowak merged commit 32bc9c0 into main Jul 2, 2026
7 checks passed
@lucarlig lucarlig self-assigned this Jul 6, 2026
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.

2 participants