using System.Data.Common;
using Microsoft.EntityFrameworkCore.Diagnostics;
namespace DodoSSH.Api.Tests;
///
/// Fails the next commit the way a connection dropped on the way to the server would, when asked to.
///
///
/// Before the commit reaches the database, so the transaction is rolled back — which is what a lost commit
/// looks like from the server's side — and with a , which the retrying
/// execution strategy treats as transient. That is the only way to watch a retry happen against a real
/// database, and the retry is the thing worth watching: see FreshAttempts.
///
internal sealed class FlakyCommits : DbTransactionInterceptor
{
private int armed;
private int failed;
/// How many commits this has failed.
internal int Failed => Volatile.Read(ref failed);
/// Makes the next commit, whoever's it is, fail once.
internal void FailNextCommit() => Interlocked.Exchange(ref armed, 1);
///
public override ValueTask TransactionCommittingAsync(
DbTransaction transaction,
TransactionEventData eventData,
InterceptionResult result,
CancellationToken cancellationToken = default)
{
if (Interlocked.Exchange(ref armed, 0) == 1)
{
Interlocked.Increment(ref failed);
throw new TimeoutException("The commit was lost on its way to the server.");
}
return base.TransactionCommittingAsync(transaction, eventData, result, cancellationToken);
}
}