fix(siteruntime): capture Self before Task.Run in artifact deploy; seed MxGateway connections
- DeploymentManagerActor.HandleDeployArtifacts read the Self property inside its Task.Run lambda (line dispatching ApplyArtifactDataConnectionsToDcl). Self is backed by the ambient ActorCell, null on a thread-pool thread, so it threw 'no active ActorContext' — surfaced the first time a data connection is deployed via deploy-artifacts. Capture Self into a local first (as Sender already was). - seed-sites.sh: create a shared MxGateway data connection (10.100.0.48:5120) on each site and deploy artifacts so the DCL establishes them. - build.sh: nounset-safe empty-array expansion (bash 3.2).
This commit is contained in:
+3
-1
@@ -23,10 +23,12 @@ fi
|
|||||||
|
|
||||||
# Build from repo root (so COPY paths in Dockerfile resolve correctly)
|
# Build from repo root (so COPY paths in Dockerfile resolve correctly)
|
||||||
echo "Building scadabridge:latest image..."
|
echo "Building scadabridge:latest image..."
|
||||||
|
# Note: ${NUGET_ARGS[@]+...} guards against the "unbound variable" error that
|
||||||
|
# set -u raises on bash 3.2 (macOS default) when expanding an empty array.
|
||||||
docker build \
|
docker build \
|
||||||
-t scadabridge:latest \
|
-t scadabridge:latest \
|
||||||
-f "$SCRIPT_DIR/Dockerfile" \
|
-f "$SCRIPT_DIR/Dockerfile" \
|
||||||
"${NUGET_ARGS[@]}" \
|
${NUGET_ARGS[@]+"${NUGET_ARGS[@]}"} \
|
||||||
"$REPO_ROOT"
|
"$REPO_ROOT"
|
||||||
|
|
||||||
echo "Build complete: scadabridge:latest"
|
echo "Build complete: scadabridge:latest"
|
||||||
|
|||||||
@@ -63,6 +63,35 @@ $CLI $URL $AUTH notification create \
|
|||||||
--emails "engineer@company.com" \
|
--emails "engineer@company.com" \
|
||||||
|| echo " (Engineering Alerts may already exist)"
|
|| echo " (Engineering Alerts may already exist)"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Creating MxGateway data connections (shared gateway) on each site..."
|
||||||
|
# A shared MxGateway data connection pointing at the MxAccess Gateway. Data
|
||||||
|
# connections are site-scoped (the DCL runs on site clusters only — central
|
||||||
|
# nodes do not host data connections), so one is created per site. The same
|
||||||
|
# gateway endpoint + API key is reused across all sites.
|
||||||
|
#
|
||||||
|
# Config is the typed MxGatewayEndpointConfig JSON (camelCase keys), matching
|
||||||
|
# MxGatewayEndpointConfigSerializer.
|
||||||
|
MXGW_ENDPOINT="http://10.100.0.48:5120"
|
||||||
|
MXGW_APIKEY="mxgw_scadabridgeshared_O193yRm28zftUAcL-HPkTjAuE-vPz86MUtNLFWpcbOY"
|
||||||
|
MXGW_CONFIG="{\"endpoint\":\"${MXGW_ENDPOINT}\",\"apiKey\":\"${MXGW_APIKEY}\",\"clientName\":\"\",\"writeUserId\":0,\"useTls\":false,\"caFile\":\"\",\"serverName\":\"\",\"readTimeoutMs\":5000}"
|
||||||
|
|
||||||
|
for ident in site-a site-b site-c; do
|
||||||
|
SITE_ID=$($CLI $URL $AUTH --format json site list \
|
||||||
|
| python3 -c "import sys,json; print(next((s['id'] for s in json.load(sys.stdin) if s.get('siteIdentifier')=='$ident'), ''))" 2>/dev/null)
|
||||||
|
if [ -z "$SITE_ID" ]; then
|
||||||
|
echo " ($ident not found — skipping MxGateway connection)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo " $ident (id=$SITE_ID): creating 'MxGateway Shared'..."
|
||||||
|
$CLI $URL $AUTH data-connection create \
|
||||||
|
--site-id "$SITE_ID" \
|
||||||
|
--name "MxGateway Shared" \
|
||||||
|
--protocol "MxGateway" \
|
||||||
|
--primary-config "$MXGW_CONFIG" \
|
||||||
|
|| echo " (MxGateway connection may already exist on $ident)"
|
||||||
|
done
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Seeding LDAP group mappings (Design + Deployment)..."
|
echo "Seeding LDAP group mappings (Design + Deployment)..."
|
||||||
# SecurityConfiguration.HasData declares 4 mappings but the InitialSchema
|
# SecurityConfiguration.HasData declares 4 mappings but the InitialSchema
|
||||||
@@ -82,9 +111,18 @@ IF NOT EXISTS (SELECT 1 FROM LdapGroupMappings WHERE Id = 4)
|
|||||||
SET IDENTITY_INSERT LdapGroupMappings OFF;
|
SET IDENTITY_INSERT LdapGroupMappings OFF;
|
||||||
"
|
"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Deploying artifacts to all sites (pushes data connections so the sites"
|
||||||
|
echo "establish them — the MxGateway DataConnectionActor connects eagerly)..."
|
||||||
|
$CLI $URL $AUTH deploy artifacts \
|
||||||
|
|| echo " (artifact deploy reported an issue — check 'deploy status')"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== Site seeding complete ==="
|
echo "=== Site seeding complete ==="
|
||||||
echo ""
|
echo ""
|
||||||
echo "Verify with: $CLI $URL $AUTH site list"
|
echo "Verify with: $CLI $URL $AUTH site list"
|
||||||
|
echo "Verify connections: $CLI $URL $AUTH data-connection list"
|
||||||
|
echo "Verify MxGateway is live (per site container):"
|
||||||
|
echo " docker logs scadabridge-site-a-a 2>&1 | grep -i mxgateway"
|
||||||
echo "Multi-role test user has Admin + Design + Deployment."
|
echo "Multi-role test user has Admin + Design + Deployment."
|
||||||
echo "Sign out and back in to refresh session role claims."
|
echo "Sign out and back in to refresh session role claims."
|
||||||
|
|||||||
@@ -1002,6 +1002,11 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
|
|||||||
"Deploying system artifacts, deploymentId={DeploymentId}", command.DeploymentId);
|
"Deploying system artifacts, deploymentId={DeploymentId}", command.DeploymentId);
|
||||||
|
|
||||||
var sender = Sender;
|
var sender = Sender;
|
||||||
|
// Capture Self before entering Task.Run: the Self/Sender/Context properties
|
||||||
|
// are backed by the ambient ActorCell, which is null on a thread-pool thread,
|
||||||
|
// so reading Self *inside* the lambda throws "no active ActorContext". The
|
||||||
|
// data-connections branch below dispatches via this captured ref.
|
||||||
|
var self = Self;
|
||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
@@ -1071,7 +1076,7 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
|
|||||||
// helper's hash cache skips unchanged definitions, so
|
// helper's hash cache skips unchanged definitions, so
|
||||||
// the push is idempotent for re-deploys of the same
|
// the push is idempotent for re-deploys of the same
|
||||||
// artifact bundle.
|
// artifact bundle.
|
||||||
Self.Tell(new ApplyArtifactDataConnectionsToDcl(command.DataConnections));
|
self.Tell(new ApplyArtifactDataConnectionsToDcl(command.DataConnections));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store SMTP configurations
|
// Store SMTP configurations
|
||||||
|
|||||||
Reference in New Issue
Block a user