Skip to content

feat(segcache): allow segment cache expiry of 0 to cache forever - #800

Merged
javi11 merged 1 commit into
mainfrom
session/nzb-cache-zero-value-6a60dd
Jul 25, 2026
Merged

feat(segcache): allow segment cache expiry of 0 to cache forever#800
javi11 merged 1 commit into
mainfrom
session/nzb-cache-zero-value-6a60dd

Conversation

@javi11

@javi11 javi11 commented Jul 24, 2026

Copy link
Copy Markdown
Owner

What & why

The segment cache expiry could not be set to 0 to keep decoded segments forever. Two layers blocked it:

  • The config slider was capped at min=1.
  • segcache.WithDefaults() silently rewrote any expiry <= 0 back to 24h — so even a 0 that reached the manager was clobbered.

The cache engine itself (SegmentCache.Cleanup) already treats <= 0 as "never expire", so the intent existed but was blocked upstream.

Changes

  • config (internal/config/manager.go): SegmentCacheConfig.ExpiryHours becomes *int so unset and explicit 0 are distinguishable (mirrors the existing Enabled *bool idiom). Validate() normalizes nil -> 24h, preserving the default for unconfigured installs while an explicit 0 means "forever".
  • segcache (internal/nzbfilesystem/segcache/manager.go): drop the ExpiryDuration default from WithDefaults(); the config layer now owns the default, so an explicit "forever" survives.
  • setup (cmd/altmount/cmd/setup.go): dereference the pointer with a defensive nil guard.
  • serve (cmd/altmount/cmd/serve.go): pointer-safe value comparison (intPtrValue) for the dynamic reload detection.
  • frontend (StreamingConfigSection.tsx): expiry slider min=0, renders "Forever" at 0, updated helper text and scale label.

Behavior

ExpiryHours Result
nil (unset) 24h default — no regression for existing installs
explicit 0 Forever (still bounded by the max-size LRU cap)
N N hours

Reviewer notes

  • The *int pointer is the mechanism that distinguishes "never configured" from "explicitly 0"; Validate() guarantees the frontend always receives a concrete number.
  • The 5-min cleanup loop no-ops on expiry when <= 0, but Evict() still enforces the size cap, so "forever" is always bounded by MaxSizeGB.
  • Includes minor Biome auto-formatting in a few unrelated frontend files (ProviderStatusTable, HealthPage, QueuePage, HealthTable) picked up by bun run check.

Verification

  • go build ./... — clean
  • go test ./internal/config/... ./internal/nzbfilesystem/segcache/... — pass
  • bun run check — pass

The segment cache expiry could not be set to 0 to keep decoded segments
forever. Two layers blocked it: the config slider was capped at min=1,
and segcache.WithDefaults() silently rewrote any expiry <= 0 back to 24h,
so even a 0 that reached the manager was clobbered. The cache engine
itself already treats <= 0 as "never expire".

Changes:
- config: SegmentCacheConfig.ExpiryHours becomes *int so "unset" and
  "explicit 0" are distinguishable (mirrors the Enabled *bool idiom).
  Validate() normalizes nil -> 24h, preserving the default for
  unconfigured installs while an explicit 0 means "forever".
- segcache: drop the ExpiryDuration default from WithDefaults(); the
  config layer now owns the default, so an explicit "forever" survives.
- setup: dereference the pointer with a defensive nil guard.
- serve: pointer-safe value comparison (intPtrValue) for the dynamic
  reload detection.
- frontend: expiry slider min=0, renders "Forever" at 0, updated helper
  text and scale label.

Behavior: nil (unset) -> 24h; explicit 0 -> forever (bounded by the size
cap via LRU); N -> N hours.
@javi11
javi11 merged commit 5c71c73 into main Jul 25, 2026
2 checks passed
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