아바타 저장소 승격 계약을 완성

This commit is contained in:
Yun Chan 2026-08-29 23:58:33 +09:00
parent ac9b702688
commit ccdcfcd2f5
36 changed files with 14734 additions and 222 deletions

View file

@ -0,0 +1,220 @@
$taskDefinitionCutoverContract = Join-Path $PSScriptRoot "public-runtime-task-definition-cutover.ps1"
if (-not (Test-Path -LiteralPath $taskDefinitionCutoverContract -PathType Leaf)) {
throw "Public runtime task definition cutover contract is unavailable"
}
. $taskDefinitionCutoverContract
function Assert-PublicRuntimeTasksDisabledAndIdle {
param(
[Parameter(Mandatory = $true)][object[]]$Snapshot,
[int]$TimeoutSec = 30
)
$deadline = (Get-Date).AddSeconds($TimeoutSec)
do {
$allDisabledAndIdle = $true
foreach ($entry in @($Snapshot)) {
if (-not [bool]$entry.exists) {
$unexpectedTask = Get-ScheduledTask `
-TaskName ([string]$entry.task_name) `
-TaskPath "\" `
-ErrorAction SilentlyContinue
if ($null -ne $unexpectedTask) {
throw "A coordinated public runtime task appeared during maintenance: $($entry.task_name)"
}
continue
}
$task = Get-ScheduledTask `
-TaskName ([string]$entry.task_name) `
-TaskPath "\" `
-ErrorAction Stop
if ([bool]$task.Settings.Enabled -or [string]$task.State -eq "Running") {
$allDisabledAndIdle = $false
break
}
}
if ($allDisabledAndIdle) {
return
}
Start-Sleep -Milliseconds 250
} while ((Get-Date) -lt $deadline)
throw "Public runtime scheduled tasks did not become disabled and idle"
}
function Get-PublicRuntimeTaskMaintenanceState {
param([Parameter(Mandatory = $true)][object[]]$Snapshot)
$allDisabledAndIdle = $true
$restoredToSnapshot = $true
$verified = $true
foreach ($entry in @($Snapshot)) {
if (-not [bool]$entry.exists) {
try {
$unexpectedTask = Get-ScheduledTask `
-TaskName ([string]$entry.task_name) `
-TaskPath "\" `
-ErrorAction SilentlyContinue
if ($null -ne $unexpectedTask) {
$allDisabledAndIdle = $false
$restoredToSnapshot = $false
}
} catch {
$verified = $false
$allDisabledAndIdle = $false
$restoredToSnapshot = $false
}
continue
}
try {
$task = Get-ScheduledTask `
-TaskName ([string]$entry.task_name) `
-TaskPath "\" `
-ErrorAction Stop
$isEnabled = [bool]$task.Settings.Enabled
$isRunning = [string]$task.State -eq "Running"
if ($isEnabled -or $isRunning) {
$allDisabledAndIdle = $false
}
if ($isEnabled -ne [bool]$entry.was_enabled) {
$restoredToSnapshot = $false
}
} catch {
$verified = $false
$allDisabledAndIdle = $false
$restoredToSnapshot = $false
}
}
return [pscustomobject][ordered]@{
verified = $verified
all_disabled_and_idle = $allDisabledAndIdle
restored_to_snapshot = $restoredToSnapshot
}
}
function Suspend-PublicRuntimeTasks {
param(
[Parameter(Mandatory = $true)][object[]]$Snapshot,
[int]$TimeoutSec = 30
)
foreach ($entry in @($Snapshot)) {
if (-not [bool]$entry.exists) {
continue
}
Disable-ScheduledTask `
-TaskName ([string]$entry.task_name) `
-TaskPath "\" `
-ErrorAction Stop `
| Out-Null
}
Assert-PublicRuntimeTasksDisabledAndIdle `
-Snapshot $Snapshot `
-TimeoutSec $TimeoutSec
}
function Enter-PublicRuntimeTaskMaintenance {
param(
[Parameter(Mandatory = $true)][string[]]$TaskNames,
[int]$TimeoutSec = 30
)
$snapshot = @()
try {
# 모든 원상복구 정보를 먼저 캡처한다. disable 도중 두 번째 task에서 오류가 나도
# 첫 번째 task를 포함한 완전한 snapshot으로 되돌릴 수 있어야 한다.
foreach ($taskName in @($TaskNames | Sort-Object -Unique)) {
if ([string]::IsNullOrWhiteSpace($taskName)) {
throw "Public runtime scheduled task name is empty"
}
$task = Get-ScheduledTask `
-TaskName $taskName `
-TaskPath "\" `
-ErrorAction SilentlyContinue
if ($null -eq $task) {
$snapshot += [pscustomobject][ordered]@{
task_name = $taskName
exists = $false
was_enabled = $false
}
continue
}
$wasEnabled = [bool]$task.Settings.Enabled
$snapshot += [pscustomobject][ordered]@{
task_name = $taskName
exists = $true
was_enabled = $wasEnabled
}
}
$result = @($snapshot)
Suspend-PublicRuntimeTasks `
-Snapshot $result `
-TimeoutSec $TimeoutSec
return $result
} catch {
foreach ($entry in @($snapshot)) {
if ([bool]$entry.exists -and [bool]$entry.was_enabled) {
Enable-ScheduledTask `
-TaskName ([string]$entry.task_name) `
-TaskPath "\" `
-ErrorAction SilentlyContinue `
| Out-Null
}
}
foreach ($entry in @($snapshot)) {
if (-not [bool]$entry.exists) {
continue
}
$task = Get-ScheduledTask `
-TaskName ([string]$entry.task_name) `
-TaskPath "\" `
-ErrorAction Stop
if ([bool]$task.Settings.Enabled -ne [bool]$entry.was_enabled) {
throw "Public runtime task maintenance entry rollback failed: $($entry.task_name)"
}
}
throw
}
}
function Exit-PublicRuntimeTaskMaintenance {
param([Parameter(Mandatory = $true)][object[]]$Snapshot)
try {
foreach ($entry in @($Snapshot)) {
if (-not [bool]$entry.exists -or -not [bool]$entry.was_enabled) {
continue
}
Enable-ScheduledTask `
-TaskName ([string]$entry.task_name) `
-TaskPath "\" `
-ErrorAction Stop `
| Out-Null
}
foreach ($entry in @($Snapshot)) {
if (-not [bool]$entry.exists -or -not [bool]$entry.was_enabled) {
continue
}
$task = Get-ScheduledTask `
-TaskName ([string]$entry.task_name) `
-TaskPath "\" `
-ErrorAction Stop
if (-not [bool]$task.Settings.Enabled) {
throw "Public runtime scheduled task was not re-enabled: $($entry.task_name)"
}
}
$restoredTruth = Get-PublicRuntimeTaskMaintenanceState -Snapshot $Snapshot
if (
-not [bool]$restoredTruth.verified -or
-not [bool]$restoredTruth.restored_to_snapshot
) {
throw "Public runtime scheduled task set drifted during maintenance"
}
} catch {
Suspend-PublicRuntimeTasks -Snapshot $Snapshot -TimeoutSec 30
throw
}
}