diff --git a/src/Prima.Application/Commands/FFXIV/DelubrumReginae/CommandBatchActorMapper.cs b/src/Prima.Application/Commands/FFXIV/DelubrumReginae/CommandBatchActorMapper.cs index 4be7fb8..79a3b9d 100644 --- a/src/Prima.Application/Commands/FFXIV/DelubrumReginae/CommandBatchActorMapper.cs +++ b/src/Prima.Application/Commands/FFXIV/DelubrumReginae/CommandBatchActorMapper.cs @@ -16,17 +16,32 @@ public CommandBatchActorMapper(IDbService db) public async Task> GetUsersFromActors( IEnumerable actors) { + // Map to dict of actor ID to potential DB user var potentialUsers = actors.ToDictionary(a => a.Id, a => a) - .Select(async kvp => new + .Select(kvp => new { ActorId = kvp.Key, - User = await _db.GetUserByCharacterInfo(kvp.Value.Server, kvp.Value.Name), + User = new PotentialDbUser(kvp.Value.Name, kvp.Value.Server), }) .ToList(); - var potentialUsersAwaited = await Task.WhenAll(potentialUsers); - var users = potentialUsersAwaited - .Where(kvp => kvp.User != null) - .ToDictionary(kvp => kvp.ActorId, kvp => kvp.User); + + // Dedupe by world/name to minimize DB queries since the same user can show up as many actors + var dedupedUsersForQuery = potentialUsers.Select(kvp => kvp.User) + .DistinctBy(u => u.ToString()) + .Select(u => _db.GetUserByCharacterInfo(u.World, u.Name)) + .ToList(); + var dedupedUsersForQueryAwaited = await Task.WhenAll(dedupedUsersForQuery); + + // Reshape to dict of potential DB user to real DB user + var dedupedUsersForQueryDict = dedupedUsersForQueryAwaited + .Where(u => u != null) + .ToDictionary(u => new PotentialDbUser(u.Name, u.World).ToString()); + + // Build dict of actor ID to real DB user + var users = potentialUsers + .ToDictionary( + kvp => kvp.ActorId, + kvp => dedupedUsersForQueryDict.GetValueOrDefault(kvp.User.ToString())); return users; } } \ No newline at end of file diff --git a/src/Prima/Game/FFXIV/PotentialDbUser.cs b/src/Prima/Game/FFXIV/PotentialDbUser.cs index e1da631..d4b34cc 100644 --- a/src/Prima/Game/FFXIV/PotentialDbUser.cs +++ b/src/Prima/Game/FFXIV/PotentialDbUser.cs @@ -12,5 +12,10 @@ public PotentialDbUser(string name, string world, DiscordXIVUser? user = null) World = world; User = user; } + + public override string ToString() + { + return $"({World}) {Name}"; + } } } \ No newline at end of file diff --git a/src/Prima/Services/DbService.cs b/src/Prima/Services/DbService.cs index fe0af17..47a7c88 100644 --- a/src/Prima/Services/DbService.cs +++ b/src/Prima/Services/DbService.cs @@ -14,7 +14,7 @@ public class DbService : IDbService { private const string ConnectionString = "mongodb://localhost:27017"; private const string DbName = "PrimaDb"; - private const double LockTimeoutSeconds = 30; + private const double LockTimeoutSeconds = 120; // Hide types of the database implementation from callers. public GlobalConfiguration Config