Public/Update-DFPackageCache.ps1
|
#Requires -Version 7.0 function Update-DFPackageCache { <# .SYNOPSIS Refreshes all catalog caches used by Find-DFPackage (trifle) — and does nothing else. Designed to run from Task Scheduler so interactive queries always answer from warm caches. .DESCRIPTION Runs synchronously and sequentially (it IS the background work): rebuilds snapshot indexes (scoop bucket index, winget SQLite extraction), refreshes the unified installed-package snapshot, then re-fetches every recently seen query plus the exact name of every installed tool against each web catalog. Also re-warms every cached package-detail entry (readme/GitHub/install-hint data fetched by `trifle`'s detail card) — the files under each provider's `details/` cache directory ARE the re-warm list, keyed off the raw PackageId stored in each entry. Safe to run while an interactive session is open — all cache writes are atomic renames, so last writer wins and both stay valid. .PARAMETER Source Restrict the refresh to these catalogs. .PARAMETER Quiet Suppress progress output (Task Scheduler mode); warnings still flow. .EXAMPLE Update-DFPackageCache Full refresh with progress messages. .EXAMPLE pwsh -NoProfile -Command "winget source update; Import-Module DotForge; Update-DFPackageCache -Quiet" The Task Scheduler action for a nightly catalog refresh. `winget source update` runs first — see NOTES for why. .OUTPUTS None. .NOTES Winget caveat: the winget catalog is read from the source.msix that winget itself downloads, and winget only refreshes that file when winget runs. This command re-extracts whatever msix is present — it cannot make winget download a newer one. On machines that rarely invoke winget the index silently ages (the card's Cache line shows e.g. 'winget 61d'). Include `winget source update` (~5s) in the scheduled action, before Update-DFPackageCache, to keep it bounded. #> [CmdletBinding()] param( [ValidateSet('scoop', 'winget', 'choco', 'npm', 'pypi', 'crates', 'psgallery')] [string[]]$Source, [switch]$Quiet ) $providers = @(Get-DFCatalogProvider -Source $Source) foreach ($provider in $providers | Where-Object Kind -eq 'snapshot') { if (-not $Quiet) { Write-Host "Refreshing $($provider.Name) index…" } try { & $provider.Refresh $null } catch { Write-Warning "DotForge: $($provider.Name) index refresh failed: $_" } } if (-not $Quiet) { Write-Host 'Reading installed packages…' } $installed = Get-DFCatalogInstalled # Re-warm targets: recently seen queries + names of everything installed. $queries = [System.Collections.Generic.List[string]]::new() $cacheRoot = Get-DFCatalogCacheRoot if ($cacheRoot) { $seenFile = Join-Path $cacheRoot 'seen-queries.json' if (Test-Path $seenFile) { try { foreach ($entry in @(Get-Content $seenFile -Raw | ConvertFrom-Json)) { if ($entry.query) { $queries.Add([string]$entry.query) } } } catch {} } } foreach ($item in $installed.Items) { if ($item.Name) { $queries.Add(([string]$item.Name).ToLowerInvariant()) } } $queries = @($queries | Select-Object -Unique) $webProviders = @($providers | Where-Object Kind -eq 'query-cache') foreach ($query in $queries) { foreach ($provider in $webProviders) { try { & $provider.Refresh $query } catch { Write-Warning "DotForge: $($provider.Name) re-warm of '$query' failed: $_" } } } # Re-warm every cached detail entry (the files themselves are the list; # the envelope's query field holds the raw PackageId). $detailCount = 0 if ($cacheRoot) { foreach ($provider in $providers) { if (-not $provider.Detail) { continue } $detailsDir = Join-Path $cacheRoot "$($provider.Name)/details" if (-not (Test-Path $detailsDir)) { continue } foreach ($file in Get-ChildItem $detailsDir -Filter '*.json' -File) { $cached = Read-DFCatalogCacheFile -Path $file.FullName -Ttl ([timespan]::MaxValue) if (-not $cached -or -not $cached.Query) { continue } try { $null = & $provider.Detail $cached.Query $true $detailCount++ } catch { Write-Warning "DotForge: $($provider.Name) detail re-warm of '$($cached.Query)' failed: $_" } } } } if (-not $Quiet) { Write-Host "Re-warmed $($queries.Count) queries across $($webProviders.Count) web catalogs and $detailCount detail entries." } } |