Handler.cs 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. using Application.Abstractions.Messaging;
  2. using Application.Abstractions.Cache;
  3. using Application.Abstractions.Crypto;
  4. namespace Application.Features.Api.Crypto.Candle.GetDays;
  5. public sealed class Handler(IUpbitClient upbit, ICacheService cache) : IQueryHandler<Query, Response>
  6. {
  7. private static readonly TimeSpan _cacheExpiry = TimeSpan.FromMinutes(5);
  8. public async Task<Response> Handle(Query request, CancellationToken ct)
  9. {
  10. var count = Math.Clamp(request.Count, 1, 200);
  11. var cacheKey = CacheKeys.CryptoCandle(request.Market, "d");
  12. // 캐시 확인
  13. var cached = await cache.GetAsync<List<Response.CandleItem>>(cacheKey, ct);
  14. if (cached is { Count: > 0 })
  15. {
  16. return new Response(cached);
  17. }
  18. // Upbit REST API 호출
  19. var candles = await upbit.GetDayCandlesAsync(request.Market, count, ct);
  20. var items = candles
  21. .OrderBy(c => c.CandleDateTimeUtc)
  22. .Select(c => new Response.CandleItem(
  23. c.CandleDateTimeUtc,
  24. c.CandleDateTimeKst,
  25. c.OpeningPrice,
  26. c.HighPrice,
  27. c.LowPrice,
  28. c.TradePrice,
  29. c.Timestamp,
  30. c.CandleAccTradePrice,
  31. c.CandleAccTradeVolume,
  32. c.PrevClosingPrice ?? 0,
  33. c.ChangePrice ?? 0,
  34. c.ChangeRate ?? 0
  35. ))
  36. .ToList();
  37. // Redis 캐시 저장 (5분)
  38. if (items.Count > 0)
  39. {
  40. await cache.SetAsync(cacheKey, items, _cacheExpiry, ct);
  41. }
  42. return new Response(items);
  43. }
  44. }