Commit Graph

4 Commits

Author SHA1 Message Date
Joseph Doherty 733dfe94da 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
2026-11-11 14:20:19 -05:00
Joseph Doherty b77bb2ded1 fix(opcua): #855 perf review 2 — where clause in the group bucket key; pin dedupe, modify and keys
- Filter-group buckets include the where clause's (value-based) hash, so
  per-source filters sharing a select list are not all scanned under Lock.
- Locale keys are cached per session array.
- Tests: a notifier reached twice in one walk (Line above two wired
  equipment) gets each event once on both paths (fails without the
  per-report set); queued events re-projected by a modify are identical on
  both paths; locale keys unambiguous and where clauses hash by value.

Claude-Session: https://claude.ai/code/session_01GT67AD99zQQqpLCVm3p7xk
2026-11-11 14:10:02 -05:00
Joseph Doherty ca0e73fbca fix(opcua): #855 perf review 1 — groups evaluate their own filter clone; lazy fields; tighter equivalence tests
- A filter group owns a deep clone of its first filter, validated once and
  evaluated under the group's lock: no item-owned filter is mutated or raced
  (Validate mutates a select clause).
- The projection is computed in the SDK's order: where clause first, fields
  only for an item that will queue.
- Unambiguous locale key; counter for filters given a private group past the
  registry cap; DeliveryCache getter returns its own allocation.
- UseProjectedEventDelivery=false also asks the role and grant checks per
  item, so the equivalence test compares against the pre-optimisation path.
- Equivalence test: same select list under three where clauses, a filter
  modified mid-run, a session with other locales, an ungranted anonymous
  Server-object item, per-rig counter; plus a small overflowing queue with
  DiscardOldest true and false.

Claude-Session: https://claude.ai/code/session_01GT67AD99zQQqpLCVm3p7xk
2026-11-11 13:59:22 -05:00
Joseph Doherty 98d962b24b perf(opcua): #855 — shared per-report projection for condition events under Lock
Condition events delivered to many event items (folder and Server-object)
no longer pay the SDK's per-item QueueEvent(IFilterTarget) work under the
node-manager Lock: the role-permission verdict is shared per (session,
identity), the #826 grant check per identity per hop, and the where clause +
select-clause projection per (value-equal EventFilter, locales); each item
gets its own EventFieldList over the shared read-only fields. The SDK's
QueueEvent body is reproduced under the item's own lock (three private SDK
members, guard-tested); anything outside that shape falls back to the SDK.
The per-report duplicate check replaces the SDK's O(queue) scan.

ProjectedEventDeliveryWireTests compares both paths over the wire.

Claude-Session: https://claude.ai/code/session_01GT67AD99zQQqpLCVm3p7xk
2026-11-11 13:42:29 -05:00