feat(kol): cache marketplace and generation reads with singleflight

Add cache-aside + singleflight to KOL marketplace list/detail, my-subscription
prompts, and generation schema lookups. Invalidate the shared public-facing
caches when subscriptions are added/revoked (ops) or KOL profile is updated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-24 11:33:17 +08:00
parent 09c8fe1e56
commit 8761e47f78
10 changed files with 339 additions and 102 deletions
@@ -241,6 +241,7 @@ func (s *KolSubscriptionService) invalidateAccessCaches(ctx context.Context, ten
_ = s.cache.Delete(ctx, fmt.Sprintf("workspace:kol_cards:%d", tenantID))
_ = s.cache.DeletePrefix(ctx, fmt.Sprintf("kol:subscription_prompt:list:%d:", tenantID))
_ = s.cache.DeletePrefix(ctx, fmt.Sprintf("kol:subscription_prompt:schema:%d:", tenantID))
_ = s.cache.DeletePrefix(ctx, "kol:marketplace:")
}
func toKolSubscriptionView(item repository.KolSubscriptionRecord) KolSubscriptionView {
@@ -58,6 +58,7 @@ func TestKolSubscriptionInvalidateAccessCaches(t *testing.T) {
wantPrefixes := []string{
"kol:subscription_prompt:list:42:",
"kol:subscription_prompt:schema:42:",
"kol:marketplace:",
}
if !reflect.DeepEqual(cache.deletedPrefixes, wantPrefixes) {
t.Fatalf("deleted prefixes = %v, want %v", cache.deletedPrefixes, wantPrefixes)