#nullable enable
using MMoneyCoderSharp.Data;
using MBN_STOCK_WEBVIEW.Infrastructure;
using MySqlConnector;
using Oracle.ManagedDataAccess.Client;
namespace MBN_STOCK_WEBVIEW.DbWriteSmoke;
///
/// Emits only a provider/type classification. Messages, SQL, credentials,
/// identifiers, and values deliberately never cross this boundary.
///
internal static class RedactedDatabaseFailureClassifier
{
internal static string Classify(Exception exception)
{
ArgumentNullException.ThrowIfNull(exception);
foreach (var current in Flatten(exception))
{
switch (current)
{
case OracleException oracle:
return "Oracle-" + oracle.Number.ToString(
System.Globalization.CultureInfo.InvariantCulture);
case MySqlException mariaDb:
return "MariaDb-" + ((int)mariaDb.ErrorCode).ToString(
System.Globalization.CultureInfo.InvariantCulture);
case DatabaseOperationException database:
return database.DataSource + "-" +
(database.ProviderErrorCode?.ToString(
System.Globalization.CultureInfo.InvariantCulture) ?? "none");
case ManualFinancialMutationRejectedException rejected:
return "ManualRejected-" + rejected.Reason;
case OperatorCatalogConflictException conflict:
return "CatalogConflict-" + conflict.Kind + "-" + conflict.CommandKind;
}
}
return exception.GetType().Name;
}
private static IEnumerable Flatten(Exception exception)
{
var pending = new Stack();
var visited = new HashSet(ReferenceEqualityComparer.Instance);
pending.Push(exception);
while (pending.TryPop(out var current) && visited.Add(current))
{
yield return current;
if (current is AggregateException aggregate)
{
foreach (var inner in aggregate.InnerExceptions.Reverse())
{
pending.Push(inner);
}
}
else if (current.InnerException is not null)
{
pending.Push(current.InnerException);
}
}
}
}