Add Galaxy platform scope filter so multi-node deployments can restrict the OPC UA address space to only objects hosted by the local platform, reducing memory footprint and MXAccess subscription count from the full Galaxy (49 objects / 4206 attributes) down to the local subtree (3 objects / 386 attributes on the dev Galaxy).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
101
service_info.md
101
service_info.md
@@ -826,6 +826,107 @@ The earlier service_info.md entry referenced `tools/opcuacli-dotnet/bin/Debug/ne
|
||||
|
||||
The code changes in this deploy are defensive and do not alter the runtime-status feature's control flow except in one place (subscribe rollback, which only triggers when `SubscribeAsync` throws). The 471/471 baseline on the probe manager tests plus the three new rollback regression tests give high confidence that the runtime-status behavior is preserved. If a human operator runs the IDE OffScan/OnScan cycle and observes an anomaly, the fix is most likely isolated to `GalaxyRuntimeProbeManager.SyncAsync` — see Finding 1 above — and can be reverted by restoring `C:\publish\lmxopcua\backups\20260414-003948-instance{1,2}\ZB.MOM.WW.LmxOpcUa.Host.exe`.
|
||||
|
||||
## Galaxy Platform Scope Filter
|
||||
|
||||
Updated: `2026-04-16 00:21-00:27 America/New_York`
|
||||
|
||||
Both instances updated with a new `GalaxyRepository.Scope` configuration flag that controls whether the OPC UA server loads the entire Galaxy or only objects hosted by the local platform. Reduces address space size, MXAccess subscription count, and memory footprint on multi-node Galaxy deployments.
|
||||
|
||||
Backups:
|
||||
- `C:\publish\lmxopcua\backups\20260416-002120-instance1`
|
||||
- `C:\publish\lmxopcua\backups\20260416-002120-instance2`
|
||||
|
||||
Configuration preserved:
|
||||
- Both `appsettings.json` updated with new fields only (`Scope`, `PlatformName`). All existing settings preserved.
|
||||
|
||||
Deployed binary (both instances):
|
||||
- `ZB.MOM.WW.LmxOpcUa.Host.exe`
|
||||
- Last write time: `2026-04-16 00:23 -04:00`
|
||||
- Size: `7,993,344`
|
||||
|
||||
Windows services:
|
||||
- `LmxOpcUa` — Running, PID `15204`
|
||||
- `LmxOpcUa2` — Running, PID `9544`
|
||||
|
||||
### Code changes
|
||||
|
||||
- `Configuration/GalaxyScope.cs` (new) — enum: `Galaxy` (default, all deployed objects), `LocalPlatform` (only objects hosted by the local platform's subtree).
|
||||
- `Domain/PlatformInfo.cs` (new) — DTO mapping `platform.platform_gobject_id` to `platform.node_name`.
|
||||
- `Configuration/GalaxyRepositoryConfiguration.cs` — added `Scope: GalaxyScope` (default `Galaxy`) and `PlatformName: string?` (optional override for `Environment.MachineName`).
|
||||
- `GalaxyRepository/PlatformScopeFilter.cs` (new) — stateless C# filter applied after the existing SQL queries (preserves `GR-006: const string, no dynamic SQL` convention). Algorithm: (1) resolve the local platform's `gobject_id` via a new `PlatformLookupSql` query against the `platform` table, (2) collect all AppEngine hosts under that platform, (3) include all objects hosted by any host in the set, (4) walk `ParentGobjectId` chains upward to retain ancestor areas for a connected browse tree.
|
||||
- `GalaxyRepository/GalaxyRepositoryService.cs` — added `PlatformLookupSql` const query, `GetPlatformsAsync()` method, post-query filtering in `GetHierarchyAsync`/`GetAttributesAsync` with cached `_scopeFilteredGobjectIds` for cross-method consistency.
|
||||
- `Configuration/ConfigurationValidator.cs` — logs `Scope` and effective `PlatformName` at startup.
|
||||
|
||||
### Configuration
|
||||
|
||||
New fields in `GalaxyRepository` section of `appsettings.json`:
|
||||
|
||||
```json
|
||||
"GalaxyRepository": {
|
||||
"Scope": "Galaxy",
|
||||
"PlatformName": null
|
||||
}
|
||||
```
|
||||
|
||||
- `Scope`: `"Galaxy"` (default) loads all deployed objects. `"LocalPlatform"` filters to the local platform only.
|
||||
- `PlatformName`: When null, uses `Environment.MachineName`. Set explicitly to target a specific platform by hostname.
|
||||
|
||||
Both instances deployed with `"Scope": "Galaxy"` (full Galaxy, backward-compatible default).
|
||||
|
||||
### Tests
|
||||
|
||||
8 new unit tests in `PlatformScopeFilterTests.cs`:
|
||||
- Two-platform Galaxy filtering (platform A, platform B)
|
||||
- Case-insensitive node name matching
|
||||
- No matching platform → empty result
|
||||
- Ancestor area inclusion for connected tree
|
||||
- Area exclusion when no local descendants
|
||||
- Attribute filtering by gobject_id set
|
||||
- Original order preservation
|
||||
|
||||
Full suite: **494/494** tests passing (8 new, 0 regressions).
|
||||
|
||||
### Live verification
|
||||
|
||||
**LocalPlatform scope test** (instance1, temporarily set to `"Scope": "LocalPlatform"`):
|
||||
```
|
||||
Startup log:
|
||||
GalaxyRepository.Scope="LocalPlatform", PlatformName=DESKTOP-6JL3KKO
|
||||
GalaxyRepository.PlatformName not set — using Environment.MachineName 'DESKTOP-6JL3KKO'
|
||||
GetHierarchyAsync returned 49 objects
|
||||
GetPlatformsAsync returned 1 platform(s)
|
||||
Scope filter targeting platform 'DESKTOP-6JL3KKO' (gobject_id=1042)
|
||||
Scope filter retained 3 of 49 objects for platform 'DESKTOP-6JL3KKO'
|
||||
GetAttributesAsync returned 4206 attributes (extended=true)
|
||||
Scope filter retained 386 of 4206 attributes
|
||||
Address space built: 2 objects, 386 variables, 386 tag references, 0 alarm tags, 2 runtime hosts
|
||||
|
||||
CLI browse ZB:
|
||||
DEV → DevAppEngine, DevPlatform (only local platform subtree)
|
||||
TestArea, TestArea2 → absent (filtered out)
|
||||
|
||||
CLI read DEV.ScanState:
|
||||
Value: True, Status: 0x00000000 (Good)
|
||||
```
|
||||
|
||||
**Galaxy scope comparison** (instance2, `"Scope": "Galaxy"`):
|
||||
```
|
||||
CLI browse ZB/DEV:
|
||||
DevAppEngine, DevPlatform, TestArea, TestArea2 (full Galaxy)
|
||||
```
|
||||
|
||||
**Galaxy scope restored** (instance1, set back to `"Scope": "Galaxy"`):
|
||||
```
|
||||
CLI browse ZB/DEV:
|
||||
DevAppEngine, DevPlatform, TestArea, TestArea2 (full Galaxy restored)
|
||||
```
|
||||
|
||||
**Redundancy baseline preserved** (both instances):
|
||||
```
|
||||
instance1 → Warm, ServiceLevel=200, urn:localhost:LmxOpcUa:instance1
|
||||
instance2 → Warm, ServiceLevel=150, urn:localhost:LmxOpcUa:instance2
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
The service deployment and restart succeeded. The live CLI checks confirm the endpoint is reachable and that the array node identifier has changed to the bracketless form. The array value on the live service still prints as blank even though the status is good, so if this environment should have populated `MoveInPartNumbers`, the runtime data path still needs follow-up investigation.
|
||||
|
||||
Reference in New Issue
Block a user