/// <summary>
/// Repeatedly attempts to rollback, to support timeout-triggered rollbacks that occur while the connection is busy.
/// </summary>
void RollbackLocal()
{
Debug.Assert(_connector != null, "No connector");
Debug.Assert(_localTx != null, "No local transaction");
var attempt = 0;
while (true)
{
try
{
_localTx.Rollback();
return;
}
catch (NpgsqlOperationInProgressException)
{
// This really shouldn't be necessary, but just in case
if (attempt++ == MaximumRollbackAttempts)
{
throw new Exception($"Could not roll back after {MaximumRollbackAttempts} attempts, aborting. Transaction is in an unknown state.");
}
Log.Logger.LogWarning(NpgsqlEventId.ConnectionInUseDuringRollback, "[{ConnectorId}] Connection in use while trying to rollback, will cancel and retry (localid={TransactionId}", _connector.Id, _txId);
_connector.CancelRequest();
// Cancellations are asynchronous, give it some time
Thread.Sleep(500);
}
}
}