fix(acl): a stale-generation straggler can no longer roll the cache stamp backward and thrash ClearAll
This commit is contained in:
@@ -263,6 +263,48 @@ public sealed class SessionAclDecisionCacheTests
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A request presenting an OLDER generation — one whose authority snapshot was captured before a
|
||||
/// deploy and which then lost the scheduling race — must not roll the cache stamp backward, and must
|
||||
/// not purge the new generation's entries on its way past.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The generation itself is monotonic by construction; what is not monotonic is the order
|
||||
/// requests <i>arrive</i> holding it. Treating a straggler as a deploy inverts the stamp and
|
||||
/// wipes shards that were populated correctly, so the post-deploy window — the coldest the cache
|
||||
/// ever is, and the busiest repopulating — is precisely when it would thrash.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Nothing here uses <c>AdvanceGenerationForTest</c>: this is the ordinary lookup path,
|
||||
/// observed. The straggler must miss (its snapshot is superseded, so recomputing is right) AND
|
||||
/// leave everything else standing — a test asserting only the miss passes against the defect,
|
||||
/// because the straggler misses either way.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Fact]
|
||||
public void A_straggler_from_an_older_generation_neither_clears_nor_rolls_the_stamp_back()
|
||||
{
|
||||
var cache = new SessionAclDecisionCache();
|
||||
|
||||
Ask(cache, generation: 2, compute: () => true).ShouldBeTrue();
|
||||
cache.Generation.ShouldBe(2);
|
||||
cache.Count.ShouldBe(1);
|
||||
|
||||
// The straggler: same question, superseded snapshot.
|
||||
cache.TryGet(generation: 1, Session, OpcUaOperation.Read, AddressSpaceRealm.Raw, Node, out _)
|
||||
.ShouldBeFalse("a superseded snapshot must recompute rather than read the newer generation");
|
||||
|
||||
// Asserted BEFORE the generation-2 lookup below, which would itself restore a rolled-back stamp and
|
||||
// hide the defect.
|
||||
cache.Generation.ShouldBe(2, "the straggler must not have rolled the stamp backward");
|
||||
cache.Count.ShouldBe(1, "and must not have purged the current generation's entries");
|
||||
|
||||
cache.TryGet(generation: 2, Session, OpcUaOperation.Read, AddressSpaceRealm.Raw, Node, out var decision)
|
||||
.ShouldBeTrue("the current generation's decision survived the straggler");
|
||||
decision.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The store half of the same window: a <c>Set</c> that meets the previous generation's shard must
|
||||
/// displace it, not fill it.
|
||||
|
||||
Reference in New Issue
Block a user