ChatRoomConfigLoader.cs 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. using Application.Abstractions.Cache;
  2. using Application.Abstractions.Chat;
  3. using Application.Abstractions.Data;
  4. using Microsoft.EntityFrameworkCore;
  5. namespace Application.Helpers;
  6. /// <summary>
  7. /// ChatRoomConfig 로더 — Redis 캐시(60초 TTL) → MSSQL 폴백.
  8. /// 오픈 판정: main 은 row 없어도 기본 오픈, 종목방은 row 존재 + IsActive 필요(단계 오픈 — d0 §5-④),
  9. /// 레거시 channel:{sid} 룸은 항상 통과(기존 채널 채팅 동작 유지).
  10. /// </summary>
  11. public static class ChatRoomConfigLoader
  12. {
  13. public sealed record RoomConfig(bool Exists, bool IsActive, short SlowModeSeconds, string? Notice);
  14. private static readonly TimeSpan CacheTtl = TimeSpan.FromSeconds(60);
  15. public static async Task<RoomConfig> GetAsync(ICacheService cache, IAppDbContext db, string roomKey, CancellationToken ct)
  16. {
  17. var cacheKey = CacheKeys.ChatRoomConfig(roomKey);
  18. var cached = await cache.GetAsync<RoomConfig>(cacheKey);
  19. if (cached is not null)
  20. {
  21. return cached;
  22. }
  23. var row = await db.ChatRoomConfig.AsNoTracking().Where(c => c.RoomKey == roomKey).Select(c => new { c.IsActive, c.SlowModeSeconds, c.Notice }).FirstOrDefaultAsync(ct);
  24. var config = row is null
  25. ? new RoomConfig(false, false, 0, null)
  26. : new RoomConfig(true, row.IsActive, row.SlowModeSeconds, row.Notice);
  27. await cache.SetAsync(cacheKey, config, CacheTtl);
  28. return config;
  29. }
  30. public static bool IsRoomOpen(string roomKey, RoomConfig config)
  31. {
  32. if (roomKey == ChatRoomKeys.Main)
  33. {
  34. return !config.Exists || config.IsActive;
  35. }
  36. if (ChatRoomKeys.IsStockRoom(roomKey))
  37. {
  38. return config.Exists && config.IsActive;
  39. }
  40. return true;
  41. }
  42. }