♻️ Refactor cache system with redis
🐛 Add lock to check in prevent multiple at the same time
This commit is contained in:
@ -1,6 +1,5 @@
|
||||
using DysonNetwork.Sphere.Storage;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using System;
|
||||
@ -8,19 +7,21 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DysonNetwork.Sphere.Sticker;
|
||||
public class StickerService(AppDatabase db, FileService fs, IMemoryCache cache)
|
||||
|
||||
public class StickerService(AppDatabase db, FileService fs, ICacheService cache)
|
||||
{
|
||||
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(15);
|
||||
|
||||
|
||||
public async Task<Sticker> CreateStickerAsync(Sticker sticker)
|
||||
{
|
||||
db.Stickers.Add(sticker);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
|
||||
await fs.MarkUsageAsync(sticker.Image, 1);
|
||||
|
||||
return sticker;
|
||||
}
|
||||
|
||||
public async Task<Sticker> UpdateStickerAsync(Sticker sticker, CloudFile? newImage)
|
||||
{
|
||||
if (newImage != null)
|
||||
@ -32,53 +33,54 @@ public class StickerService(AppDatabase db, FileService fs, IMemoryCache cache)
|
||||
|
||||
db.Stickers.Update(sticker);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
|
||||
// Invalidate cache for this sticker
|
||||
PurgeStickerCache(sticker);
|
||||
await PurgeStickerCache(sticker);
|
||||
|
||||
return sticker;
|
||||
}
|
||||
|
||||
public async Task DeleteStickerAsync(Sticker sticker)
|
||||
{
|
||||
db.Stickers.Remove(sticker);
|
||||
await db.SaveChangesAsync();
|
||||
await fs.MarkUsageAsync(sticker.Image, -1);
|
||||
|
||||
|
||||
// Invalidate cache for this sticker
|
||||
PurgeStickerCache(sticker);
|
||||
await PurgeStickerCache(sticker);
|
||||
}
|
||||
|
||||
public async Task DeleteStickerPackAsync(StickerPack pack)
|
||||
{
|
||||
var stickers = await db.Stickers
|
||||
.Include(s => s.Image)
|
||||
.Where(s => s.PackId == pack.Id)
|
||||
.ToListAsync();
|
||||
|
||||
|
||||
var images = stickers.Select(s => s.Image).ToList();
|
||||
|
||||
|
||||
db.Stickers.RemoveRange(stickers);
|
||||
db.StickerPacks.Remove(pack);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
|
||||
await fs.MarkUsageRangeAsync(images, -1);
|
||||
|
||||
|
||||
// Invalidate cache for all stickers in this pack
|
||||
foreach (var sticker in stickers)
|
||||
{
|
||||
PurgeStickerCache(sticker);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<Sticker?> LookupStickerByIdentifierAsync(string identifier)
|
||||
{
|
||||
identifier = identifier.ToLower();
|
||||
// Try to get from the cache first
|
||||
var cacheKey = $"StickerLookup_{identifier}";
|
||||
if (cache.TryGetValue(cacheKey, out Sticker? cachedSticker))
|
||||
{
|
||||
var cachedSticker = await cache.GetAsync<Sticker>(cacheKey);
|
||||
if (cachedSticker is not null)
|
||||
return cachedSticker;
|
||||
}
|
||||
|
||||
|
||||
// If not in cache, fetch from the database
|
||||
IQueryable<Sticker> query = db.Stickers
|
||||
.Include(e => e.Pack)
|
||||
@ -86,20 +88,20 @@ public class StickerService(AppDatabase db, FileService fs, IMemoryCache cache)
|
||||
query = Guid.TryParse(identifier, out var guid)
|
||||
? query.Where(e => e.Id == guid)
|
||||
: query.Where(e => (e.Pack.Prefix + e.Slug).ToLower() == identifier);
|
||||
|
||||
|
||||
var sticker = await query.FirstOrDefaultAsync();
|
||||
|
||||
|
||||
// Store in cache if found
|
||||
if (sticker != null)
|
||||
cache.Set(cacheKey, sticker, CacheDuration);
|
||||
|
||||
await cache.SetAsync(cacheKey, sticker, CacheDuration);
|
||||
|
||||
return sticker;
|
||||
}
|
||||
|
||||
private void PurgeStickerCache(Sticker sticker)
|
||||
|
||||
private async Task PurgeStickerCache(Sticker sticker)
|
||||
{
|
||||
// Remove both possible cache entries
|
||||
cache.Remove($"StickerLookup_{sticker.Id}");
|
||||
cache.Remove($"StickerLookup_{sticker.Pack.Prefix}{sticker.Slug}");
|
||||
await cache.RemoveAsync($"StickerLookup_{sticker.Id}");
|
||||
await cache.RemoveAsync($"StickerLookup_{sticker.Pack.Prefix}{sticker.Slug}");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user