# Grace Period Checker - Validates cache freshness # Prevents excessive API calls by checking grace periods # Check if cache entry is still valid (within grace period) export def is-cache-valid? [ component: string # Component name cache_type: string # "infra" or "provisioning" ] { let cache_path = if $cache_type == "infra" { get-infra-cache-path } else { get-provisioning-cache-path } let cache_file = ($cache_path | path join "versions.json") if not ($cache_file | path exists) { return false } let result = (do { open $cache_file } | complete) if $result.exit_code != 0 { return false } let cache_data = ($result.stdout | from json) let vd_result = (do { $cache_data | get $component } | complete) let version_data = if $vd_result.exit_code == 0 { $vd_result.stdout } else { {} } if ($version_data | is-empty) { return false } let ca_result = (do { $version_data | get cached_at } | complete) let cached_at = if $ca_result.exit_code == 0 { $ca_result.stdout } else { "" } let gp_result = (do { $version_data | get grace_period } | complete) let grace_period = if $gp_result.exit_code == 0 { $gp_result.stdout } else { (get-default-grace-period) } if ($cached_at | is-empty) { return false } # Parse cached timestamp let parse_date = (do { $cached_at | into datetime } | complete) if $parse_date.exit_code != 0 { return false } let cached_time = $parse_date.stdout let current_time = (date now) let age_seconds = (($current_time - $cached_time) / 1sec) # Check if within grace period $age_seconds < $grace_period } # Get expired cache entries export def get-expired-entries [ cache_type: string # "infra" or "provisioning" ] { let cache_path = if $cache_type == "infra" { get-infra-cache-path } else { get-provisioning-cache-path } let cache_file = ($cache_path | path join "versions.json") if not ($cache_file | path exists) { return [] } let result = (do { open $cache_file } | complete) if $result.exit_code != 0 { return [] } let cache_data = ($result.stdout | from json) $cache_data | columns | where { |component| not (is-cache-valid? $component $cache_type) } } # Get components that need update check (check_latest = true and expired) export def get-components-needing-update [] { let components = [] # Check infra cache let infra_expired = (get-expired-entries "infra") let infra_check_latest = (get-check-latest-components "infra") let infra_needs_update = ($infra_expired | where { |comp| $comp in $infra_check_latest }) # Check provisioning cache let prov_expired = (get-expired-entries "provisioning") let prov_check_latest = (get-check-latest-components "provisioning") let prov_needs_update = ($prov_expired | where { |comp| $comp in $prov_check_latest }) # Combine and deduplicate ($infra_needs_update ++ $prov_needs_update) | uniq } # Get components with check_latest = true def get-check-latest-components [cache_type: string] { let cache_path = if $cache_type == "infra" { get-infra-cache-path } else { get-provisioning-cache-path } let cache_file = ($cache_path | path join "versions.json") if not ($cache_file | path exists) { return [] } let result = (do { open $cache_file } | complete) if $result.exit_code != 0 { return [] } let cache_data = ($result.stdout | from json) $cache_data | columns | where { |component| let comp_data = ($cache_data | get $component) let cl_result = (do { $comp_data | get check_latest } | complete) if $cl_result.exit_code == 0 { $cl_result.stdout } else { false } } } # Invalidate cache entry (force refresh on next access) export def invalidate-cache-entry [ component: string # Component name cache_type: string # "infra" or "provisioning" ] { let cache_path = if $cache_type == "infra" { get-infra-cache-path } else { get-provisioning-cache-path } let cache_file = ($cache_path | path join "versions.json") if ($cache_file | path exists) { let result = (do { open $cache_file } | complete) if $result.exit_code == 0 { let cache_data = ($result.stdout | from json) let updated_cache = ($cache_data | upsert $component { |entry| $entry | upsert cached_at "1970-01-01T00:00:00Z" # Force expiry }) $updated_cache | save -f $cache_file } } } # Helper functions (same as in cache_manager.nu) def get-infra-cache-path [] { use ../config/accessor.nu config-get let infra_path = (config-get "paths.infra" "") let current_infra = (config-get "infra.current" "default") if ($infra_path | is-empty) { return (get-provisioning-cache-path) } $infra_path | path join $current_infra "cache" } def get-provisioning-cache-path [] { use ../config/accessor.nu config-get config-get "cache.path" ".cache/versions" } def get-default-grace-period [] { use ../config/accessor.nu config-get config-get "cache.grace_period" 86400 }