Modules/businessdev.ALbuild.Core/Public/Get-ALbuildCacheLockName.ps1
|
function Get-ALbuildCacheLockName { <# .SYNOPSIS Returns the global mutex name that guards a cache folder against concurrent write/removal. .DESCRIPTION ALbuild caches are shared by every build running on a host - several agents on the same server, and (since the runtime factory) several worker threads inside a single agent job. Two operations must never overlap on the same cache entry: * Get-BcArtifact EXTRACTING into it, and * Clear-ALbuildCache REMOVING it. Both sides serialise on a machine-global mutex, and a mutex only serialises anything if both sides compute the SAME name. That is the entire reason this helper exists: the name used to be an inline expression in Get-BcArtifact, so the prune path had no way to agree with it without copying the expression - and a copied hash silently stops matching the moment either copy is touched. A prune that no longer matches does not fail loudly; it deletes a folder out from under a reader, and the build fails much later with a misleading "package ... could not be found". The name is derived from the folder path so that unrelated cache entries never contend: SHA-256 over the lower-cased path, hex, truncated to 32 characters (well inside the 260-character limit on a mutex name), prefixed 'Global\albuild-artifact-' so it spans sessions and services. Lower-casing matters because Windows paths are case-insensitive: 'C:\alb' and 'c:\ALB' are the same folder and must yield the same lock. The 'Global\' prefix requires no elevation for the creating account, but a mutex created by one user is not writable by another by default; agents on a host run as the same service account, so this is not a constraint in practice. .PARAMETER Path The cache folder the lock protects. Does not need to exist - callers lock BEFORE creating it. .EXAMPLE $mutex = New-Object System.Threading.Mutex($false, (Get-ALbuildCacheLockName -Path $targetFolder)) Acquire the same lock Get-BcArtifact uses for that folder. .OUTPUTS System.String: the fully-qualified mutex name. #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory, Position = 0, ValueFromPipeline)] [ValidateNotNullOrEmpty()] [string] $Path ) process { $sha = [System.Security.Cryptography.SHA256]::Create() try { $bytes = $sha.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Path.ToLowerInvariant())) } finally { $sha.Dispose() } $hash = [System.BitConverter]::ToString($bytes).Replace('-', '').Substring(0, 32) return "Global\albuild-artifact-$hash" } } |