Files
navi/internal/corebin/cache.go
T
M4andCursor 2ad376b49e
ci / test (macos-latest) (push) Waiting to run
ci / test (ubuntu-latest) (push) Waiting to run
ci / test (windows-latest) (push) Waiting to run
Release 3.8.2.5: cheaper idle UI poll and tighter hot paths.
Delta getState by rev, pause when hidden, cancellable background loops,
hostCache bounds, unlock PollUI around engine status, corebin singleflight,
PingAll worker pool.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-01 16:13:59 +03:00

90 lines
1.9 KiB
Go

package corebin
import (
"strings"
"sync"
"golang.org/x/sync/singleflight"
)
var (
mu sync.Mutex
cache = map[string]string{}
group singleflight.Group
)
// CacheKey identifies a resolved core binary for a binDir + protocol.
func CacheKey(binDir, proto string) string {
return binDir + "\x00" + proto
}
// VirtualPath reports paths that are not on-disk binaries (e.g. embedded AWG).
func VirtualPath(path string) bool {
return strings.HasPrefix(path, "embedded-")
}
// Get returns a cached absolute path if present.
func Get(key string) (string, bool) {
mu.Lock()
defer mu.Unlock()
p, ok := cache[key]
return p, ok
}
// Set stores a resolved path.
func Set(key, path string) {
if key == "" || path == "" {
return
}
mu.Lock()
cache[key] = path
mu.Unlock()
}
// Invalidate clears all cached paths (call after EnsureCore / binDir change / failed Start).
func Invalidate() {
mu.Lock()
cache = map[string]string{}
mu.Unlock()
}
// Resolve caches the result of fn under key.
// Hot-path polls trust the cache until Invalidate (no per-poll os.Stat).
// Embedded/virtual paths never touch the filesystem.
// Concurrent cold misses for the same key share one fn call (singleflight).
func Resolve(key string, fn func() (string, error)) (string, error) {
if path, ok := Get(key); ok {
return path, nil
}
v, err, _ := group.Do(key, func() (any, error) {
if path, ok := Get(key); ok {
return path, nil
}
path, err := fn()
if err != nil {
return "", err
}
Set(key, path)
return path, nil
})
if err != nil {
return "", err
}
path, _ := v.(string)
return path, nil
}
// ProtoKey normalizes protocol to the shared binary cache key (xray covers vless/vmess/trojan).
func ProtoKey(proto string) string {
switch proto {
case "hysteria2":
return "hysteria2"
case "awg":
return "awg"
case "vless", "vmess", "trojan", "xray":
return "xray"
default:
return "naive"
}
}