using System.Diagnostics; using Application.Abstractions.Cache; using Application.Abstractions.Messaging; using Application.Abstractions.YouTube; using SharedKernel.Results; namespace Application.Features.Admin.Channel.YouTubePubSub.TestApiKey; internal sealed class Handler( IYouTubeApiConnectionTester tester, IYouTubeApiKeyProvider keyProvider, ICacheService cache ) : ICommandHandler> { // Google Developers 공식 샘플 채널 — 퍼블릭/안정/삭제되지 않을 채널 private const string TestChannelId = "UC_x5XG1OV2P6uZZ5FSM9Ttw"; private static readonly TimeSpan Cooldown = TimeSpan.FromSeconds(30); public async Task> Handle(Command request, CancellationToken ct) { // 30초 쿨다운 (quota 낭비 방지) var locked = await cache.TryLockAsync(CacheKeys.YouTubeApiTestKeyCooldown, Cooldown, ct); if (!locked) { return Result.Failure(Error.Problem( "YouTube.TestApiKey.Cooldown", "30초 쿨다운 중입니다. 잠시 후 다시 시도하세요." )); } // 방금 저장된 API Key가 캐시에 묻히는 문제 회피 — 테스트 직전 무효화 keyProvider.Invalidate(); var sw = Stopwatch.StartNew(); var result = await tester.TestAsync(TestChannelId, ct); sw.Stop(); return Result.Success(new Response( Ok: result.Ok, ElapsedMs: sw.ElapsedMilliseconds, TestedChannelName: result.ChannelTitle, TestedChannelId: result.ChannelId, ErrorMessage: result.ErrorMessage )); } }