fix: gc was being stupid allowing another thread to take the space it made before it could not anymore
All checks were successful
PR Check / check-and-test (pull_request) Successful in 12s

This commit is contained in:
2025-07-13 07:50:22 -05:00
parent 7f744d04b0
commit 3427b8f5bc
6 changed files with 68 additions and 79 deletions

View File

@@ -68,7 +68,7 @@ type SteamCache struct {
wg sync.WaitGroup
}
func New(address string, memorySize string, memoryMultiplier int, diskSize string, diskMultiplier int, diskPath, upstream string) *SteamCache {
func New(address string, memorySize string, diskSize string, diskPath, upstream string) *SteamCache {
memorysize, err := units.FromHumanSize(memorySize)
if err != nil {
panic(err)
@@ -87,14 +87,14 @@ func New(address string, memorySize string, memoryMultiplier int, diskSize strin
var mgc *gc.GCFS
if memorysize > 0 {
m = memory.New(memorysize)
mgc = gc.New(m, memoryMultiplier, gc.LRUGC)
mgc = gc.New(m, gc.LRUGC)
}
var d *disk.DiskFS
var dgc *gc.GCFS
if disksize > 0 {
d = disk.New(diskPath, disksize)
dgc = gc.New(d, diskMultiplier, gc.LRUGC)
dgc = gc.New(d, gc.LRUGC)
}
// configure the cache to match the specified mode (memory only, disk only, or memory and disk) based on the provided sizes
@@ -220,16 +220,16 @@ func (sc *SteamCache) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.String(), "/depot/") {
// trim the query parameters from the URL path
// this is necessary because the cache key should not include query parameters
r.URL.Path = strings.Split(r.URL.Path, "?")[0]
path := strings.Split(r.URL.String(), "?")[0]
tstart := time.Now()
defer func() { responseTime.Observe(time.Since(tstart).Seconds()) }()
cacheKey := strings.ReplaceAll(r.URL.String()[1:], "\\", "/") // replace all backslashes with forward slashes shouldn't be necessary but just in case
cacheKey := strings.ReplaceAll(path[1:], "\\", "/") // replace all backslashes with forward slashes shouldn't be necessary but just in case
if cacheKey == "" {
requestsTotal.WithLabelValues(r.Method, "400").Inc()
logger.Logger.Warn().Str("url", r.URL.String()).Msg("Invalid URL")
logger.Logger.Warn().Str("url", path).Msg("Invalid URL")
http.Error(w, "Invalid URL", http.StatusBadRequest)
return
}
@@ -258,7 +258,7 @@ func (sc *SteamCache) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var req *http.Request
if sc.upstream != "" { // if an upstream server is configured, proxy the request to the upstream server
ur, err := url.JoinPath(sc.upstream, r.URL.String())
ur, err := url.JoinPath(sc.upstream, path)
if err != nil {
requestsTotal.WithLabelValues(r.Method, "500").Inc()
logger.Logger.Error().Err(err).Str("upstream", sc.upstream).Msg("Failed to join URL path")
@@ -282,7 +282,7 @@ func (sc *SteamCache) ServeHTTP(w http.ResponseWriter, r *http.Request) {
host = "http://" + host
}
ur, err := url.JoinPath(host, r.URL.String())
ur, err := url.JoinPath(host, path)
if err != nil {
requestsTotal.WithLabelValues(r.Method, "500").Inc()
logger.Logger.Error().Err(err).Str("host", host).Msg("Failed to join URL path")
@@ -328,16 +328,17 @@ func (sc *SteamCache) ServeHTTP(w http.ResponseWriter, r *http.Request) {
size := resp.ContentLength
writer, err := sc.vfs.Create(cacheKey, size)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
// this is sortof not needed as we should always be able to get a writer from the cache as long as the gc is able to reclaim enough space aka the file is not bigger than the disk can handle
ww := w.(io.Writer) // default writer to write to the response writer
writer, _ := sc.vfs.Create(cacheKey, size) // create a writer to write to the cache
if writer != nil { // if the writer is not nil, it means the cache is writable
defer writer.Close() // close the writer when done
ww = io.MultiWriter(w, writer) // write to both the response writer and the cache writer
}
defer writer.Close()
w.Header().Add("X-LanCache-Status", "MISS")
io.Copy(io.MultiWriter(w, writer), resp.Body)
io.Copy(ww, resp.Body)
logger.Logger.Info().
Str("key", cacheKey).

View File

@@ -13,7 +13,7 @@ func TestCaching(t *testing.T) {
os.WriteFile(filepath.Join(td, "key2"), []byte("value2"), 0644)
sc := New("localhost:8080", "1G", 10, "1G", 100, td, "")
sc := New("localhost:8080", "1G", "1G", td, "")
w, err := sc.vfs.Create("key", 5)
if err != nil {
@@ -84,7 +84,7 @@ func TestCaching(t *testing.T) {
}
func TestCacheMissAndHit(t *testing.T) {
sc := New("localhost:8080", "0", 0, "1G", 100, t.TempDir(), "")
sc := New("localhost:8080", "0", "1G", t.TempDir(), "")
key := "testkey"
value := []byte("testvalue")