feat: complete 2.0.7.12 platform overhaul
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type dashboardCacheEntry struct {
|
||||
value map[string]any
|
||||
expiresAt time.Time
|
||||
building chan struct{}
|
||||
}
|
||||
|
||||
type dashboardSnapshotCache struct {
|
||||
mu sync.Mutex
|
||||
ttl time.Duration
|
||||
generation uint64
|
||||
entries map[string]*dashboardCacheEntry
|
||||
}
|
||||
|
||||
func newDashboardSnapshotCache(ttl time.Duration) *dashboardSnapshotCache {
|
||||
if ttl <= 0 {
|
||||
ttl = 5 * time.Second
|
||||
}
|
||||
return &dashboardSnapshotCache{ttl: ttl, entries: map[string]*dashboardCacheEntry{}}
|
||||
}
|
||||
|
||||
func (c *dashboardSnapshotCache) Get(key string, build func() (map[string]any, error)) (map[string]any, bool, error) {
|
||||
for {
|
||||
now := time.Now()
|
||||
c.mu.Lock()
|
||||
entry := c.entries[key]
|
||||
if entry != nil && entry.value != nil && now.Before(entry.expiresAt) {
|
||||
value := entry.value
|
||||
c.mu.Unlock()
|
||||
return value, true, nil
|
||||
}
|
||||
if entry != nil && entry.building != nil {
|
||||
ready := entry.building
|
||||
c.mu.Unlock()
|
||||
<-ready
|
||||
continue
|
||||
}
|
||||
generation := c.generation
|
||||
ready := make(chan struct{})
|
||||
c.entries[key] = &dashboardCacheEntry{building: ready}
|
||||
c.mu.Unlock()
|
||||
|
||||
value, err := build()
|
||||
|
||||
c.mu.Lock()
|
||||
if generation != c.generation {
|
||||
if current := c.entries[key]; current != nil && current.building == ready {
|
||||
delete(c.entries, key)
|
||||
}
|
||||
close(ready)
|
||||
c.mu.Unlock()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
delete(c.entries, key)
|
||||
close(ready)
|
||||
c.mu.Unlock()
|
||||
return nil, false, err
|
||||
}
|
||||
c.entries[key] = &dashboardCacheEntry{value: value, expiresAt: time.Now().Add(c.ttl)}
|
||||
close(ready)
|
||||
c.mu.Unlock()
|
||||
return value, false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *dashboardSnapshotCache) Invalidate() {
|
||||
c.mu.Lock()
|
||||
c.generation++
|
||||
for key, entry := range c.entries {
|
||||
if entry.building == nil {
|
||||
delete(c.entries, key)
|
||||
}
|
||||
}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
Reference in New Issue
Block a user