fix: implement exponential backoff strategy for concurrency exceptions in SaveChangesAsync
This commit is contained in:
@@ -352,10 +352,17 @@ public class JellyfinDbContext(DbContextOptions<JellyfinDbContext> options, ILog
|
|||||||
}
|
}
|
||||||
catch (DbUpdateConcurrencyException ex)
|
catch (DbUpdateConcurrencyException ex)
|
||||||
{
|
{
|
||||||
// When marking items as played in quick succession, concurrency conflicts can occur.
|
// Concurrency conflicts can occur when marking items as played in quick succession.
|
||||||
// To resolve this, we'll reload the conflicting entities from the database and retry.
|
// To resolve this, we'll retry the operation with an exponential backoff strategy.
|
||||||
logger.LogWarning(ex, "Concurrency exception, retrying operation.");
|
logger.LogWarning(ex, "Concurrency exception, retrying operation with exponential backoff.");
|
||||||
|
|
||||||
|
var maxRetries = 3;
|
||||||
|
var delay = TimeSpan.FromMilliseconds(100);
|
||||||
|
|
||||||
|
for (var i = 0; i < maxRetries; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
foreach (var entry in ex.Entries)
|
foreach (var entry in ex.Entries)
|
||||||
{
|
{
|
||||||
// Reload the entity from the database to get the latest version
|
// Reload the entity from the database to get the latest version
|
||||||
@@ -365,6 +372,17 @@ public class JellyfinDbContext(DbContextOptions<JellyfinDbContext> options, ILog
|
|||||||
// Retry saving changes after resolving conflicts
|
// Retry saving changes after resolving conflicts
|
||||||
return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken).ConfigureAwait(false);
|
return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
catch (DbUpdateConcurrencyException retryEx) when (i < maxRetries - 1)
|
||||||
|
{
|
||||||
|
logger.LogWarning(retryEx, "Concurrency exception on retry {RetryCount}, delaying for {Delay}ms.", i + 1, delay.TotalMilliseconds);
|
||||||
|
await Task.Delay(delay, cancellationToken).ConfigureAwait(false);
|
||||||
|
delay *= 2; // Exponential backoff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all retries fail, rethrow the last exception
|
||||||
|
throw;
|
||||||
|
}
|
||||||
catch (DbUpdateException ex)
|
catch (DbUpdateException ex)
|
||||||
{
|
{
|
||||||
// Check if it's a constraint violation (works across all database providers)
|
// Check if it's a constraint violation (works across all database providers)
|
||||||
|
|||||||
Reference in New Issue
Block a user