Skip to content

Commit

Permalink
Probable fix to current DbConnection issues (#11)
Browse files Browse the repository at this point in the history
* Updated InitConnection to check connection state after the resource has been freed

* Fixed _databaseConnection state grabbing

* Added semaphore for InitConnection

* Switched DB connection error log to use `HttpLogger`

* Added catch for Update failure

* Added DbConnection Log

* Re-added event check to prevent deadlock

* Changed DbConnection log to Debug

---------

Co-authored-by: Usman Shafiq <[email protected]>
  • Loading branch information
JulianusIV and DubyaDude authored May 7, 2023
1 parent 47e6a52 commit 70da422
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 11 deletions.
32 changes: 21 additions & 11 deletions src/CookieTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public sealed class CookieTracker : IAsyncDisposable
private readonly Dictionary<Ulid, CachedCookie> _cachedCookies = new();
private readonly NpgsqlConnection _databaseConnection;
private readonly ILogger<CookieTracker> _logger;
private readonly SemaphoreSlim _dbConnectionSemaphore = new(1, 1);
private readonly SemaphoreSlim _semaphore = new(1, 1);
private readonly PeriodicTimer _timer;
private readonly Task _bakingTask;
Expand Down Expand Up @@ -149,6 +150,10 @@ private async Task StartBakingAsync()
HttpLogger.CookieUpdated(_logger, await updateCommand.ExecuteNonQueryAsync(), null);
}
}
catch(Exception exception)
{
HttpLogger.BakingError(_logger, exception);
}
finally
{
_semaphore.Release();
Expand All @@ -171,21 +176,26 @@ private void InitConnection(object? sender, StateChangeEventArgs eventArgs)
return;
}

_semaphore.Wait();
reconnect:
try
_dbConnectionSemaphore.Wait();

while (_databaseConnection.FullState is ConnectionState.Closed or ConnectionState.Broken)
{
_databaseConnection.Open();
foreach (DbCommand command in _databaseCommands.Values)
try
{
command.Prepare();
_databaseConnection.Open();
foreach (DbCommand command in _databaseCommands.Values)
{
command.Prepare();
}
HttpLogger.DbConnection(_logger, null);
}
catch (Exception exception)
{
HttpLogger.DbConnectionError(_logger, exception);
}
}
catch (Exception)
{
goto reconnect;
}
_semaphore.Release();

_dbConnectionSemaphore.Release();
}

private static NpgsqlCommand GetSelectCommand(NpgsqlConnection connection)
Expand Down
3 changes: 3 additions & 0 deletions src/HttpLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public sealed class HttpLogger : IServerCompanion
internal static readonly Action<Microsoft.Extensions.Logging.ILogger, int, string, Exception?> RegisterSlashCommandsFailed = LoggerMessage.Define<int, string>(LogLevel.Error, new EventId(2, "SlashCommands failed to register"), "Failed to register slash commands: {HttpStatusCode} {ReasonPhrase}");
internal static readonly Action<Microsoft.Extensions.Logging.ILogger, int, Exception?> CookieCreated = LoggerMessage.Define<int>(LogLevel.Debug, new EventId(3, "Cookie Database Operation"), "Created {Count:N0} cookies!");
internal static readonly Action<Microsoft.Extensions.Logging.ILogger, int, Exception?> CookieUpdated = LoggerMessage.Define<int>(LogLevel.Debug, new EventId(3, "Cookie Database Operation"), "Updated {Count:N0} cookies!");
internal static readonly Action<Microsoft.Extensions.Logging.ILogger, Exception?> BakingError = LoggerMessage.Define(LogLevel.Error, new EventId(3, "Cookie Database Operation"), "There was an error baking cookies!");
internal static readonly Action<Microsoft.Extensions.Logging.ILogger, Exception?> DbConnection = LoggerMessage.Define(LogLevel.Debug, new EventId(4, "Database"), "Connected to database.");
internal static readonly Action<Microsoft.Extensions.Logging.ILogger, Exception?> DbConnectionError = LoggerMessage.Define(LogLevel.Error, new EventId(4, "Database"), "Failed to connect to database.");

private readonly ILogger<HttpLogger> _logger;

Expand Down

0 comments on commit 70da422

Please sign in to comment.