仪表盘和 6 类统计摘要接入 HybridCache(内存 + Redis)。
默认 Redis 缓存 3 分钟、本地缓存 30 秒,可通过环境变量调整。 缓存键包含数据权限范围、有效学院和全部筛选条件,避免跨学院串数据。 Excel 导出保持实时查询,不使用摘要缓存。 无需数据库迁移。
This commit is contained in:
@@ -6,7 +6,8 @@ namespace Jiaowu.Api.Infrastructure.Caching;
|
||||
public enum AppCacheProfile
|
||||
{
|
||||
ReferenceData,
|
||||
PublishedTimetable
|
||||
PublishedTimetable,
|
||||
Analytics
|
||||
}
|
||||
|
||||
public interface IAppCache
|
||||
@@ -106,6 +107,12 @@ public sealed class HybridAppCache(
|
||||
LocalCacheExpiration =
|
||||
TimeSpan.FromSeconds(options.TimetableLocalExpirationSeconds)
|
||||
},
|
||||
AppCacheProfile.Analytics => new HybridCacheEntryOptions
|
||||
{
|
||||
Expiration = TimeSpan.FromMinutes(options.AnalyticsExpirationMinutes),
|
||||
LocalCacheExpiration =
|
||||
TimeSpan.FromSeconds(options.AnalyticsLocalExpirationSeconds)
|
||||
},
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(profile), profile, null)
|
||||
};
|
||||
|
||||
@@ -146,6 +153,7 @@ public sealed class NoOpAppCache : IAppCache
|
||||
public static class AppCacheKeys
|
||||
{
|
||||
public const string ActivationOptions = "auth:activation-options";
|
||||
public const string Dashboard = "dashboard:summary";
|
||||
public const string TimetableOptions = "timetable:options";
|
||||
|
||||
public static string BaseData(string kind) => $"base-data:{kind}";
|
||||
@@ -156,11 +164,30 @@ public static class AppCacheKeys
|
||||
Guid? academicTermId) =>
|
||||
$"timetable:published:{academicTermId?.ToString("N") ?? "current"}:" +
|
||||
$"{resourceType}:{resourceId:N}";
|
||||
|
||||
public static string Statistics(
|
||||
string area,
|
||||
string dataScope,
|
||||
Guid? effectiveCollegeId,
|
||||
params string?[] filters)
|
||||
{
|
||||
static string Normalize(string? value) =>
|
||||
string.IsNullOrWhiteSpace(value)
|
||||
? "-"
|
||||
: value.Trim().ToLowerInvariant();
|
||||
|
||||
var filterPart = filters.Length == 0
|
||||
? "all"
|
||||
: string.Join(':', filters.Select(Normalize));
|
||||
return $"statistics:{Normalize(area)}:scope:{Normalize(dataScope)}:" +
|
||||
$"college:{effectiveCollegeId?.ToString("N") ?? "all"}:{filterPart}";
|
||||
}
|
||||
}
|
||||
|
||||
public static class AppCacheTags
|
||||
{
|
||||
public const string BaseData = "base-data";
|
||||
public const string Analytics = "analytics";
|
||||
public const string Timetables = "timetables";
|
||||
public const string TimetableOptions = "timetable:options";
|
||||
|
||||
|
||||
@@ -10,5 +10,7 @@ public sealed class AppCacheOptions
|
||||
public int ReferenceLocalExpirationSeconds { get; set; } = 120;
|
||||
public int TimetableExpirationMinutes { get; set; } = 10;
|
||||
public int TimetableLocalExpirationSeconds { get; set; } = 30;
|
||||
public int AnalyticsExpirationMinutes { get; set; } = 3;
|
||||
public int AnalyticsLocalExpirationSeconds { get; set; } = 30;
|
||||
public int MaximumPayloadKilobytes { get; set; } = 2048;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user