优化
This commit is contained in:
+35
-16
@@ -12,27 +12,42 @@ $ErrorActionPreference = 'Stop'
|
||||
if (-not $IsWindows -or $PSVersionTable.PSVersion.Major -lt 7) {
|
||||
throw 'local-check requires Windows and PowerShell 7 (pwsh).'
|
||||
}
|
||||
# 所有工作目录使用同一用户级锁;句柄随进程退出关闭,不依赖删除过期锁文件。
|
||||
# 所有工作目录共用两个用户级锁;首槽保留原锁名,运行中的旧入口仍计入容量。
|
||||
$stateDirectory = Join-Path $env:LOCALAPPDATA 'Chongchong/LocalChecks'
|
||||
[IO.Directory]::CreateDirectory($stateDirectory) | Out-Null
|
||||
$lockPath = Join-Path $stateDirectory 'heavy.lock'
|
||||
$ownerPath = Join-Path $stateDirectory 'owner.json'
|
||||
$resultPath = Join-Path $stateDirectory 'last-result.json'
|
||||
function Read-Owner {
|
||||
try { return [IO.File]::ReadAllText($ownerPath) } catch { return 'Owner information is being updated.' }
|
||||
$slotDefinitions = @(
|
||||
[pscustomobject]@{ number = 1; lock = (Join-Path $stateDirectory 'heavy.lock'); owner = (Join-Path $stateDirectory 'owner.json'); result = (Join-Path $stateDirectory 'last-result.json') },
|
||||
[pscustomobject]@{ number = 2; lock = (Join-Path $stateDirectory 'heavy-2.lock'); owner = (Join-Path $stateDirectory 'owner-2.json'); result = (Join-Path $stateDirectory 'last-result-2.json') }
|
||||
)
|
||||
function Read-Owner($definition) {
|
||||
try { return [IO.File]::ReadAllText($definition.owner) } catch { return 'Owner information is being updated.' }
|
||||
}
|
||||
function Open-Slot {
|
||||
try { return [IO.File]::Open($lockPath, 'OpenOrCreate', 'ReadWrite', 'None') }
|
||||
function Open-Slot($definition) {
|
||||
try { return [IO.File]::Open($definition.lock, 'OpenOrCreate', 'ReadWrite', 'None') }
|
||||
catch [IO.IOException] {
|
||||
if (($_.Exception.HResult -band 0xffff) -notin @(32, 33)) { throw }
|
||||
return $null
|
||||
}
|
||||
}
|
||||
function Open-AvailableSlot {
|
||||
foreach ($definition in $slotDefinitions) {
|
||||
$handle = Open-Slot $definition
|
||||
if ($handle) { return [pscustomobject]@{ definition = $definition; handle = $handle } }
|
||||
}
|
||||
return $null
|
||||
}
|
||||
if ($Status) {
|
||||
$probe = Open-Slot
|
||||
if ($probe) { $probe.Dispose(); Write-Host 'IDLE: heavy check slot is free.' }
|
||||
else { Write-Host 'BUSY:'; Write-Host (Read-Owner) }
|
||||
if (Test-Path -LiteralPath $resultPath) { Write-Host 'Last result:'; Write-Host ([IO.File]::ReadAllText($resultPath)) }
|
||||
$busyCount = 0
|
||||
foreach ($definition in $slotDefinitions) {
|
||||
$probe = Open-Slot $definition
|
||||
if ($probe) { $probe.Dispose(); Write-Host "IDLE: slot $($definition.number)/2 is free." }
|
||||
else { $busyCount++; Write-Host "BUSY: slot $($definition.number)/2"; Write-Host (Read-Owner $definition) }
|
||||
if (Test-Path -LiteralPath $definition.result) {
|
||||
Write-Host "Last result for slot $($definition.number):"
|
||||
try { Write-Host ([IO.File]::ReadAllText($definition.result)) } catch { Write-Host 'Result is being updated.' }
|
||||
}
|
||||
}
|
||||
Write-Host "Capacity: $busyCount/2 slots occupied."
|
||||
exit 0
|
||||
}
|
||||
if (-not $Command -or -not $Command[0]) { throw 'Pass -Command as an array, for example @("pnpm", "typecheck").' }
|
||||
@@ -51,20 +66,24 @@ $owner = $null
|
||||
$exitCode = 1
|
||||
try {
|
||||
$nextNotice = 0
|
||||
while (-not ($slot = Open-Slot)) {
|
||||
while (-not ($lease = Open-AvailableSlot)) {
|
||||
if ($timer.Elapsed.TotalSeconds -ge $WaitSeconds) {
|
||||
Write-Host "QUEUE TIMEOUT after $WaitSeconds seconds. No check was started."
|
||||
exit 75
|
||||
}
|
||||
if ($timer.Elapsed.TotalSeconds -ge $nextNotice) {
|
||||
Write-Host "WAITING for the shared heavy check slot: $(Read-Owner)"
|
||||
$owners = @($slotDefinitions | ForEach-Object { "slot $($_.number)/2: $(Read-Owner $_)" }) -join ' | '
|
||||
Write-Host "WAITING for either shared heavy check slot: $owners"
|
||||
$nextNotice = $timer.Elapsed.TotalSeconds + 15
|
||||
}
|
||||
Start-Sleep -Milliseconds 250
|
||||
}
|
||||
$owner = [ordered]@{ label = $Label; pid = $PID; directory = $directory; tool = $Command[0]; startedAt = [DateTimeOffset]::Now.ToString('o') }
|
||||
$slot = $lease.handle
|
||||
$ownerPath = $lease.definition.owner
|
||||
$resultPath = $lease.definition.result
|
||||
$owner = [ordered]@{ label = $Label; pid = $PID; slot = $lease.definition.number; directory = $directory; tool = $Command[0]; startedAt = [DateTimeOffset]::Now.ToString('o') }
|
||||
[IO.File]::WriteAllText($ownerPath, ($owner | ConvertTo-Json -Compress))
|
||||
Write-Host "RUNNING [$Label] in $directory (one shared slot; timeout ${TimeoutSeconds}s)"
|
||||
Write-Host "RUNNING [$Label] in $directory (shared slot $($lease.definition.number)/2; timeout ${TimeoutSeconds}s)"
|
||||
|
||||
# Job Object 在包装器被强制结束时也回收本次子进程树,不影响其他 Node/Java。
|
||||
if (-not ('LocalCheckJob' -as [type])) {
|
||||
|
||||
Reference in New Issue
Block a user