返回 DeepSeek-Reasonix
idle_pool.go
根目录 / internal / session / idle_pool.go
1 package session
2
3 import "sync"
4
5 // IdlePool bounds unbound runtime retention across historical storage roots.
6 // It never calls a service while holding its mutex. Victims are only candidates:
7 // the owning service rechecks bindings and execution before retiring them.
8 type IdlePool struct {
9 mu sync.Mutex
10 entries map[*Runtime]idlePoolEntry
11 used int64
12 clock uint64
13 }
14
15 type idlePoolEntry struct {
16 service *Service
17 runtime *Runtime
18 bytes int64
19 order uint64
20 epoch uint64
21 }
22
23 const DesktopIdleBudgetBytes int64 = 256 << 20
24
25 // UseIdlePool must be called before publishing the service to clients.
26 func (s *Service) UseIdlePool(pool *IdlePool) { s.idlePool = pool }
27
28 // MetadataOnlyListings keeps listing observations free of content replay.
29 // Configure it before the service is published; history/search remain explicit.
30 func (s *Service) MetadataOnlyListings() { s.query.metadataOnlyListings = true }
31
32 func (p *IdlePool) add(s *Service, r *Runtime, bytes int64) []idlePoolEntry {
33 p.mu.Lock()
34 defer p.mu.Unlock()
35 if p.entries == nil {
36 p.entries = make(map[*Runtime]idlePoolEntry)
37 }
38 if old, ok := p.entries[r]; ok {
39 p.used -= old.bytes
40 }
41 p.clock++
42 p.entries[r] = idlePoolEntry{service: s, runtime: r, bytes: bytes, order: p.clock, epoch: s.idleOrder[r]}
43 p.used += bytes
44 var victims []idlePoolEntry
45 for p.used > DesktopIdleBudgetBytes && len(p.entries) > 0 {
46 var oldest idlePoolEntry
47 for _, entry := range p.entries {
48 if oldest.runtime == nil || entry.order < oldest.order {
49 oldest = entry
50 }
51 }
52 delete(p.entries, oldest.runtime)
53 p.used -= oldest.bytes
54 victims = append(victims, oldest)
55 }
56 return victims
57 }
58
59 func (p *IdlePool) remove(r *Runtime) {
60 if p == nil {
61 return
62 }
63 p.mu.Lock()
64 defer p.mu.Unlock()
65 if old, ok := p.entries[r]; ok {
66 p.used -= old.bytes
67 delete(p.entries, r)
68 }
69 }
70
70 lines GO