Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions src/Prima/Services/DbService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

Expand All @@ -13,6 +14,7 @@ public class DbService : IDbService
{
private const string ConnectionString = "mongodb://localhost:27017";
private const string DbName = "PrimaDb";
private const double LockTimeoutSeconds = 30;

// Hide types of the database implementation from callers.
public GlobalConfiguration Config
Expand Down Expand Up @@ -48,9 +50,12 @@ public GlobalConfiguration Config

private readonly ILogger<DbService> _logger;

private readonly SemaphoreSlim _lock;

public DbService(ILogger<DbService> logger)
{
_logger = logger;
_lock = new SemaphoreSlim(80, 80);

var client = new MongoClient(ConnectionString);
var database = client.GetDatabase(DbName);
Expand Down Expand Up @@ -96,11 +101,14 @@ public DbService(ILogger<DbService> logger)
_ephemeralPins.EstimatedDocumentCount());
}

public async Task<DiscordXIVUser?> GetUserByCharacterInfo(string? world, string? characterName)
public Task<DiscordXIVUser?> GetUserByCharacterInfo(string? world, string? characterName)
{
if (characterName == null || world == null) return null;
_logger.LogInformation("Fetching user: ({World}) {CharacterName}", world, characterName);
return await _users.Find(u => u.World == world && u.Name == characterName).FirstOrDefaultAsync();
return WithLock(async () =>
{
if (characterName == null || world == null) return null;
_logger.LogInformation("Fetching user: ({World}) {CharacterName}", world, characterName);
return await _users.Find(u => u.World == world && u.Name == characterName).FirstOrDefaultAsync();
});
}

public async Task SetGlobalConfigurationProperty(string key, string value)
Expand Down Expand Up @@ -426,5 +434,23 @@ public async Task DeleteChannelDescription(ulong channelId)
await _channelDescriptions.DeleteOneAsync(cd => cd.ChannelId == channelId);
}
}

private async Task<T> WithLock<T>(Func<Task<T>> action)
{
if (!await _lock.WaitAsync(TimeSpan.FromSeconds(LockTimeoutSeconds)).ConfigureAwait(false))
{
_logger.LogWarning("Could not acquire database lock");
throw new TimeoutException("Could not acquire database lock");
}

try
{
return await action();
}
finally
{
_lock.Release();
}
}
}
}
Loading