Handler.cs 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Application.Abstractions.YouTube;
  4. using SharedKernel.Results;
  5. using Microsoft.EntityFrameworkCore;
  6. using Microsoft.Extensions.Logging;
  7. namespace Application.Features.Api.Studio.DisconnectYouTube;
  8. internal sealed class Handler(
  9. IAppDbContext db,
  10. IYouTubeChannelCache channelCache,
  11. IGoogleOAuthService oauthService,
  12. IYouTubePubSubService pubSubService,
  13. ILogger<Handler> logger
  14. ) : ICommandHandler<Command, Result>
  15. {
  16. public async Task<Result> Handle(Command request, CancellationToken ct)
  17. {
  18. var channel = await db.Channel.FirstOrDefaultAsync(c => c.MemberID == request.MemberID && c.IsActive, ct);
  19. if (channel is null)
  20. {
  21. return Result.Failure(Error.NotFound("YouTube.ChannelNotConnected", "연동된 채널이 없습니다."));
  22. }
  23. // OAuth 토큰 조회 → revoke → 삭제
  24. var oauthToken = await db.MemberOAuthToken.FirstOrDefaultAsync(t => t.MemberID == request.MemberID && t.Provider == "YouTube", ct);
  25. if (oauthToken is not null)
  26. {
  27. // Google OAuth revoke (실패해도 무시)
  28. await oauthService.RevokeTokenAsync(oauthToken.AccessTokenEnc, ct);
  29. db.MemberOAuthToken.Remove(oauthToken);
  30. }
  31. // 채널 비활성화
  32. channel.Deactivate();
  33. // Redis 캐시 삭제
  34. var cacheKey = channel.YouTubeChannelID ?? channel.SID;
  35. await channelCache.RemoveAsync(cacheKey);
  36. await db.SaveChangesAsync(ct);
  37. // PubSub 구독 해지 (실패해도 DB는 이미 해지됨)
  38. if (!string.IsNullOrEmpty(channel.YouTubeChannelID))
  39. {
  40. try
  41. {
  42. await pubSubService.UnsubscribeAsync(channel.YouTubeChannelID, ct);
  43. }
  44. catch (Exception ex)
  45. {
  46. logger.LogError(ex, "[DisconnectYouTube] PubSub 구독 해지 중 예외: channelId={ChannelId}", channel.YouTubeChannelID);
  47. }
  48. }
  49. logger.LogInformation("YouTube 연동 해지: MemberID={MemberID}, ChannelID={ChannelID}", request.MemberID, channel.ID);
  50. return Result.Success();
  51. }
  52. }