feat: add TTL to durable forge caches #311

Closed
opened 2026-04-18 16:33:46 +00:00 by barrettruth · 0 comments
barrettruth commented 2026-04-18 16:33:46 +00:00

Prerequisites

  • I have searched existing issues

Problem

Forge currently keeps its durable remote-data caches in memory until an explicit refresh/clear or the Neovim session ends. In practice that means list_cache and repo_info_cache can stay stale indefinitely.

This becomes more important as picker/action availability and Ex completion become more state-aware and rely on cache-backed data with backend fallback. We need an explicit freshness policy instead of treating all cached remote data as valid forever.

picker_session should not be treated as part of this problem: it coordinates inflight/stale async requests, but it is not itself a durable data cache.

Proposed solution

Add TTL support for durable remote-data caches.

Initial scope:

  • list_cache
  • repo_info_cache
  • any new durable remote-data caches introduced for richer action/completion support (for example PR detail/state, CI runs, or checks), so they land on the same cache policy instead of inventing one-off behavior

Expected behavior:

  • cache reads use cached data while it is fresh
  • expired or missing entries fall back to the backend/CLI and refresh the cache
  • explicit refresh actions and clear_cache() remain hard invalidation
  • picker_session remains separate unless it becomes a real data cache in the future

Open design questions:

  • one global TTL vs per-cache/per-surface TTLs
  • whether stale data should ever be shown while a background refresh is happening, or whether expiry should force a blocking refetch
  • which currently non-durable remote data should gain durable caches as part of the same policy

Alternatives considered

  • Keep the current manual-refresh-only model and accept indefinite staleness
  • Add TTL only to one cache and let newer caches each pick their own policy
  • Apply TTL to every cache-like structure, including picker_session, even though some of them are request-coordination state rather than cached remote data
## Prerequisites - [x] I have searched existing issues ## Problem Forge currently keeps its durable remote-data caches in memory until an explicit refresh/clear or the Neovim session ends. In practice that means `list_cache` and `repo_info_cache` can stay stale indefinitely. This becomes more important as picker/action availability and Ex completion become more state-aware and rely on cache-backed data with backend fallback. We need an explicit freshness policy instead of treating all cached remote data as valid forever. `picker_session` should not be treated as part of this problem: it coordinates inflight/stale async requests, but it is not itself a durable data cache. ## Proposed solution Add TTL support for durable remote-data caches. Initial scope: - `list_cache` - `repo_info_cache` - any new durable remote-data caches introduced for richer action/completion support (for example PR detail/state, CI runs, or checks), so they land on the same cache policy instead of inventing one-off behavior Expected behavior: - cache reads use cached data while it is fresh - expired or missing entries fall back to the backend/CLI and refresh the cache - explicit refresh actions and `clear_cache()` remain hard invalidation - `picker_session` remains separate unless it becomes a real data cache in the future Open design questions: - one global TTL vs per-cache/per-surface TTLs - whether stale data should ever be shown while a background refresh is happening, or whether expiry should force a blocking refetch - which currently non-durable remote data should gain durable caches as part of the same policy ## Alternatives considered - Keep the current manual-refresh-only model and accept indefinite staleness - Add TTL only to one cache and let newer caches each pick their own policy - Apply TTL to every cache-like structure, including `picker_session`, even though some of them are request-coordination state rather than cached remote data
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
barrettruth/forge.nvim#311
No description provided.