Handler.cs 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. using System.Diagnostics;
  2. using Application.Abstractions.Cache;
  3. using Application.Abstractions.Messaging;
  4. using Application.Abstractions.YouTube;
  5. using SharedKernel.Results;
  6. namespace Application.Features.Admin.Channel.YouTubePubSub.TestApiKey;
  7. internal sealed class Handler(
  8. IYouTubeApiConnectionTester tester,
  9. IYouTubeApiKeyProvider keyProvider,
  10. ICacheService cache
  11. ) : ICommandHandler<Command, Result<Response>>
  12. {
  13. // Google Developers 공식 샘플 채널 — 퍼블릭/안정/삭제되지 않을 채널
  14. private const string TestChannelId = "UC_x5XG1OV2P6uZZ5FSM9Ttw";
  15. private static readonly TimeSpan Cooldown = TimeSpan.FromSeconds(30);
  16. public async Task<Result<Response>> Handle(Command request, CancellationToken ct)
  17. {
  18. // 30초 쿨다운 (quota 낭비 방지)
  19. var locked = await cache.TryLockAsync(CacheKeys.YouTubeApiTestKeyCooldown, Cooldown, ct);
  20. if (!locked)
  21. {
  22. return Result.Failure<Response>(Error.Problem(
  23. "YouTube.TestApiKey.Cooldown",
  24. "30초 쿨다운 중입니다. 잠시 후 다시 시도하세요."
  25. ));
  26. }
  27. // 방금 저장된 API Key가 캐시에 묻히는 문제 회피 — 테스트 직전 무효화
  28. keyProvider.Invalidate();
  29. var sw = Stopwatch.StartNew();
  30. var result = await tester.TestAsync(TestChannelId, ct);
  31. sw.Stop();
  32. return Result.Success(new Response(
  33. Ok: result.Ok,
  34. ElapsedMs: sw.ElapsedMilliseconds,
  35. TestedChannelName: result.ChannelTitle,
  36. TestedChannelId: result.ChannelId,
  37. ErrorMessage: result.ErrorMessage
  38. ));
  39. }
  40. }