feat: update dependencies and improve caching mechanism
Some checks failed
PR Check / check-and-test (pull_request) Failing after 2m11s

- Added Prometheus client library for metrics collection.
- Refactored garbage collection strategy from random deletion to LRU (Least Recently Used) deletion.
- Introduced per-key locking in cache to prevent race conditions.
- Enhanced logging with structured log messages for cache hits and misses.
- Implemented a retry mechanism for upstream requests with exponential backoff.
- Updated Go modules and indirect dependencies for better compatibility and performance.
- Removed unused sync filesystem implementation.
- Added version initialization to ensure a default version string.
This commit is contained in:
2025-07-12 06:43:00 -05:00
parent 8c1bb695b8
commit f378d0e81f
13 changed files with 326 additions and 219 deletions

26
vfs/cache/cache.go vendored
View File

@@ -5,6 +5,7 @@ import (
"s1d3sw1ped/SteamCache2/vfs"
"s1d3sw1ped/SteamCache2/vfs/cachestate"
"s1d3sw1ped/SteamCache2/vfs/vfserror"
"sync"
)
// Ensure CacheFS implements VFS.
@@ -16,6 +17,8 @@ type CacheFS struct {
slow vfs.VFS
cacheHandler CacheHandler
keyLocks sync.Map // map[string]*sync.RWMutex for per-key locks
}
type CacheHandler func(*vfs.FileInfo, cachestate.CacheState) bool
@@ -24,6 +27,7 @@ type CacheHandler func(*vfs.FileInfo, cachestate.CacheState) bool
func New(cacheHandler CacheHandler) *CacheFS {
return &CacheFS{
cacheHandler: cacheHandler,
keyLocks: sync.Map{},
}
}
@@ -39,6 +43,12 @@ func (c *CacheFS) SetFast(vfs vfs.VFS) {
c.fast = vfs
}
// getKeyLock returns a RWMutex for the given key, creating it if necessary.
func (c *CacheFS) getKeyLock(key string) *sync.RWMutex {
mu, _ := c.keyLocks.LoadOrStore(key, &sync.RWMutex{})
return mu.(*sync.RWMutex)
}
// cacheState returns the state of the file at key.
func (c *CacheFS) cacheState(key string) cachestate.CacheState {
if c.fast != nil {
@@ -65,6 +75,10 @@ func (c *CacheFS) Size() int64 {
// Set sets the file at key to src. If the file is already in the cache, it is replaced.
func (c *CacheFS) Set(key string, src []byte) error {
mu := c.getKeyLock(key)
mu.Lock()
defer mu.Unlock()
state := c.cacheState(key)
switch state {
@@ -82,6 +96,10 @@ func (c *CacheFS) Set(key string, src []byte) error {
// Delete deletes the file at key from the cache.
func (c *CacheFS) Delete(key string) error {
mu := c.getKeyLock(key)
mu.Lock()
defer mu.Unlock()
if c.fast != nil {
c.fast.Delete(key)
}
@@ -96,6 +114,10 @@ func (c *CacheFS) Get(key string) ([]byte, error) {
// GetS returns the file at key. If the file is not in the cache, it is fetched from the storage. It also returns the cache state.
func (c *CacheFS) GetS(key string) ([]byte, cachestate.CacheState, error) {
mu := c.getKeyLock(key)
mu.RLock()
defer mu.RUnlock()
state := c.cacheState(key)
switch state {
@@ -130,6 +152,10 @@ func (c *CacheFS) GetS(key string) ([]byte, cachestate.CacheState, error) {
// Stat returns information about the file at key.
// Warning: This will return information about the file in the fastest storage its in.
func (c *CacheFS) Stat(key string) (*vfs.FileInfo, error) {
mu := c.getKeyLock(key)
mu.RLock()
defer mu.RUnlock()
state := c.cacheState(key)
switch state {