| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- using Application.Abstractions.Messaging;
- using Application.Abstractions.Data;
- using Application.Abstractions.Cache;
- using Application.Abstractions.Crypto;
- using Domain.Entities.Crypto;
- using Microsoft.EntityFrameworkCore;
- namespace Application.Features.Admin.Crypto.List.Sync;
- public sealed class Handler(IAppDbContext db, IUpbitClient upbit, ICacheService cache) : ICommandHandler<Command, Response>
- {
- public async Task<Response> Handle(Command request, CancellationToken ct)
- {
- var allMarkets = await upbit.GetMarketsAsync(ct);
- if (allMarkets.Count == 0)
- {
- throw new InvalidOperationException("Upbit API에서 마켓 데이터를 가져오지 못했습니다.");
- }
- var dbCoins = await db.Coin.Include(c => c.CoinMarket).ToListAsync(ct);
- var dbCoinMap = dbCoins.ToDictionary(c => c.Symbol, c => c, StringComparer.OrdinalIgnoreCase);
- var upbitSymbols = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
- int created = 0;
- int updated = 0;
- int delisted = 0;
- // 심볼별 첫 마켓에서 Coin 생성/갱신
- foreach (var market in allMarkets)
- {
- var symbol = market.Market.Split('-')[1];
- if (!upbitSymbols.Add(symbol))
- {
- continue;
- }
- if (dbCoinMap.TryGetValue(symbol, out var existing))
- {
- existing.SyncUpdate(market.KoreanName, market.EnglishName, market.MarketEvent.Warning);
- updated++;
- }
- else
- {
- var coin = Coin.SyncFromUpbit(symbol, market.KoreanName, market.EnglishName, market.MarketEvent.Warning);
- db.Coin.Add(coin);
- dbCoinMap[symbol] = coin;
- created++;
- }
- }
- // SaveChanges로 신규 코인 ID 확정
- await db.SaveChangesAsync(ct);
- // 거래쌍 동기화 (CoinMarket)
- foreach (var market in allMarkets)
- {
- var symbol = market.Market.Split('-')[1];
- if (!dbCoinMap.TryGetValue(symbol, out var coin))
- {
- continue;
- }
- if (!coin.CoinMarket.Any(m => m.Market.Equals(market.Market, StringComparison.OrdinalIgnoreCase)))
- {
- db.CoinMarket.Add(new CoinMarket { CoinID = coin.ID, Market = market.Market.ToUpper() });
- }
- }
- // 상폐 처리
- foreach (var coin in dbCoins)
- {
- if (!upbitSymbols.Contains(coin.Symbol) && !coin.IsDelisted)
- {
- coin.MarkDelisted();
- delisted++;
- }
- }
- await db.SaveChangesAsync(ct);
- await cache.RemoveByPrefixAsync("crypto:", ct);
- return new Response(created, updated, delisted);
- }
- }
|