fix(docker-dev): give each pair node its own ApplicationUri and advertise its partner (#801)
Every docker-dev node served the compiled default ApplicationUri "urn:OtOpcUa" with a one-entry Server.ServerArray, so the two halves of a redundant pair were indistinguishable by URI and peer discovery returned nothing. Each node now sets OpcUa__ApplicationUri = urn:OtOpcUa:<service> (its seeded ClusterNode.ApplicationUri) and OpcUa__PeerApplicationUris__0 = its pair partner. Verified on the central pair: ServerArray reads [self, partner] on both nodes. RedundancySupport still reads None by design (#717). The pair's 255/255 ServiceLevel was not a rig config problem: it is the SDK 2.0.1 session-headroom overwrite filed separately. Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
This commit is contained in:
@@ -251,5 +251,6 @@ The full six-node host stack therefore needs roughly **6 GiB** of Docker Desktop
|
||||
- Main: `opc.tcp://localhost:4840` (central-1), `opc.tcp://localhost:4841` (central-2)
|
||||
- Site A: `opc.tcp://localhost:4842` (site-a-1), `opc.tcp://localhost:4843` (site-a-2)
|
||||
- Site B: `opc.tcp://localhost:4844` (site-b-1), `opc.tcp://localhost:4845` (site-b-2)
|
||||
- Each node serves its own `ApplicationUri` (`urn:OtOpcUa:<service>`, the same as its seeded `ClusterNode.ApplicationUri`) and lists its pair partner in `Server.ServerArray` (`OpcUa__ApplicationUri` / `OpcUa__PeerApplicationUris__0`). Before lmxopcua#801 every node served the compiled default `urn:OtOpcUa` with a one-entry `ServerArray`. `Server.ServerRedundancy.RedundancySupport` still reads `None` on every node, by design until #717. The healthy pair's ServiceLevel is 250 (Primary, the oldest Up `driver` member) and 240 (Secondary). Read it with `otopcua-cli redundancy -u opc.tcp://localhost:4840`.
|
||||
- Galaxy + Wonderware drivers can't run in Linux containers (they need the Windows-only mxaccessgw + Historian SDK). On non-Windows, `DriverInstanceActor.ShouldStub(driverType, roles)` returns `true` for those types and the actor goes straight to a `Stubbed` state that returns deterministic success.
|
||||
- SQL persistence: ConfigDb state survives container restarts (named Docker volume). Drop the volume with `down -v` for a clean slate.
|
||||
|
||||
@@ -335,6 +335,12 @@ services:
|
||||
Cluster__Hostname: "0.0.0.0"
|
||||
Cluster__Port: "4053"
|
||||
Cluster__PublicHostname: "central-1"
|
||||
# lmxopcua#801: each redundancy peer owns a DISTINCT ApplicationUri (docs/Redundancy.md) equal to its
|
||||
# seeded ClusterNode.ApplicationUri, and advertises its pair partner in Server.ServerArray via
|
||||
# PeerApplicationUris. Without these every node served the compiled default "urn:OtOpcUa" and a
|
||||
# one-entry ServerArray, so a client could not tell the two halves of a pair apart.
|
||||
OpcUa__ApplicationUri: "urn:OtOpcUa:central-1"
|
||||
OpcUa__PeerApplicationUris__0: "urn:OtOpcUa:central-2"
|
||||
# Per-cluster mesh Phase 3 (config fetch-and-cache). Central SERVES the deployed-configuration
|
||||
# artifact to FetchAndCache site nodes over a dedicated h2c gRPC listener (:4055), gated by the
|
||||
# shared node key. Central itself is ALWAYS Direct — it IS the SQL source and must never fetch.
|
||||
@@ -502,6 +508,9 @@ services:
|
||||
Cluster__Hostname: "0.0.0.0"
|
||||
Cluster__Port: "4053"
|
||||
Cluster__PublicHostname: "central-2"
|
||||
# lmxopcua#801: distinct ApplicationUri + pair partner in ServerArray — see central-1.
|
||||
OpcUa__ApplicationUri: "urn:OtOpcUa:central-2"
|
||||
OpcUa__PeerApplicationUris__0: "urn:OtOpcUa:central-1"
|
||||
# Per-cluster mesh Phase 3 — serves the artifact to FetchAndCache site nodes (see central-1).
|
||||
# Always Direct; ConfigServe:ApiKey must match the site nodes' ConfigSource:ApiKey.
|
||||
ConfigServe__GrpcListenPort: "4055"
|
||||
@@ -626,6 +635,9 @@ services:
|
||||
Cluster__Hostname: "0.0.0.0"
|
||||
Cluster__Port: "4053"
|
||||
Cluster__PublicHostname: "site-a-1"
|
||||
# lmxopcua#801: distinct ApplicationUri + pair partner in ServerArray — see central-1.
|
||||
OpcUa__ApplicationUri: "urn:OtOpcUa:site-a-1"
|
||||
OpcUa__PeerApplicationUris__0: "urn:OtOpcUa:site-a-2"
|
||||
# FetchAndCache is MANDATORY for driver-only nodes (validator-enforced): they fetch the deployed
|
||||
# artifact from central over gRPC (endpoints below) and read ONLY the LocalDb cache — no central
|
||||
# SQL config read (they have no connection string). Central stays Direct + keeps ConfigServe.
|
||||
@@ -746,6 +758,9 @@ services:
|
||||
Cluster__Hostname: "0.0.0.0"
|
||||
Cluster__Port: "4053"
|
||||
Cluster__PublicHostname: "site-a-2"
|
||||
# lmxopcua#801: distinct ApplicationUri + pair partner in ServerArray — see central-1.
|
||||
OpcUa__ApplicationUri: "urn:OtOpcUa:site-a-2"
|
||||
OpcUa__PeerApplicationUris__0: "urn:OtOpcUa:site-a-1"
|
||||
# Per-cluster mesh Phase 4: FetchAndCache mandatory for driver-only nodes (see site-a-1) — no
|
||||
# ConfigDb string; fetch the artifact from central over gRPC and read only the LocalDb cache.
|
||||
ConfigSource__Mode: "FetchAndCache"
|
||||
@@ -848,6 +863,9 @@ services:
|
||||
Cluster__Hostname: "0.0.0.0"
|
||||
Cluster__Port: "4053"
|
||||
Cluster__PublicHostname: "site-b-1"
|
||||
# lmxopcua#801: distinct ApplicationUri + pair partner in ServerArray — see central-1.
|
||||
OpcUa__ApplicationUri: "urn:OtOpcUa:site-b-1"
|
||||
OpcUa__PeerApplicationUris__0: "urn:OtOpcUa:site-b-2"
|
||||
# Per-cluster mesh Phase 4: FetchAndCache mandatory for driver-only nodes (see site-a-1) — no
|
||||
# ConfigDb string; fetch the artifact from central over gRPC and read only the LocalDb cache.
|
||||
ConfigSource__Mode: "FetchAndCache"
|
||||
@@ -921,6 +939,9 @@ services:
|
||||
Cluster__Hostname: "0.0.0.0"
|
||||
Cluster__Port: "4053"
|
||||
Cluster__PublicHostname: "site-b-2"
|
||||
# lmxopcua#801: distinct ApplicationUri + pair partner in ServerArray — see central-1.
|
||||
OpcUa__ApplicationUri: "urn:OtOpcUa:site-b-2"
|
||||
OpcUa__PeerApplicationUris__0: "urn:OtOpcUa:site-b-1"
|
||||
# Per-cluster mesh Phase 4: FetchAndCache mandatory for driver-only nodes (see site-a-1) — no
|
||||
# ConfigDb string; fetch the artifact from central over gRPC and read only the LocalDb cache.
|
||||
ConfigSource__Mode: "FetchAndCache"
|
||||
|
||||
Reference in New Issue
Block a user