fix(mesh): also scope the reconciler's observed membership to the own cluster
Task 3 review: scoping only the rows/enabled DB queries by ClusterId left the observed set (from Cluster.State.Members) filtered by the driver role alone. In the mixed-mesh window — DB scoping live via a cluster role, but the physical Akka mesh not yet split so central still sees foreign members via gossip — a foreign-cluster driver member stays in observed while its row is filtered out, hitting the RunningNodeHasNoRow branch, which logs at ERROR. That traded the Warning-level false positive for a worse Error-level one. Filter observed by the node's own cluster ROLE too. Extracted the projection into a static FilterOwnClusterDriverMembers(members, ownClusterRole) so the membership filter is unit-testable without seeding a live cluster (the actor harness joins as admin only, so observed is always empty). Sourced at registration from IClusterRoleInfo.ClusterRole alongside ClusterId. Null role (legacy, no cluster role) keeps every driver member — reconcile-all, unchanged. Also clarified the ownClusterId doc wording (non-null-and-non-empty). Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
@@ -153,12 +153,16 @@ public static class ServiceCollectionExtensions
|
||||
(system, registry, resolver) =>
|
||||
{
|
||||
var dbFactory = resolver.GetService<IDbContextFactory<OtOpcUaConfigDbContext>>();
|
||||
// Per-cluster mesh Phase 6: scope the reconcile to the admin node's OWN cluster's rows.
|
||||
// After the mesh split central sees only its own pair via gossip, so a fleet-wide sweep
|
||||
// would false-report every other cluster's rows as EnabledRowNotInCluster forever. A
|
||||
// legacy node with no cluster role has null ClusterId ⇒ full-fleet reconcile, unchanged.
|
||||
// Per-cluster mesh Phase 6: scope BOTH halves of the reconcile to the admin node's OWN
|
||||
// cluster — rows by ClusterId, observed membership by cluster role. After the mesh split
|
||||
// central sees only its own pair via gossip, so an unscoped sweep would false-report
|
||||
// every other cluster's rows (EnabledRowNotInCluster). Scoping only the rows would swap
|
||||
// that for a WORSE Error-level RunningNodeHasNoRow in the mixed-mesh window (rows already
|
||||
// filtered, but foreign members still visible via gossip). A legacy node with no cluster
|
||||
// role has null ClusterId/ClusterRole ⇒ full-fleet reconcile, unchanged.
|
||||
var roleInfo = resolver.GetService<IClusterRoleInfo>();
|
||||
return ClusterNodeAddressReconcilerActor.Props(dbFactory, roleInfo.ClusterId);
|
||||
return ClusterNodeAddressReconcilerActor.Props(
|
||||
dbFactory, roleInfo.ClusterId, roleInfo.ClusterRole);
|
||||
},
|
||||
singletonOptions,
|
||||
createProxyToo: false);
|
||||
|
||||
Reference in New Issue
Block a user