nandi/gleanpublic Fork 0
d97639c
Commits
Clone
git clone https://git.rickub.com/nandi/glean.git
git clone ssh://git@rickub.com/nandi/glean.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Cap in-memory profile cache size and evict oldest entriesUnverified

Julien Robert committed 2026-05-06T09:37:42+02:00 Browse files
d97639c parent: a0b2768
modified internal/atproto/auth.go +30 -0
@@ -7,6 +7,7 @@ import (
77 "net/http"
88 "os"
99 "sync"
10+ "sync/atomic"
1011 "time"
1112
1213 "github.com/bluesky-social/indigo/atproto/identity"
@@ -128,12 +129,37 @@ var profileCache sync.Map
128129
129130 const profileCacheTTL = 4 * time.Hour
130131
132+// maxProfileCacheSize caps the in-memory profile cache to prevent unbounded
133+// growth. When exceeded, the oldest entries are evicted.
134+const maxProfileCacheSize = 50_000
135+
136+var profileCacheSize atomic.Int64
137+
138+func pruneProfileCache() {
139+ if profileCacheSize.Load() < maxProfileCacheSize {
140+ return
141+ }
142+ var toDelete []string
143+ count := 0
144+ profileCache.Range(func(key, value any) bool {
145+ toDelete = append(toDelete, key.(string))
146+ count++
147+ return count < maxProfileCacheSize/5
148+ })
149+ for _, k := range toDelete {
150+ profileCache.Delete(k)
151+ }
152+ profileCacheSize.Store(int64(len(toDelete)))
153+}
154+
131155 func ResolveProfile(ctx context.Context, did string) Profile {
132156 if cached, ok := profileCache.Load(did); ok {
133157 entry := cached.(*profileEntry)
134158 if time.Since(entry.fetched) < profileCacheTTL {
135159 return entry.profile
136160 }
161+ profileCache.Delete(did)
162+ profileCacheSize.Add(-1)
137163 }
138164
139165 ident, err := ResolveIdentity(ctx, did)
@@ -157,6 +183,10 @@ func ResolveProfile(ctx context.Context, did string) Profile {
157183 p.DisplayName = actor.DisplayName
158184 p.AvatarURL = actor.Avatar
159185
186+ if profileCacheSize.Load() >= maxProfileCacheSize {
187+ pruneProfileCache()
188+ }
160189 profileCache.Store(did, &profileEntry{profile: p, fetched: time.Now()})
190+ profileCacheSize.Add(1)
161191 return p
162192 }
@@ -7,6 +7,7 @@ import (
7 "net/http"7 "net/http"
8 "os"8 "os"
9 "sync"9 "sync"
10+ "sync/atomic"
10 "time"11 "time"
11 12
12 "github.com/bluesky-social/indigo/atproto/identity"13 "github.com/bluesky-social/indigo/atproto/identity"
@@ -128,12 +129,37 @@ var profileCache sync.Map
128 129
129 const profileCacheTTL = 4 * time.Hour130 const profileCacheTTL = 4 * time.Hour
130 131
132+// maxProfileCacheSize caps the in-memory profile cache to prevent unbounded
133+// growth. When exceeded, the oldest entries are evicted.
134+const maxProfileCacheSize = 50_000
135+
136+var profileCacheSize atomic.Int64
137+
138+func pruneProfileCache() {
139+ if profileCacheSize.Load() < maxProfileCacheSize {
140+ return
141+ }
142+ var toDelete []string
143+ count := 0
144+ profileCache.Range(func(key, value any) bool {
145+ toDelete = append(toDelete, key.(string))
146+ count++
147+ return count < maxProfileCacheSize/5
148+ })
149+ for _, k := range toDelete {
150+ profileCache.Delete(k)
151+ }
152+ profileCacheSize.Store(int64(len(toDelete)))
153+}
154+
131 func ResolveProfile(ctx context.Context, did string) Profile {155 func ResolveProfile(ctx context.Context, did string) Profile {
132 if cached, ok := profileCache.Load(did); ok {156 if cached, ok := profileCache.Load(did); ok {
133 entry := cached.(*profileEntry)157 entry := cached.(*profileEntry)
134 if time.Since(entry.fetched) < profileCacheTTL {158 if time.Since(entry.fetched) < profileCacheTTL {
135 return entry.profile159 return entry.profile
136 }160 }
161+ profileCache.Delete(did)
162+ profileCacheSize.Add(-1)
137 }163 }
138 164
139 ident, err := ResolveIdentity(ctx, did)165 ident, err := ResolveIdentity(ctx, did)
@@ -157,6 +183,10 @@ func ResolveProfile(ctx context.Context, did string) Profile {
157 p.DisplayName = actor.DisplayName183 p.DisplayName = actor.DisplayName
158 p.AvatarURL = actor.Avatar184 p.AvatarURL = actor.Avatar
159 185
186+ if profileCacheSize.Load() >= maxProfileCacheSize {
187+ pruneProfileCache()
188+ }
160 profileCache.Store(did, &profileEntry{profile: p, fetched: time.Now()})189 profileCache.Store(did, &profileEntry{profile: p, fetched: time.Now()})
190+ profileCacheSize.Add(1)
161 return p191 return p
162 }192 }