Query Caching Examples¶
This directory contains examples of how to implement cacheable queries using the ICacheableQuery interface.
Basic Usage¶
To make a query cacheable, implement the ICacheableQuery interface:
using System.Runtime.Serialization;
using System.Security.Claims;
using LBS.Anchor;
using LBS.Augment.Authentication;
[DataContract(Name = "MyQuery")]
public class MyQuery : ISearchQuery, ICacheableQuery, IRequiresUserContext
{
public string QueryType => this.GetType().GetQueryTypeName();
public ClaimsPrincipal? User => UserContext.Current;
// Query properties
public string? SearchTerm { get; set; }
// Cache configuration
public string CacheKey => $"my-query:{SearchTerm ?? "all"}:{User?.Identity?.IsAuthenticated ?? false}";
public TimeSpan DefaultCacheDuration => TimeSpan.FromMinutes(10);
public string[]? CacheTags => ["my-data"];
// Optional: Dynamic cache configuration based on results
public void ConfigureCaching(IEnumerable<object> results, int totalCount, IFusionCacheContext context)
{
// Adjust cache duration based on result characteristics
context.Options.Duration = totalCount switch
{
0 => TimeSpan.FromMinutes(1), // Empty results
< 10 => TimeSpan.FromMinutes(15), // Small results
_ => TimeSpan.FromHours(1) // Large results
};
}
}
Dynamic Cache Duration Patterns¶
Based on Result Count¶
context.Options.Duration = totalCount switch
{
0 => TimeSpan.FromMinutes(1), // Empty - short cache
< 10 => TimeSpan.FromMinutes(15), // Small - medium cache
< 100 => TimeSpan.FromMinutes(30), // Medium - longer cache
_ => TimeSpan.FromHours(1) // Large - longest cache
};
Based on Data Freshness (inspired by NrlController)¶
// For live data
context.Options.Duration = dataStatus switch
{
"Live" => TimeSpan.FromSeconds(5), // Frequently changing
"Recent" => TimeSpan.FromMinutes(1), // Moderately changing
"Historical" => TimeSpan.FromHours(1), // Stable data
_ => TimeSpan.FromMinutes(5) // Default
};
Based on User Context¶
// Different cache durations for authenticated vs anonymous users
var isAuthenticated = User?.Identity?.IsAuthenticated ?? false;
context.Options.Duration = isAuthenticated
? TimeSpan.FromMinutes(15) // Authenticated users get fresher data
: TimeSpan.FromMinutes(30); // Anonymous users get longer cache
Cache Invalidation¶
Use cache tags for invalidation:
public string[]? CacheTags => ["players", "team-123"];
// Later, invalidate all player-related caches:
await fusionCache.RemoveByTagAsync("players");
Service Chain¶
The query execution follows this chain:
- SecurityQueryService - Validates user permissions
- CachedQueryService - Checks cache, returns cached results or executes query
- QueryService - Executes the actual query against the database
Only queries implementing ICacheableQuery will be cached. All others pass through unchanged.