fix(site-runtime): compile cache eviction counter+warning, configurable bound, never cache faulted compiles (review 2026-10-21 01/SR-M2)

This commit is contained in:
Joseph Doherty
2026-10-22 08:28:22 -04:00
parent b0a08bb63b
commit 96cab3f3d7
5 changed files with 144 additions and 8 deletions
@@ -209,4 +209,48 @@ public class SiteScriptCompileCacheTests
$"cache grew past its bound: {_cache.Count} vs max {SiteScriptCompileCache.MaxEntries} " +
$"(+{tasks} racing-insert slack) after {tasks * perTask} distinct inserts");
}
/// <summary>A faulted compile (unexpected exception) is returned but never cached: the next call recompiles (review 2026-10-21 01/SR-M2 follow-up).</summary>
[Fact]
public void GetOrAdd_FaultedResult_IsNotCached_NextCallRecompiles()
{
var calls = 0;
ScriptCompilationResult Factory() =>
++calls == 1 ? ScriptCompilationResult.Faulted(["Compilation exception: boom"]) : Ok();
var first = _cache.GetOrAdd("return 7;", typeof(ScriptGlobals), Factory);
Assert.False(first.IsSuccess);
Assert.Equal(0, _cache.Count);
var second = _cache.GetOrAdd("return 7;", typeof(ScriptGlobals), Factory);
Assert.True(second.IsSuccess);
Assert.Equal(2, calls);
Assert.Equal(1, _cache.Count);
}
/// <summary>A diagnostic failure IS a verdict on the code and stays cached.</summary>
[Fact]
public void GetOrAdd_DiagnosticFailure_IsStillCached()
{
var calls = 0;
ScriptCompilationResult Factory() { calls++; return ScriptCompilationResult.Failed(["CS1002"]); }
_cache.GetOrAdd("bad", typeof(ScriptGlobals), Factory);
_cache.GetOrAdd("bad", typeof(ScriptGlobals), Factory);
Assert.Equal(1, calls);
}
/// <summary>A configured capacity bounds the cache and eviction is counted (01/SR-M2).</summary>
[Fact]
public void Eviction_HonoursConfiguredCapacity_AndCountsEvictions()
{
var cache = new SiteScriptCompileCache(16, logger: null);
for (var i = 0; i < 40; i++)
cache.GetOrAdd("return " + i + ";", typeof(ScriptGlobals), Ok);
Assert.Equal(16, cache.Capacity);
Assert.True(cache.Count <= 16);
Assert.True(cache.Evictions > 0);
}
}