Remove plans/ directory (P0/P1/P2 work complete)
This commit is contained in:
Vendored
+1
-1
@@ -202,7 +202,7 @@ func (tc *TieredCache) promoteToFast(key string, reader io.ReadCloser) {
|
||||
}
|
||||
}
|
||||
|
||||
// P1-01: guard promotion ReadAll using already-fetched size (in addition to space check above)
|
||||
// Guard promotion ReadAll using already-fetched size (in addition to space check above)
|
||||
if size > 0 && size > (1<<30) { // conservative 1GB hard limit on promotion reads (aligns with typical max_object_size)
|
||||
return
|
||||
}
|
||||
|
||||
Vendored
+114
@@ -0,0 +1,114 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"io"
|
||||
"s1d3sw1ped/steamcache2/vfs/memory"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestTieredCache_PromotionFallback(t *testing.T) {
|
||||
t.Parallel()
|
||||
fast := memory.New(1 * 1024 * 1024)
|
||||
slow := memory.New(10 * 1024 * 1024) // use mem for "disk" in test
|
||||
|
||||
tc := New()
|
||||
tc.SetFast(fast)
|
||||
tc.SetSlow(slow)
|
||||
|
||||
// write to slow (disk)
|
||||
w, err := tc.Create("p1", 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w.Write(make([]byte, 1024))
|
||||
w.Close()
|
||||
|
||||
// open should hit slow, trigger promote goroutine
|
||||
r, err := tc.Open("p1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
io.Copy(io.Discard, r)
|
||||
r.Close()
|
||||
|
||||
// Replace fixed sleep with bounded poll for promotion completion (robust vs load/CI variance; addresses issue7)
|
||||
deadline := time.Now().Add(500 * time.Millisecond)
|
||||
promoted := false
|
||||
for time.Now().Before(deadline) {
|
||||
if _, err := fast.Stat("p1"); err == nil {
|
||||
promoted = true
|
||||
break
|
||||
}
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
}
|
||||
if !promoted {
|
||||
// Still allow slow tier stat as fallback (promotion is best-effort)
|
||||
if _, err := tc.Stat("p1"); err != nil {
|
||||
t.Errorf("stat after promote attempt: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// size total
|
||||
if tc.Size() < 1024 {
|
||||
t.Error("total size under")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTieredCache_DeleteAllTiers(t *testing.T) {
|
||||
t.Parallel()
|
||||
fast := memory.New(1024)
|
||||
slow := memory.New(1024)
|
||||
tc := New()
|
||||
tc.SetFast(fast)
|
||||
tc.SetSlow(slow)
|
||||
|
||||
w, _ := tc.Create("delme", 100)
|
||||
w.Write([]byte{1})
|
||||
w.Close()
|
||||
|
||||
tc.Delete("delme")
|
||||
if _, err := tc.Open("delme"); err == nil {
|
||||
t.Error("deleted key still openable from tiers")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTieredCache_Concurrent(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
fast := memory.New(5 * 1024 * 1024)
|
||||
slow := memory.New(20 * 1024 * 1024)
|
||||
tc := New()
|
||||
tc.SetFast(fast)
|
||||
tc.SetSlow(slow)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
var hits int64
|
||||
for i := 0; i < 6; i++ {
|
||||
wg.Add(1)
|
||||
go func(id int) {
|
||||
defer wg.Done()
|
||||
for j := 0; j < 20; j++ {
|
||||
k := "ct" + string(rune(id)) + string(rune(j%5))
|
||||
if w, e := tc.Create(k, 256); e == nil {
|
||||
w.Write(make([]byte, 256))
|
||||
w.Close()
|
||||
}
|
||||
if r, e := tc.Open(k); e == nil {
|
||||
io.Copy(io.Discard, r)
|
||||
r.Close()
|
||||
atomic.AddInt64(&hits, 1)
|
||||
}
|
||||
tc.Delete(k)
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
if hits < 10 {
|
||||
t.Errorf("low tier hits %d", hits)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user