Modules/businessdev.ALbuild.Core/Public/Lock-ALbuildCacheEntry.ps1
|
function Lock-ALbuildCacheEntry { <# .SYNOPSIS Acquires the cache locks that cover a prunable cache entry. .DESCRIPTION A cache entry may not be removed while another build is extracting into it. Get-BcArtifact locks the LEAF it extracts into (<version>\<country>, <version>\platform), not the version folder, so covering an entry means locking the entry itself plus every immediate child. All-or-nothing: if any lock cannot be taken within the timeout, the ones already held are released before returning, so a caller can never hold half a lock set. The lock name comes from Get-ALbuildCacheLockName, which is the single definition both sides must agree on - a second, copied definition would drift and then silently delete a folder out from under a reader. .PARAMETER Path The cache entry to cover (typically a <type>\<version> folder). .PARAMETER TimeoutSeconds How long to wait per lock. Default 5. .EXAMPLE $locks = Lock-ALbuildCacheEntry -Path $versionFolder if ($locks.Acquired) { try { Remove-Item ... } finally { Unlock-ALbuildCacheEntry -Locks $locks } } .OUTPUTS PSCustomObject with Acquired, BusyPath and Mutexes. #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $Path, [int] $TimeoutSeconds = 5 ) $paths = @($Path) + @( Get-ChildItem -LiteralPath $Path -Directory -Force -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName } ) $held = [System.Collections.Generic.List[object]]::new() foreach ($p in $paths) { $mutex = New-Object System.Threading.Mutex($false, (Get-ALbuildCacheLockName -Path $p)) $got = $false try { $got = $mutex.WaitOne([TimeSpan]::FromSeconds($TimeoutSeconds)) } catch [System.Threading.AbandonedMutexException] { $got = $true } # prior holder crashed; we own it if (-not $got) { $mutex.Dispose() foreach ($h in $held) { $h.ReleaseMutex(); $h.Dispose() } return [PSCustomObject]@{ Acquired = $false; BusyPath = $p; Mutexes = @() } } $held.Add($mutex) } return [PSCustomObject]@{ Acquired = $true; BusyPath = $null; Mutexes = $held.ToArray() } } |