mirror of
https://github.com/bitwarden/server.git
synced 2025-12-11 04:34:37 -06:00
Configure EF to gracefully handle deadlocks
This commit is contained in:
parent
f5393fa643
commit
1c03ef110e
@ -47,22 +47,34 @@ public static class EntityFrameworkServiceCollectionExtensions
|
||||
{
|
||||
if (provider == SupportedDatabaseProviders.Postgres)
|
||||
{
|
||||
options.UseNpgsql(connectionString, b => b.MigrationsAssembly("PostgresMigrations"));
|
||||
options.UseNpgsql(connectionString, b =>
|
||||
{
|
||||
b.MigrationsAssembly("PostgresMigrations");
|
||||
b.EnableRetryOnFailure();
|
||||
});
|
||||
// Handle NpgSql Legacy Support for `timestamp without timezone` issue
|
||||
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
||||
}
|
||||
else if (provider == SupportedDatabaseProviders.MySql)
|
||||
{
|
||||
options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString),
|
||||
b => b.MigrationsAssembly("MySqlMigrations"));
|
||||
b =>
|
||||
{
|
||||
b.MigrationsAssembly("MySqlMigrations");
|
||||
b.EnableRetryOnFailure();
|
||||
});
|
||||
}
|
||||
else if (provider == SupportedDatabaseProviders.Sqlite)
|
||||
{
|
||||
// SQLite doesn't support EnableRetryOnFailure
|
||||
options.UseSqlite(connectionString, b => b.MigrationsAssembly("SqliteMigrations"));
|
||||
}
|
||||
else if (provider == SupportedDatabaseProviders.SqlServer)
|
||||
{
|
||||
options.UseSqlServer(connectionString);
|
||||
options.UseSqlServer(connectionString, b =>
|
||||
{
|
||||
b.EnableRetryOnFailure();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -826,6 +826,11 @@ public class CollectionRepository : Repository<Core.Entities.Collection, Collect
|
||||
using var scope = ServiceScopeFactory.CreateScope();
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
|
||||
// Use EF's execution strategy to handle transient failures (including deadlocks)
|
||||
var strategy = dbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
return await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
// Use SERIALIZABLE isolation level to prevent race conditions during concurrent calls
|
||||
using var transaction = await dbContext.Database.BeginTransactionAsync(System.Data.IsolationLevel.Serializable);
|
||||
|
||||
@ -890,6 +895,7 @@ public class CollectionRepository : Repository<Core.Entities.Collection, Collect
|
||||
await transaction.RollbackAsync();
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<HashSet<Guid>> GetOrgUserIdsWithDefaultCollectionAsync(DatabaseContext dbContext, Guid organizationId)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user