Introduce artificial delay into SQLite on DEBUG.
This makes SQLite DB ops properly asynchronous (instead of synchronously completing tasks). This makes them more consistent with postgres and means that any deadlock bugs introduced the next time somebody does .Result will be caught on SQLite too.
This commit is contained in:
@@ -31,11 +31,14 @@ namespace Content.Server.Database
|
||||
private readonly Task _dbReadyTask;
|
||||
private readonly SqliteServerDbContext _prefsCtx;
|
||||
|
||||
private int _msDelay;
|
||||
|
||||
public ServerDbSqlite(DbContextOptions<SqliteServerDbContext> options)
|
||||
{
|
||||
_prefsCtx = new SqliteServerDbContext(options);
|
||||
|
||||
if (IoCManager.Resolve<IConfigurationManager>().GetCVar(CCVars.DatabaseSynchronous))
|
||||
var cfg = IoCManager.Resolve<IConfigurationManager>();
|
||||
if (cfg.GetCVar(CCVars.DatabaseSynchronous))
|
||||
{
|
||||
_prefsCtx.Database.Migrate();
|
||||
_dbReadyTask = Task.CompletedTask;
|
||||
@@ -44,6 +47,8 @@ namespace Content.Server.Database
|
||||
{
|
||||
_dbReadyTask = Task.Run(() => _prefsCtx.Database.Migrate());
|
||||
}
|
||||
|
||||
cfg.OnValueChanged(CCVars.DatabaseSqliteDelay, v => _msDelay = v, true);
|
||||
}
|
||||
|
||||
#region Ban
|
||||
@@ -488,6 +493,9 @@ namespace Content.Server.Database
|
||||
private async Task<DbGuardImpl> GetDbImpl()
|
||||
{
|
||||
await _dbReadyTask;
|
||||
if (_msDelay > 0)
|
||||
await Task.Delay(_msDelay);
|
||||
|
||||
await _prefsSemaphore.WaitAsync();
|
||||
|
||||
return new DbGuardImpl(this);
|
||||
|
||||
@@ -242,6 +242,24 @@ namespace Content.Shared.CCVar
|
||||
public static readonly CVarDef<string> DatabaseSqliteDbPath =
|
||||
CVarDef.Create("database.sqlite_dbpath", "preferences.db", CVar.SERVERONLY);
|
||||
|
||||
/// <summary>
|
||||
/// Milliseconds to asynchronously delay all SQLite database acquisitions with.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Defaults to 1 on DEBUG, 0 on RELEASE.
|
||||
/// This is intended to help catch .Result deadlock bugs that only happen on postgres
|
||||
/// (because SQLite is not actually asynchronous normally)
|
||||
/// </remarks>
|
||||
public static readonly CVarDef<int> DatabaseSqliteDelay =
|
||||
CVarDef.Create("database.sqlite_delay", DefaultSqliteDelay, CVar.SERVERONLY);
|
||||
|
||||
#if DEBUG
|
||||
private const int DefaultSqliteDelay = 1;
|
||||
#else
|
||||
private const int DefaultSqliteDelay = 0;
|
||||
#endif
|
||||
|
||||
|
||||
public static readonly CVarDef<string> DatabasePgHost =
|
||||
CVarDef.Create("database.pg_host", "localhost", CVar.SERVERONLY);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user