fix(driver-galaxy): resolve Low code-review findings (Driver.Galaxy-005,010,012,013)
- Driver.Galaxy-005: rewrite the EventPump BoundedChannelOptions comment to honestly describe the Wait+TryWrite pattern. - Driver.Galaxy-010: ResolveApiKey now warns when a literal API key is used in production wiring; added an explicit dev: prefix for known cleartext-in-dev cases and rewrote the GalaxyGatewayOptions doc. - Driver.Galaxy-012: O(1) reverse-lookup for SubscriptionRegistry dispatch via per-entry FullRefByItemHandle map; immutable hash-set for the cross-binding reverse map; SubscribeAsync / ReadViaSubscribeOnce use BuildResultIndex for per-reference correlation. - Driver.Galaxy-013: ReinitializeAsync now validates the incoming JSON against the running options; ReplayOnSessionLost honoured by the Replay path; class summary rewritten to describe the shipped surface. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -183,6 +183,36 @@ public sealed class SubscriptionRegistryTests
|
||||
registry.ResolveSubscribers(0).ShouldBeEmpty();
|
||||
}
|
||||
|
||||
// ===== Driver.Galaxy-012 regression: ResolveSubscribers is O(1) per binding =====
|
||||
|
||||
[Fact]
|
||||
public void ResolveSubscribers_LargeBindingSet_DispatchesCorrectly()
|
||||
{
|
||||
// 5000-tag subscription. ResolveSubscribers must still return the right
|
||||
// full-reference for any item handle without a linear scan of the entire
|
||||
// binding list — the old FirstOrDefault(b => b.ItemHandle == h) was O(n)
|
||||
// per dispatch, so 50k tags × 1Hz fan-out was 50k linear scans per second.
|
||||
var registry = new SubscriptionRegistryAccess();
|
||||
const int tagCount = 5000;
|
||||
var bindings = new List<TagBindingAccess>(tagCount);
|
||||
for (var i = 0; i < tagCount; i++)
|
||||
{
|
||||
bindings.Add(new TagBindingAccess($"Tag.{i}", 1000 + i));
|
||||
}
|
||||
registry.Register(1, bindings);
|
||||
|
||||
// Pull the last entry — the worst case for a linear scan.
|
||||
var subs = registry.ResolveSubscribers(1000 + tagCount - 1);
|
||||
|
||||
subs.Count.ShouldBe(1);
|
||||
subs[0].FullReference.ShouldBe($"Tag.{tagCount - 1}");
|
||||
|
||||
// Mid-range entry too — proves the index isn't position-dependent.
|
||||
var mid = registry.ResolveSubscribers(1000 + tagCount / 2);
|
||||
mid.Count.ShouldBe(1);
|
||||
mid[0].FullReference.ShouldBe($"Tag.{tagCount / 2}");
|
||||
}
|
||||
|
||||
// Internal types are accessed via friend assembly (InternalsVisibleTo); these
|
||||
// wrapper aliases keep the test code readable.
|
||||
private sealed class SubscriptionRegistryAccess
|
||||
|
||||
Reference in New Issue
Block a user