Skip to content

Instantly share code, notes, and snippets.

@JKerens
Last active March 3, 2023 19:47
Show Gist options
  • Select an option

  • Save JKerens/dd1426be8b77a2b2a90e7cfb34a80e73 to your computer and use it in GitHub Desktop.

Select an option

Save JKerens/dd1426be8b77a2b2a90e7cfb34a80e73 to your computer and use it in GitHub Desktop.
Azure PowerShell Caching Idea
$Script:cache ??= [ordered]@{}
<#
.EXAMPLE
Import-Module .\Az.Module.Cache.psm1
$servers = Get-CachedItem -ValueFactory { Get-AzResource -ResourceType "Microsoft.Sql/servers" } -Verbose
#>
function Get-CachedItem {
param(
[Parameter(Mandatory = $true)]
[scriptblock]$ValueFactory,
[Parameter(Mandatory = $false)]
[int]$ExpiresInMinutes = 5
)
[TimeSpan]$ExpirationTime = [TimeSpan]::FromMinutes($ExpiresInMinutes)
# Hash the command in a safe deterministic way
$commandAst = [System.Management.Automation.Language.Parser]::ParseInput($ValueFactory.ToString(), [ref]$null, [ref]$null)
$commandBase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($commandAst.ToString()))
# Tack on the subscription to avoid bugs when switching subscriptions
$subscription = (Get-AzContext) ?? "NA"
$Key = "$($subscription.Subscription.Id):$($commandBase64)"
$cachedItem = Get-CachedItemFromCache $Key
if ($cachedItem -and (Get-Date) -lt $cachedItem.Expires) {
# Item exists in cache and hasn't expired, return the cached value
Write-Verbose "Cache Hit Found"
return $cachedItem.Value
}
Write-Verbose "Cache Miss, Adding Record"
# Item doesn't exist in cache or has expired, generate a new value and cache it
$value = Invoke-Command $ValueFactory
$expires = (Get-Date).Add($ExpirationTime)
Add-CachedItemToCache $Key $value $expires
Remove-ExpiredCache
return $value
}
function Get-CachedItemFromCache {
param(
[Parameter(Mandatory = $true)]
[string]$Key
)
return ($Script:cache.Contains($Key)) `
? $Script:cache[$Key]
: $null
}
function Add-CachedItemToCache {
param(
[Parameter(Mandatory = $true)]
[string]$Key,
[Parameter(Mandatory = $true)]
$Value,
[Parameter(Mandatory = $true)]
[DateTime]$Expires
)
$Script:cache[$Key] = [PSCustomObject]@{
Value = $Value
Expires = $Expires
}
}
# For debugging JIC
function Get-Cache {
return $Script:cache
}
function Clear-Cache {
$Script:cache = [ordered]@{}
}
function Remove-ExpiredCache {
# This is to prevent editing an enumeration while looping on it
$keys = $Script:cache.GetEnumerator() | ForEach-Object { $_.Key }
$keys | ForEach-Object {
if ((Get-Date) -ge $Script:cache[$_].Expires) {
Write-Verbose "Removing Stale Cache Entry $_"
$Script:cache.Remove($_)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment