7.0 KiB
Deployment record — wonder-app-vq03 + wonder-app-vq04 (QA) — 2026-08-20
Point-in-time record of a ScadaBridge binary + schema upgrade of the QA two-host
topology: a real central pair (central-a = wonder-app-vq03 10.220.158.2, central-b =
wonder-app-vq04 10.220.158.3, :8085) and a site-a pair (node-a/node-b on the same two
boxes, gRPC :8083, metrics :8084), each box running ScadaBridge-Central, ScadaBridge-Site
and ScadaBridge-LDAP out of E:\ApiInstall\ScadaBridge. Shared ConfigDb on
wonder-sql-vq03. Performed from the Mac via psbridge on vq04 (:6150, root E:\psrem);
vq03 reached from vq04 over WinRM (Invoke-Command) and the E$ admin share.
1. Binary + schema upgrade
| Item | Value |
|---|---|
| Build deployed | main @ a24fa38e (from d4bb4e17, 2026-08-12; 246 commits) — all four nodes |
| Headline change | Grouped connection bindings (docs/plans/2026-08-20-grouped-connection-bindings-design.md): the Configure page sources its binding rows from the flattened configuration, grouped per module with a per-group Object apply; CLI instance bind-module. Plus everything since 08-12 (arch-review Medium/Low waves, LocalDb 0.3.2→0.3.4, gRPC stream batching, bulk-deploy up-to-date skip, …). |
| Publish | dotnet publish -c Release -r win-x64 --self-contained true for Host (→ app\, 520 files) and CLI (→ cli\), zipped and pushed via psbridge push (SHA-256 verified), unpacked under E:\psrem\releases\a24fa38e\, mirrored to \\wonder-app-vq03\E$\psrem-stage\a24fa38e with robocopy. |
| EF migrations applied | 6, via sqlcmd -C -b -I on vq03 from an idempotent delta script (dotnet ef migrations script 20260810100836_AddSmtpConfigurationTransport --idempotent): 20260814235335_AddAuditLogAndNotificationCoveringIndexes, 20260815004957_AlignAuditLogEventIdUniqueness, 20260815154803_AddBundleUnlockAttemptTable, 20260815165452_AddDeploymentRecordListSortIndex, 20260819183326_AddSiteCallsListSortIndex, 20260819201210_AddNotificationsListSortIndex. All additive (indexes + one table + one index drop). |
| New required config | AuditLog:SiteWriter:DatabasePath (top-level section, Site nodes; StartupValidator refuses to boot without it since 2e4e41a8) — added to appsettings.Site.json on both boxes as E:\ApiInstall\ScadaBridge\site\data\auditlog.db. The only appsettings delta across the 246 commits. |
| Data relocated | The site audit SQLite file had been written CWD-relative, i.e. to C:\Windows\System32\auditlog.db (the exact hazard 2e4e41a8 closed). Moved, with its -wal/-shm, into site\data\ on both boxes while the Site service was stopped. |
| Preserved across swap | box appsettings.json / appsettings.Central.json / appsettings.Site.json (copied back from the backup; service env vars untouched), central\data, site\data (secrets.db, site-localdb.db). |
| DB backup | ScadaBridge_pre-a24fa38e_20260820T162535.bak (COPY_ONLY, SQL Server default backup dir on wonder-sql-vq03) |
| Binary backup | E:\ApiInstall\ScadaBridge\app.bak.20260820T162659 + cli.bak.20260820T162659 on each box (old d4bb4e17 binaries + appsettings) |
Sequence
Stop Site pair (both boxes) → stop Central pair → swap app\/cli\ on vq04 then vq03 →
start Central pair → wait 20 s → start Site pair. Pairs were stopped and started together
(required since LocalDb Phase 2 — no rolling upgrade of a site pair).
Pitfalls hit (for next time)
- A full-history
--idempotentscript fails on SQL Server batch-compile (Invalid column name 'Configuration'from an early migration) — script from the DB's current migration. sqlcmdneeds-I(QUOTED_IDENTIFIER ON) or the filtered/covering index migrations fail with Msg 1934.- Inside a
psbridge execsingle-quoted script, doubled''quotes are eaten — use[char]39. Invoke-Commandoutput must be piped throughOut-Stringto come back through psbridge.
Verification
/health/ready= 200 Healthy on both centrals (database + akka-cluster Up, memberCount 2, unreachable 0, all 5 required singletons) and both sites (akka-cluster Up, memberCount 2,localdbHealthy withreplicationConnected=true, backlog 0).- Zero
[ERR]/[WRN]/[FTL]on any of the four node logs after the new boot (the[FTL] host terminated unexpectedlyat 16:27:39 is the old build's stop). - Feature proven on the QA data that motivated it:
/deployment/instances/1/configure(Z28061, CvdReactor) now lists 264 data-sourced attributes in 8 groups —(instance)16,DelmiaReceiver10,LeftDelmiaReceiver10,LeftMESReceiver26,LeftReactorSide83 (incl.LeakTest),RightDelmiaReceiver10,RightMESReceiver26,RightReactorSide83 — all bound, every group's Object inferred and pre-filled (Z28061,DelmiaReceiver_043,Left_002.DelmiaReceiver,MESReceiver_023,Left_002,Right_002.DelmiaReceiver,MESReceiver_022,Right_002),Test Bindings (264). Before this build the page showed only the 16 direct attributes.
2. Rollback
- Binaries: on each box stop both services, rename
app→app.failed,app.bak.20260820T162659→app(same forcli), start Central then Site. The old build tolerates the new (additive) schema and ignores the addedAuditLogkey — but note it will again writeauditlog.dbCWD-relative into System32. - Schema: restore
ScadaBridge_pre-a24fa38e_20260820T162535.bak(not needed for a binary rollback).
3. Outstanding
- None from this deploy. ZIPSEN (id 7) remains the known non-deployable draft instance.
4. Hotfix da0bfe2b — same day, 16:53 (QA only so far)
Incident (reported on vq03 Z28061 MoveIn): SetAttribute('RightMESReceiver.MoveInCompleteFlag') failed: Session session-736b2d47… was not found while the attribute showed GOOD quality.
Root cause (from both logs): at 15:29:03 the gateway dashboard user admin (client
10.181.200.169) closed ScadaBridge's MxGateway session. The gateway completes a closed
session's event stream gracefully (OK status), and MxGatewayDataConnection.RunEventLoopAsync
only raised Disconnected on a fault — so the adapter stayed Connected on a dead session for
an hour (values frozen at last GOOD, every write NotFound; the 10 s NotFound heartbeat was
the unresolved-tag resolution probe re-subscribing on the dead session). The 16:28 upgrade
restart cleared it incidentally. A graceful gateway shutdown takes the same path.
Fix: da0bfe2b — a non-cancelled end of the event stream now signals Disconnected
(pinned by MxGatewayDataConnectionReconnectTests.EventStreamGracefulCompletion_*).
Deployed to all four QA nodes as a binary-only swap (no migrations, no config): backups
app.bak.20260820T165357 / cli.bak.20260820T165357 on both boxes; /health/ready 200
Healthy, 2/2 members, site replication connected. Not yet on prod vd03. Live gate still to
run: close the site's session from the gateway dashboard and confirm the site reconnects
(MxGateway event stream ended without a fault … signalling disconnect → reconnect → values resume).