using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.Stocks.Watch.IsWatching; /// 회원이 관심 등록한 코드 집합을 조회해 요청 코드별 true/false 맵을 반환 (IsFollowing 패턴). internal sealed class Handler(IAppDbContext db) : IQueryHandler { // 방어적 상한 — 엔드포인트에서도 Take(100) 하지만 Handler 계층 자체도 무방비가 되지 않도록 (GetQuotes 패턴) public const int MaxCodes = 100; public async Task Handle(Query request, CancellationToken ct) { var codes = request.Codes.Select(c => c.Trim()).Where(c => c.Length > 0).Distinct().Take(MaxCodes).ToArray(); if (codes.Length == 0) { return new Response { Map = new Dictionary() }; } var watched = await db.StockWatch.AsNoTracking() .Where(w => w.MemberID == request.MemberID && codes.Contains(w.StockCode)) .Select(w => w.StockCode) .ToListAsync(ct); var watchedSet = watched.ToHashSet(); var map = codes.ToDictionary(c => c, c => watchedSet.Contains(c)); return new Response { Map = map }; } }