Skip to content

feat: in-memory LRU email body cache#1281

Merged
andrinoff merged 5 commits into
floatpane:masterfrom
mavonx:fix/issue-1171
May 16, 2026
Merged

feat: in-memory LRU email body cache#1281
andrinoff merged 5 commits into
floatpane:masterfrom
mavonx:fix/issue-1171

Conversation

@mavonx
Copy link
Copy Markdown
Contributor

@mavonx mavonx commented May 12, 2026

What?

Replaces the disk-only email body cache with an in-memory LRU cache backed by write-through disk persistence.

  • Single global LRU instance shared across all folders via sync.Once singleton.
  • Fast Get() and Put() operations — O(1) via hashmap + doubly-linked list.
  • Write-through: every Get() and Put() immediately persists to disk, so no data is lost on crash.
  • Eviction removes least-recently-used entries from both memory and disk atomically.
  • On the first GetLRUInstance() call, LoadFromDisk() restores LRU order using LastAccessedAt timestamps sorted oldest-first, so the most recently accessed email ends up at the front.

Why?

The previous disk-only approach had two bottlenecks: GetCachedEmailBody() read the entire folder JSON file on every call, and pruneEmailBodyCacheSize() loaded all folder files on every SaveEmailBody() call. With multiple accounts and many folders, this becomes expensive.

Related #1171

@mavonx mavonx requested a review from a team as a code owner May 12, 2026 22:50
@floatpanebot floatpanebot added area/config Configuration / settings enhancement New feature or request size/L Diff: 201–800 lines labels May 12, 2026
@andrinoff
Copy link
Copy Markdown
Member

@mavonx tests fail

@mavonx
Copy link
Copy Markdown
Contributor Author

mavonx commented May 13, 2026

@andrinoff

I will double-check this again tonight.

Comment thread config/lru.go
Comment thread config/lru.go
Comment thread config/lru.go Outdated
}

if err := lru.LoadFromDisk(); err != nil {
fmt.Printf("Failed to load LRU from disk: %v\n", err)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we use log.Printf

@andrinoff
Copy link
Copy Markdown
Member

@andrinoff

Fine, I’m just busy right now. When I get back home, I’ll fix those issues and then commit the changes.

Yeah, no worries, I'm just trying to triage as many PRs as I can, i'm very busy

@mavonx
Copy link
Copy Markdown
Contributor Author

mavonx commented May 14, 2026

@andrinoff

I’ll check why the tests are failing tonight, but I’ve already addressed your RCs.

@mavonx mavonx requested a review from andrinoff May 14, 2026 15:57
@mavonx
Copy link
Copy Markdown
Contributor Author

mavonx commented May 15, 2026

@andrinoff

I think we're ready now.

Copy link
Copy Markdown
Member

@andrinoff andrinoff left a comment

Choose a reason for hiding this comment

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

The LRU struct has no sync.Mutex or sync.RWMutex. Every method — Get, Put, Delete, evict, and now the threshold update in GetLRUInstance — touches lru.cache, lru.ll, and lru.currentSize without any lock.

After it, i'll merge. This could be critical in case of a race

@mavonx mavonx requested a review from andrinoff May 15, 2026 21:34
Copy link
Copy Markdown
Member

@andrinoff andrinoff left a comment

Choose a reason for hiding this comment

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

lgtm

@andrinoff andrinoff merged commit 86dbe96 into floatpane:master May 16, 2026
14 checks passed
@mavonx mavonx deleted the fix/issue-1171 branch May 16, 2026 05:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Configuration / settings enhancement New feature or request size/L Diff: 201–800 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants