fix(opcua): #855 perf review 3 — weak filter-group registry; where clause validated; sharing pinned
- The filter-group registry holds groups weakly (the filter->group table is the only strong reference), sweeps dead entries amortised and counts only live shapes against the 4096 cap; filters past the cap are counted on the new meter otopcua.opcua.condition_events.filter_groups_unshared. - A group validates its where clause too (restored, never-validated filters evaluate like validated ones). - Test: value-equal filters cost one projection per locale set per report. Claude-Session: https://claude.ai/code/session_01GT67AD99zQQqpLCVm3p7xk
This commit is contained in:
+33
@@ -295,6 +295,39 @@ public sealed class ProjectedEventDeliveryWireTests
|
||||
Narrow(800).WhereClause.GetHashCode().ShouldNotBe(Narrow(900).WhereClause.GetHashCode());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sharing really happens (not only equivalence): three items with value-equal filters on one session and one on a
|
||||
/// session with other locales cost TWO projections per report (one per locale set), not four.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Value_equal_filters_share_one_projection_per_locale_set()
|
||||
{
|
||||
var ct = TestContext.Current.CancellationToken;
|
||||
await using var rig = await ServerEventRig.StartAsync("Projected855Share", encrypted: false, ct);
|
||||
rig.KeyRoles = [];
|
||||
rig.MaterialiseNative();
|
||||
rig.Enforce(false, [ServerEventRig.Key()], KeyEquipmentGrant(EqA));
|
||||
|
||||
using var session = await rig.ConnectAsync(anonymous: false, ct);
|
||||
var events = new RecordedEvents();
|
||||
var subscription = await RecordedEvents.SubscribeAsync(session, events, ct);
|
||||
var eqA = ServerEventRig.UnsNodeId(session, EqA);
|
||||
var items = Enumerable.Range(0, 3).Select(_ => RecordedEvents.AddEventItem(subscription, eqA)).ToList();
|
||||
await subscription.ApplyChangesAsync(ct);
|
||||
|
||||
using var german = await rig.ConnectAsync(anonymous: false, ct, preferredLocales: ["de-DE"]);
|
||||
var germanEvents = new RecordedEvents();
|
||||
var germanSubscription = await RecordedEvents.SubscribeAsync(german, germanEvents, ct);
|
||||
var g1 = RecordedEvents.AddEventItem(germanSubscription, ServerEventRig.UnsNodeId(german, EqA));
|
||||
await germanSubscription.ApplyChangesAsync(ct);
|
||||
|
||||
var before = rig.Nm.ProjectionsCreated;
|
||||
const int Reports = 5;
|
||||
for (var i = 0; i < Reports; i++) rig.Project(native: true, State($"x{i}"));
|
||||
(rig.Nm.ProjectionsCreated - before).ShouldBe(2 * Reports, "one projection per (filter group, locale set) per report");
|
||||
await RecordedEvents.WaitUntilAsync(() => items.All(m => events.Has(m, $"x{Reports - 1}")) && germanEvents.Has(g1, $"x{Reports - 1}"));
|
||||
}
|
||||
|
||||
private static AlarmConditionSnapshot State(string message) =>
|
||||
new(true, false, false, true, AlarmShelvingKind.Unshelved, 700, message);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user