Handler.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Application.Abstractions.YouTube;
  4. using Microsoft.EntityFrameworkCore;
  5. using SharedKernel.Results;
  6. namespace Application.Features.Api.Studio.GetSettings;
  7. internal sealed class Handler(IAppDbContext db, IYouTubeChannelCache channelCache) : IQueryHandler<Query, Result<Response>>
  8. {
  9. private static readonly Response Empty = new(false, null, null, null, null, null, null, 0, 0, 0, null);
  10. public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
  11. {
  12. var channel = await db.Channel.AsNoTracking().FirstOrDefaultAsync(c => c.MemberID == request.MemberID && c.IsActive, ct);
  13. if (channel is null)
  14. {
  15. return Result.Success(Empty);
  16. }
  17. // 채널 레코드가 존재하면 YouTube 연동된 상태
  18. // SID = YouTube 채널 ID (캐시 키로 사용)
  19. var ytChannelID = channel.YouTubeChannelID ?? channel.SID;
  20. var ytInfo = await channelCache.GetAsync(ytChannelID);
  21. if (ytInfo is not null)
  22. {
  23. // 캐시 데이터가 DB와 다르면 DB 동기화
  24. if (ytInfo.Title != channel.Name
  25. || ytInfo.SubscriberCount != channel.SubscriberCount
  26. || ytInfo.VideoCount != channel.VideoCount
  27. || ytInfo.ViewCount != channel.ViewCount
  28. || channel.YouTubeChannelID is null)
  29. {
  30. var tracked = await db.Channel.FindAsync([channel.ID], ct);
  31. if (tracked is not null)
  32. {
  33. tracked.UpdateYouTubeInfo(
  34. ytInfo.ChannelID, ytInfo.Title, ytInfo.CustomUrl,
  35. ytInfo.Description, ytInfo.ThumbnailUrl, ytInfo.BannerUrl,
  36. ytInfo.SubscriberCount, ytInfo.VideoCount, ytInfo.ViewCount,
  37. ytInfo.Email, ytInfo.PublishedAt);
  38. await db.SaveChangesAsync(ct);
  39. }
  40. }
  41. return Result.Success(new Response(
  42. true,
  43. ytInfo.Title,
  44. ytInfo.CustomUrl,
  45. ytInfo.Description,
  46. channel.YouTubeUrl,
  47. ytInfo.ThumbnailUrl,
  48. ytInfo.BannerUrl,
  49. ytInfo.SubscriberCount,
  50. ytInfo.VideoCount,
  51. ytInfo.ViewCount,
  52. ytInfo.PublishedAt));
  53. }
  54. // 캐시 미스 → DB 데이터로 응답
  55. var isConnected = channel.YouTubeChannelID is not null;
  56. return Result.Success(new Response(
  57. isConnected,
  58. channel.Name,
  59. channel.Handle,
  60. channel.Description,
  61. channel.YouTubeUrl,
  62. channel.ThumbnailUrl,
  63. channel.BannerUrl,
  64. channel.SubscriberCount,
  65. channel.VideoCount,
  66. channel.ViewCount,
  67. channel.YouTubePublishedAt));
  68. }
  69. }