Install swap: -Reapply/-Verify folder walk runs while the service is stopped (vd03 downtime ~101 s vs 20–40 s estimate) #905
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found in the 2026-11-13
c9640f5cdeploy (recorddocs/deploy/2026-11-13-vd03-qa-to-c9640f5c.md).Invoke-OtOpcUaInstallSwap.ps1(#901) runs-Reapply+-Verifybetween stop and start. On vd03 the walk covers all ofE:\ApiInstall, so downtime was about 101 s (the pack estimated 20–40 s; earlier swaps took 10–15 s). The QA pair outage was about 91 s against an estimate of 1–1.5 min.Suggested fix: do as much of the ACL work as possible before stopping. The folder-level ACLs on everything except the swapped-in install folder can be re-applied or verified while the old build still serves. Only the new install folder (and anything inside it) needs re-applying in the stopped window, followed by a scoped
-Verifyof those entries. A full-Verifycan run after start as a gate (stop the service again if it fails), or before stop for the untouched entries. Keep the guarantee that the new build never runs unverified. Measure before and after on windev with the Windows test harness.Fixed in
0c19f26con master.Where the time went. I measured on windev with a vd03-like tree. The cost was the protected-DACL coverage scan, not icacls propagation and not the ACL writes. Both
-Reapplyand-Verifywalked every denied folder while the service was stopped. On vd03 that means all ofE:\ApiInstall, and the nested roots (install folder,pki\) were walked again. Each walk usedGet-ChildItem -Recurse, thenGet-Aclper item, then a pipeline per item for-Skip.17,584 items (PS 5.1 / PS 7):
Get-Aclper itemFind-OtOpcUaDenyCoverageGap(old)GetAccessControl(Access)per item (new)Set-Acldeny on the whole tree, first time (propagation)A second cost showed up once the walk was gone.
Get-NetFirewallRule+Get-NetFirewallApplicationFiltertake 3–5 s per run on windev.Change
-Skipfolders and reads only the DACL. It walks each denied folder once (outermost roots only) and does not follow reparse points.Install-ScriptWorkerIsolation.ps1 -Scope All|InstallRoot|Outside(works with-Reapply,-Verifyand-PlanOnly):InstallRootis the folder ACEs a swap drops:WorkerFolderAcl,InstallRootDeny, and a denied folder inside the install folder such as vd03'spki\.Outsideis everything else, including the firewall rule. Its exe path does not change in a swap, and the swap preflight now checks that the candidate carries the worker exe.Invoke-OtOpcUaInstallSwap.ps1:-Reapply/-Verify -Scope Outsidebefore the stop, with the full scan. If that fails, nothing is stopped or moved.-Reapply/-Verify -Scope InstallRoot, so the new build is still never started unverified.stopped window (…): N s [stop, move, carry, isolation].-NoStart,-NoCarryand the pre-#901 refusal behave as before.Before/after on windev (
Test-ScriptWorkerIsolation.Windows.ps1 -TimingOnly -TimingFiles 17000 [-ScriptsDir <old>]; 17,851 items under the denied folder, 48 protected files, temporary local host account):Of the remaining ~6 s, about 1.5 s per installer run is process start, script parse and module import.
Tests
-Scopeargument rules, and the swap order checked from the parsed script. The new assertions were mutation-checked.-LocalHostAccount). New cases: scoped verify/reapply after a raw swap, each scope's negative control, scan scoping and dedup, the candidate-without-exe refusal, the pre-stop gate (nothing moves),-NoStartwith service control, and a-NoCarryrollback.Docs:
docs/ServiceHosting.md, plus downtime notes in thec9640f5cpack (§7) and record. The next vd03 swap should be about 20–30 s from stop to ready, plus thedata\backup.Deployed to DEV vd03 and the QA pair vq03/vq04 on 2026-11-13 (12:27–12:48Z), master
76e73e7d. Record:docs/deploy/2026-11-13-vd03-qa-to-76e73e7d.md(5baf05f6).The swap ran with the service up and
-NoStart, so-Scope Outsideran with the old build serving.vd03
stop -> swapped and verified (left stopped): 5.7 s [stop 1.5 s, move 0.0 s, carry 0.8 s, isolation 3.4 s].c9640f5c: ~101 s). Full-Verifyafter start: OK 14/14.QA
4.8 s(vq04) and4.6 s(vq03). Full-Verifyafter every start: OK 21/21.c9640f5c: ~91 s).One new defect, filed as #908. On both QA nodes the first
Move-Item app → app.bak…failed "file in use" right after the stop. The host was probably still exiting after SCM reported Stopped. Nothing had moved, so a retry with the service stopped went through. On vq03 the retry re-ran the Outside scope inside the outage (~20 s of the 36.5 s).Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi