fix(34): WR-06 bound the Plugins screen's search cache
pluginCatalog.lists was keyed by every distinct query and category and never dropped an expired entry, so searching distinct strings grew the process without limit (each entry can hold a 4 MiB answer). Storing a search into a full cache now drops the expired searches and then the ones that expire first, keeping at most 256.
This commit is contained in:
@@ -264,6 +264,37 @@ func TestPluginsEndpoints(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("search cache is bounded", func(t *testing.T) {
|
||||
reg := &memPluginRegistry{}
|
||||
clk := &testClock{now: clock.Now()}
|
||||
c := &pluginCatalog{registry: reg, timeout: time.Second, now: clk.Now, lists: map[string]cachedList{}, versions: map[string]cachedVersions{}}
|
||||
for i := 0; i < marketplaceCacheSize+50; i++ {
|
||||
clk.advance(time.Millisecond)
|
||||
if _, err := c.list(t.Context(), fmt.Sprintf("q%d", i), ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if n := len(c.lists); n != marketplaceCacheSize {
|
||||
t.Fatalf("cached searches = %d, want at most %d", n, marketplaceCacheSize)
|
||||
}
|
||||
// The oldest went first; the newest is still a hit.
|
||||
if _, ok := c.lists["q0\x00"]; ok {
|
||||
t.Error("the oldest search survived")
|
||||
}
|
||||
before := reg.count(fmt.Sprintf("list q%d|", marketplaceCacheSize+49))
|
||||
if _, err := c.list(t.Context(), fmt.Sprintf("q%d", marketplaceCacheSize+49), ""); err != nil || reg.count(fmt.Sprintf("list q%d|", marketplaceCacheSize+49)) != before {
|
||||
t.Errorf("the newest search was not cached: %v", err)
|
||||
}
|
||||
// Expired searches are dropped when a new one needs the room.
|
||||
clk.advance(marketplaceTTL + time.Second)
|
||||
if _, err := c.list(t.Context(), "fresh", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n := len(c.lists); n != 1 {
|
||||
t.Errorf("cached searches after expiry = %d, want 1", n)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("cache hit and expiry", func(t *testing.T) {
|
||||
reg := &memPluginRegistry{versions: map[string][]kiosk.RegistryVersion{"acme.blog": {rel("v0.2.0", "v0.6.0")}, "acme.translate": {rel("v0.1.1", "v0.6.0")}}}
|
||||
clk := &testClock{now: clock.Now()}
|
||||
|
||||
Reference in New Issue
Block a user