using Microsoft.EntityFrameworkCore; using NodaTime; using Quartz; using DysonNetwork.Drive.Auth; using DysonNetwork.Drive.Models; using Microsoft.Extensions.DependencyInjection; using DysonNetwork.Common.Models; using System; namespace DysonNetwork.Drive.Handlers; public class LastActiveFlushHandler(IServiceProvider serviceProvider) : IFlushHandler { public async Task FlushAsync(IReadOnlyList items) { using var scope = serviceProvider.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); // Remove duplicates by grouping on (sessionId, accountId), taking the most recent SeenAt var distinctItems = items .GroupBy(x => (SessionId: x.SessionId, AccountId: x.AccountId)) .Select(g => g.OrderByDescending(x => x.SeenAt).First()) .ToList(); // Build dictionaries so we can match session/account IDs to their new "last seen" timestamps var sessionIdMap = distinctItems .GroupBy(x => x.SessionId) .ToDictionary(g => Guid.Parse(g.Key), g => g.Last().SeenAt); var accountIdMap = distinctItems .GroupBy(x => x.AccountId) .ToDictionary(g => Guid.Parse(g.Key), g => g.Last().SeenAt); // Update sessions using native EF Core ExecuteUpdateAsync foreach (var kvp in sessionIdMap) { await db.AuthSessions .Where(s => s.Id == kvp.Key) .ExecuteUpdateAsync(s => s.SetProperty(x => x.LastGrantedAt, kvp.Value)); } // Update account profiles using native EF Core ExecuteUpdateAsync foreach (var kvp in accountIdMap) { await db.AccountProfiles .Where(a => a.AccountId == kvp.Key) .ExecuteUpdateAsync(a => a.SetProperty(x => x.LastSeenAt, kvp.Value)); } } } public class LastActiveFlushJob(FlushBufferService fbs, LastActiveFlushHandler hdl) : IJob { public async Task Execute(IJobExecutionContext context) { await fbs.FlushAsync(hdl); } }