Handler.cs 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Domain.Entities.Developers.ValueObject;
  4. using Microsoft.EntityFrameworkCore;
  5. namespace Application.Features.Admin.Developers.GlobalStats;
  6. internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
  7. {
  8. private const int DefaultDays = 7;
  9. private const int MaxDays = 90;
  10. public async Task<Response> Handle(Query request, CancellationToken ct)
  11. {
  12. var days = Math.Clamp(request.Days <= 0 ? DefaultDays : request.Days, 1, MaxDays);
  13. var since = DateTime.UtcNow.AddDays(-days);
  14. var totalApps = await db.ApiApplication.CountAsync(ct);
  15. var activeApps = await db.ApiApplication.CountAsync(c => c.Status == ApplicationStatus.Active, ct);
  16. var pendingApps = await db.ApiApplication.CountAsync(c => c.Status == ApplicationStatus.Pending, ct);
  17. var totalPats = await db.ApiPersonalAccessToken.CountAsync(ct);
  18. var activePats = await db.ApiPersonalAccessToken.CountAsync(c => c.RevokedAt == null, ct);
  19. var daily = await db.ApiRequestLog
  20. .Where(c => c.RequestedAt >= since)
  21. .GroupBy(c => DateOnly.FromDateTime(c.RequestedAt))
  22. .Select(g => new DailyStat(
  23. g.Key,
  24. g.Count(),
  25. g.Count(c => c.StatusCode >= 400)
  26. ))
  27. .OrderBy(c => c.Date)
  28. .ToListAsync(ct);
  29. return new Response(totalApps, activeApps, pendingApps, totalPats, activePats, daily);
  30. }
  31. }