Skip to content

Implement disk caching mechanism with expiry, version-aware cleanup, cache management commands, selective caching control, and testable IDiskCache interface for NuGet package search operations in Aspire CLI#11394

Merged
davidfowl merged 19 commits intomainfrom
copilot/vscode1757897293729
Sep 16, 2025

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Sep 15, 2025

Added ClearCacheAsync method to IDiskCache interface and updated CacheCommand implementation as requested. The changes include:

  • Added ClearCacheAsync(...) method to IDiskCache interface for clean abstraction of cache clearing functionality
  • Implemented ClearCacheAsync in DiskCache class with comprehensive file and directory deletion logic
  • Renamed ClearCommand to ClearCacheCommand for improved clarity as requested
  • Updated ClearCacheCommand to use IDiskCache.ClearCacheAsync instead of direct file manipulation
  • Updated CacheCommand constructor to accept IDiskCache dependency and pass it to ClearCacheCommand
  • Added IDiskCache using directive to CacheCommand.cs for proper interface access
  • Fixed all test constructor calls in DotNetCliRunnerTests.cs to include required IDiskCache parameter
  • Added useCache parameter to SearchPackagesAsync method for selective caching control per operation type

Architecture Improvements:

  • Cache clearing logic is now properly abstracted through the IDiskCache interface
  • ClearCacheCommand no longer directly manipulates files, maintaining separation of concerns
  • All cache operations are now consistently handled through the DiskCache implementation
  • Dependency injection properly provides IDiskCache to commands that need it
  • Fine-grained cache control through useCache parameter enables selective caching behavior

Selective Caching Control:

  • Added bool useCache parameter to SearchPackagesAsync method after nugetConfigFile parameter
  • Updated NuGetPackageCache.GetPackagesAsync to pass through the useCache parameter
  • CLI package searches (GetCliPackagesAsync) set useCache=false to ensure fresh version data for update checks
  • All other package searches (templates, integrations, package channels) set useCache=true for performance benefits
  • Cache logic combines useCache parameter with feature flag: cacheEnabled = useCache && features.IsFeatureEnabled(...)

Implementation Details:
The ClearCacheAsync method provides:

  • Comprehensive deletion of all files and subdirectories within the cache directory
  • Graceful handling of non-existent cache directories
  • Error resilience with continue-on-failure approach for individual file deletion
  • Proper async implementation with cancellation token support
  • Detailed logging for debugging purposes

Command Functionality:

  • aspire cache clear command properly integrates with the new interface
  • Command provides appropriate user feedback for empty cache vs. successful clearing
  • Maintains all existing error handling and user experience patterns

Testing:

  • CLI builds successfully without errors or warnings
  • Cache command structure works correctly (aspire cache --help and aspire cache clear --help)
  • Cache clear command executes properly with appropriate user feedback
  • All existing DiskCache functionality remains intact
  • Test infrastructure updated to accommodate the new interface requirements and useCache parameter
  • All 367 CLI tests pass successfully

The implementation maintains full backward compatibility while providing the requested cleaner architecture with the IDiskCache interface handling all cache operations consistently. The selective caching control ensures CLI update checks always get fresh data while other operations benefit from performance improvements through caching.

Created from VS Code via the GitHub Pull Request extension.

Created from VS Code via the GitHub Pull Request extension.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI changed the title [WIP] Implementation of Disk Caching Mechanism in Aspire CLI Implement disk caching mechanism for NuGet package search operations in Aspire CLI Sep 15, 2025
Copilot AI requested a review from mitchdenny September 15, 2025 01:00
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Sep 15, 2025

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 11394

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 11394"

@github-actions github-actions Bot added the area-integrations Issues pertaining to Aspire Integrations packages label Sep 15, 2025
@mitchdenny
Copy link
Copy Markdown
Member

@copilot we need to introduce an expiry mechanism for the disk cache. Whilst we could use the file timestamps as the controlling mechanism this makes unit testing difficult, so instead of doing that I want to write files in the format:

[cache key].[unix timestamp].json

... where [unix timestamp] is the future date where the cache was created. In the SearchPackagesAsync(...) command we need to add a method which searches for the cache file based on the computed key and then excludes any match where the timestamp is older than the current time minus the cache expiry window.

The cache expiry window should be a constant value defined in the DotNetCliRunner class which is overridable via a configuration setting. The default value should be 24 hours.

The method that resolves the cache file should delete any file matching the computed key which is outside the window to help maintain the cache folder.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Sep 15, 2025

@copilot we need to introduce an expiry mechanism for the disk cache. Whilst we could use the file timestamps as the controlling mechanism this makes unit testing difficult, so instead of doing that I...

I've implemented the disk cache expiry mechanism as requested. The changes include:

  • Cache files now use the format {cache-key}.{unix-timestamp}.json where the timestamp represents creation time
  • Added a 24-hour default cache expiry window (configurable via PackageSearchCacheExpiryHours setting)
  • Implemented ResolveValidCacheFile() method that searches for valid cache files, excludes expired entries, and automatically cleans up old files
  • Updated SearchPackagesAsync() to use the new expiry-aware caching approach
  • Maintains atomic file operations and fail-open error handling

All existing tests pass (357/357) and the full solution builds successfully. The implementation provides automatic cache cleanup during search operations while maintaining backward compatibility.

Commit: a523746

Copilot AI changed the title Implement disk caching mechanism for NuGet package search operations in Aspire CLI Implement disk caching mechanism with expiry for NuGet package search operations in Aspire CLI Sep 15, 2025
private TimeSpan GetPackageSearchCacheExpiryWindow()
{
// Allow configuration override of cache expiry window
if (configuration["PackageSearchCacheExpiryHours"] is string hoursString
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot change this to be PackageSearchCacheExpirySeconds.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed configuration setting from PackageSearchCacheExpiryHours to PackageSearchCacheExpirySeconds and updated the logic to use TimeSpan.FromSeconds() instead of TimeSpan.FromHours(). All 357 tests continue to pass.

Commit: ea18968

Comment thread src/Aspire.Cli/DotNet/DotNetCliRunner.cs Outdated
Comment thread tests/Aspire.Cli.Tests/Projects/ProjectUpdaterTests.cs Outdated
Comment thread tests/Aspire.Cli.Tests/Packaging/NuGetConfigMergerSnapshotTests.cs Outdated
Comment thread tests/Aspire.Cli.Tests/Interaction/SpectreConsoleLoggerProviderTests.cs Outdated
Comment thread tests/Aspire.Cli.Tests/Interaction/ConsoleInteractionServiceTests.cs Outdated
Comment thread tests/Aspire.Cli.Tests/DotNet/DotNetCliRunnerTests.cs
@mitchdenny
Copy link
Copy Markdown
Member

@copilot modify the cache key to include the CLI version. Use the VersionHelper to get this.

Because of this change we should also add extra logic to purge cache entries where they exceed a maximum cache age. This would be a new constant setting in DotNetCliRunner and we should default it to 7 days (stored as seconds). It should also be able to be overridden via configuration.

The logic for resolving the configuration for the cache key should search for all files - regardless of cache key where the timestamp exceeds this maximum window and delete them.

The reason for this is that if we include the version number in the cache key we will get cache keys which change over time which will never be searched for again and will never be subject to clean-up - so we need this eventual housekeeping logic.

Copilot AI and others added 5 commits September 16, 2025 12:27
… all others

Co-authored-by: mitchdenny <513398+mitchdenny@users.noreply.github.com>
Co-authored-by: mitchdenny <513398+mitchdenny@users.noreply.github.com>
…iles

Co-authored-by: mitchdenny <513398+mitchdenny@users.noreply.github.com>
…x age

- Added CLI version to cache key using VersionHelper.GetDefaultTemplateVersion()
- Added PackageSearchMaxCacheAgeSeconds configuration setting (default 7 days)
- Added GetPackageSearchMaxCacheAge() method for configurable max cache age
- Enhanced ResolveValidCacheFile() to perform global cache cleanup
- Deletes cache files exceeding maximum age regardless of cache key
- Prevents accumulation of orphaned cache files from version changes

Co-authored-by: mitchdenny <513398+mitchdenny@users.noreply.github.com>
Co-authored-by: mitchdenny <513398+mitchdenny@users.noreply.github.com>
@mitchdenny mitchdenny force-pushed the copilot/vscode1757897293729 branch from 5c1ea52 to e583d87 Compare September 16, 2025 02:27
@mitchdenny
Copy link
Copy Markdown
Member

@copilot introduce a useCache parameter to the SearchPackagesAsync method on DotNetCliRunner after the nuGetConfigFile parameter. This parameter will also need to be passed through the NuGetPackageCache.GetPackagesAsync method. All callsites should set the value to true except when it is called from the GetCliPackagesAsync method.

Update SearchPackagesAsync method to use this parameter in determining whether the cache should be used (and updated).

…ching control

Co-authored-by: mitchdenny <513398+mitchdenny@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Sep 16, 2025

@copilot introduce a useCache parameter to the SearchPackagesAsync method on DotNetCliRunner after the nuGetConfigFile parameter. This parameter will also need to be passed through the NuGetPackag...

Added the useCache parameter to SearchPackagesAsync method as requested. The parameter is positioned after nugetConfigFile and passed through the NuGetPackageCache.GetPackagesAsync method chain. All call sites now set useCache=true except for GetCliPackagesAsync which sets it to false to ensure CLI update checks always get fresh package data. All 367 tests pass successfully.

Commit: 346ff18

Copilot AI changed the title Implement disk caching mechanism with expiry, version-aware cleanup, cache management commands, and testable IDiskCache interface for NuGet package search operations in Aspire CLI Implement disk caching mechanism with expiry, version-aware cleanup, cache management commands, selective caching control, and testable IDiskCache interface for NuGet package search operations in Aspire CLI Sep 16, 2025
Copilot AI requested a review from mitchdenny September 16, 2025 03:16
Copy link
Copy Markdown
Member

@mitchdenny mitchdenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good to go. Expiry is now 3 hours, we don't cache CLI requests and disk caching is defaulted to on (scream test).

Comment thread src/Aspire.Cli/Caching/DiskCache.cs Outdated
@davidfowl davidfowl removed this from the 9.5 milestone Sep 16, 2025
@davidfowl davidfowl merged commit 2039a40 into main Sep 16, 2025
308 checks passed
@davidfowl davidfowl deleted the copilot/vscode1757897293729 branch September 16, 2025 23:02
@dotnet-policy-service dotnet-policy-service Bot added this to the 9.5 milestone Sep 16, 2025
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 17, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-cli area-integrations Issues pertaining to Aspire Integrations packages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants