feat(render #53): EntityClassificationCache.InvalidateLandblock + tests
Sweep-by-landblock removal for the streaming demote/unload path. Tests #6, #7, #8 from spec section 7.1 lock in: (a) all matching entries removed, (b) non-matching entries preserved, (c) idempotent on missing LB. Phase 1 (cache foundation) complete. 11 cache tests passing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
aea4460eae
commit
a171e7007b
2 changed files with 71 additions and 0 deletions
|
|
@ -71,4 +71,30 @@ internal sealed class EntityClassificationCache
|
|||
{
|
||||
_entries.Remove(entityId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove every cache entry whose <see cref="EntityCacheEntry.LandblockHint"/>
|
||||
/// equals <paramref name="landblockId"/>. Used by the streaming pipeline
|
||||
/// when a landblock demotes from near to far or unloads. No-op if no
|
||||
/// entries match.
|
||||
/// </summary>
|
||||
public void InvalidateLandblock(uint landblockId)
|
||||
{
|
||||
if (_entries.Count == 0) return;
|
||||
|
||||
// Collect the ids to remove first to avoid mutating the dict during iteration.
|
||||
// Buffered locally because the typical case removes ~all entries in the LB
|
||||
// (which is still small relative to the total cache).
|
||||
List<uint>? toRemove = null;
|
||||
foreach (var (id, entry) in _entries)
|
||||
{
|
||||
if (entry.LandblockHint == landblockId)
|
||||
{
|
||||
toRemove ??= new List<uint>();
|
||||
toRemove.Add(id);
|
||||
}
|
||||
}
|
||||
if (toRemove is null) return;
|
||||
foreach (var id in toRemove) _entries.Remove(id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue