Skip to content

Implement RoutingStorage LRU+remote two-tier backend#4294

Open
yrobla wants to merge 1 commit intomainfrom
issue-4210
Open

Implement RoutingStorage LRU+remote two-tier backend#4294
yrobla wants to merge 1 commit intomainfrom
issue-4210

Conversation

@yrobla
Copy link
Contributor

@yrobla yrobla commented Mar 20, 2026

Summary

Adds RoutingStorage, a two-tier session storage that serves reads from a bounded in-memory LRU cache and falls back to a remote Storage (Redis) on cache misses. Store writes to remote first, only promoting to the local cache on success. DeleteExpired delegates entirely to remote, which owns the TTL source of truth; the local cache self-corrects on subsequent Loads.

Uses github.com/hashicorp/golang-lru/v2 (already a transitive dependency) for a thread-safe generic LRU. NewRoutingStorage panics on maxLocalEntries <= 0 so that callers apply a sensible default (e.g. 1000) before calling.

Fixes #4210

Type of change

  • Bug fix
  • New feature
  • Refactoring (no behavior change)
  • Dependency update
  • Documentation
  • Other (describe):

Test plan

  • Unit tests (task test)
  • E2E tests (task test-e2e)
  • Linting (task lint-fix)
  • Manual testing (describe below)

Changes

File Change

Does this introduce a user-facing change?

Special notes for reviewers

@yrobla yrobla requested a review from Copilot March 20, 2026 15:29
@github-actions github-actions bot added the size/M Medium PR: 300-599 lines changed label Mar 20, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cbae45d38a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@github-actions github-actions bot added size/M Medium PR: 300-599 lines changed and removed size/M Medium PR: 300-599 lines changed labels Mar 20, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new two-tier session.Storage implementation that fronts a remote storage backend (e.g., Redis) with a bounded in-memory LRU to reduce remote round-trips while preserving remote durability/authority.

Changes:

  • Introduce RoutingStorage implementing the session.Storage interface with local LRU + remote fallback.
  • Add a comprehensive unit test suite covering cache hits/misses, eviction, delete semantics, remote failure behavior, and constructor panics.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
pkg/transport/session/storage_routing.go New two-tier storage implementation using hashicorp/golang-lru for local caching and a delegated remote Storage.
pkg/transport/session/storage_routing_test.go Unit tests validating caching behavior, remote delegation, eviction, and concurrency sanity.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov
Copy link

codecov bot commented Mar 20, 2026

Codecov Report

❌ Patch coverage is 67.24138% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.98%. Comparing base (a685e89) to head (7d39d79).

Files with missing lines Patch % Lines
pkg/transport/session/storage_redis.go 0.00% 9 Missing ⚠️
pkg/transport/session/storage_routing.go 86.66% 3 Missing and 3 partials ⚠️
pkg/transport/session/storage_local.go 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4294      +/-   ##
==========================================
+ Coverage   68.85%   68.98%   +0.13%     
==========================================
  Files         473      474       +1     
  Lines       47899    47938      +39     
==========================================
+ Hits        32979    33070      +91     
- Misses      12279    12289      +10     
+ Partials     2641     2579      -62     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions bot added size/M Medium PR: 300-599 lines changed and removed size/M Medium PR: 300-599 lines changed labels Mar 20, 2026
@yrobla yrobla requested a review from jerm-dro as a code owner March 20, 2026 16:07
@yrobla yrobla requested a review from Copilot March 20, 2026 16:07
@github-actions github-actions bot added size/M Medium PR: 300-599 lines changed and removed size/M Medium PR: 300-599 lines changed labels Mar 20, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@yrobla yrobla requested a review from Copilot March 20, 2026 16:24
@github-actions github-actions bot added size/L Large PR: 600-999 lines changed and removed size/M Medium PR: 300-599 lines changed labels Mar 20, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Adds RoutingStorage, a two-tier session storage that serves reads from a
bounded in-memory LRU cache and falls back to a remote Storage (Redis) on
cache misses. Store writes to remote first, only promoting to the local
cache on success. DeleteExpired delegates entirely to remote, which owns
the TTL source of truth; the local cache self-corrects on subsequent Loads.

Uses github.com/hashicorp/golang-lru/v2 (already a transitive dependency)
for a thread-safe generic LRU. NewRoutingStorage panics on maxLocalEntries
<= 0 so that callers apply a sensible default (e.g. 1000) before calling.
@github-actions github-actions bot added size/L Large PR: 600-999 lines changed and removed size/L Large PR: 600-999 lines changed labels Mar 20, 2026
Copy link
Contributor

@jerm-dro jerm-dro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the LRU cache?

The original RFC I proposed mentioned LRU caching, but after seeing this implementation I've reconsidered. The PR correctly identifies that we must refresh Redis TTLs on access — something the RFC didn't account for. That constraint changes the calculus.

Every Load cache hit still calls remote.Touch (Redis EXPIRE), so every request pays a Redis RTT regardless. The LRU only saves deserializing the session payload, but sessions are small and GET and EXPIRE are both O(1) — the RTT dominates.

That means we're taking on significant complexity for a marginal saving: a new Touch method on the Storage interface (breaking change for all implementations), cross-replica staleness edge cases, LRU eviction/recovery logic, and a generated mock.

Suggestion: drop the LRU and have RedisStorage.Load use GETEX instead of GET. GETEX atomically returns the data and refreshes the TTL — the TTL refresh becomes an internal Redis concern, invisible to callers. No Touch, no interface change, no cache invalidation bugs. The RoutingStorage, mock, and Touch additions can all be removed.

If we later find Redis RTT is a bottleneck, we can add a local TTL cache in front, but that would be a different design (no per-hit remote calls, bounded staleness via local expiry, GETEX on cache miss).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Large PR: 600-999 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement RoutingStorage (LRU + Redis fallback)

4 participants