Skip to content

fix FlatKV cache memory leak - #4084

Merged
cody-littley merged 2 commits into
mainfrom
cjl/fix-cache-retention
Sep 3, 2026
Merged

fix FlatKV cache memory leak#4084
cody-littley merged 2 commits into
mainfrom
cjl/fix-cache-retention

Conversation

@cody-littley

Copy link
Copy Markdown
Contributor

Describe your changes and provide context

fix a (slow) memory leak in the FlatKV cache layer

@cursor

cursor Bot commented Sep 2, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches concurrency and cache lifecycle in the DB read path; behavior is intended to be equivalent aside from fixing retention, but races between in-flight reads and retire/evict are sensitive.

Overview
Fixes a slow memory leak in the FlatKV read-through cache by not keeping per-key valueChan (and buffered read results) on entries after a read finishes or is superseded.

setTerminalStateLocked now centralizes moving entries to available/deleted/failed, enrolling them in the LRU where appropriate, and clearing valueChan. Completion paths use the channel captured at schedule time (resolve, batch reads, injectValue) so waiters still get results after the entry detaches its field.

setRetiredLocked / deleteRetiredLocked go through the same helper so retirements also drop any stale channel reference.

New tests cover an end-to-end Get through the read pool and a randomized fuzz that valueChan != nil iff statusScheduled.

Reviewed by Cursor Bugbot for commit 3dad3b0. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedSep 3, 2026, 1:30 PM

@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.16%. Comparing base (b68026f) to head (3dad3b0).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4084      +/-   ##
==========================================
- Coverage   61.23%   60.16%   -1.07%     
==========================================
  Files        2177     2069     -108     
  Lines      190632   178126   -12506     
==========================================
- Hits       116729   107170    -9559     
+ Misses      62892    60987    -1905     
+ Partials    11011     9969    -1042     
Flag Coverage Δ
sei-chain-pr 88.64% <100.00%> (?)
sei-db 69.80% <ø> (ø)
sei-db-state-db ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
sei-db/db_engine/view/read_cache.go 97.70% <100.00%> (-0.11%) ⬇️

... and 108 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The channel-binding refactor is sound: entry.valueChan is only read in lookupLocked's statusScheduled branch, and both retire paths move the entry to a terminal status under the same lock, so nil'ing the field cannot strand a waiter or hand a reader a nil channel — while it does release the stale buffered value that caused the leak. One non-blocking note on the new fuzz test's effective coverage.

Findings: 0 blocking | 1 non-blocking | 1 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • None at the file/PR level.
  • 1 suggestion(s)/nit(s) flagged inline on specific lines.

Comment thread sei-db/db_engine/view/read_cache_test.go
@blindchaser

Copy link
Copy Markdown
Contributor

it looks the detach logic is something each caller (multiple callers there not limited to ones we addressed) has to remember rather than an invariant. could we fold all fields into one function under cacheEntry struct ?

something like:

func (e *cacheEntry) settleLocked(status valueStatus, value []byte) {
	e.status = status
	e.value = value
	e.valueChan = nil
}

@masih masih added the backport release/v6.7 Backport to release v6.7 label Sep 3, 2026
@cody-littley

Copy link
Copy Markdown
Contributor Author

@blindchaser

Good suggestion, created method (called it setTerminateStateLocked() though).

@cody-littley
cody-littley added this pull request to the merge queue Sep 3, 2026
Merged via the queue into main with commit f6ef2c3 Sep 3, 2026
72 checks passed
@cody-littley
cody-littley deleted the cjl/fix-cache-retention branch September 3, 2026 18:51
@seidroid

seidroid Bot commented Sep 3, 2026

Copy link
Copy Markdown

Created backport PR for release/v6.7:

Please cherry-pick the changes locally and resolve any conflicts.

git fetch origin backport-4084-to-release/v6.7
git worktree add --checkout .worktree/backport-4084-to-release/v6.7 backport-4084-to-release/v6.7
cd .worktree/backport-4084-to-release/v6.7
git reset --hard HEAD^
git cherry-pick -x f6ef2c3e0066c8996c922f50f50f68082541b298
git push --force-with-lease

cody-littley pushed a commit that referenced this pull request Sep 3, 2026
This reverts commit 1258739.

The automated backport applied #4084 to sei-db/db_engine/snapshot/read_cache.go.
That is not the cache wired into FlatKV on this branch — dbcache is — so the leak
went unfixed, and nothing outside the snapshot package references it at all.

It also does not build: main's read_cache_test.go was dropped in verbatim, leaving
a file declaring `package view` inside the snapshot package, calling a test helper
(newTestManagerWithDB) that does not exist here.
masih pushed a commit that referenced this pull request Sep 4, 2026
Backport of #4084 to `release/v6.7`.

---------

Co-authored-by: Cody Littley <56973212+cody-littley@users.noreply.github.com>
Co-authored-by: Cody Littley <cody.littley@seinetwork.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants