C# Cosmos DB-某些记录无法插入

C# Cosmos DB-某些记录无法插入,c#,azure-cosmosdb,C#,Azure Cosmosdb,我们有一个递归函数,用于将记录批量插入Cosmos。 在运行长时间迁移以插入许多记录时,似乎有些记录未能插入,但我们无法从日志中看出原因。 我的假设是,某一类型的状态代码没有在应该重试的时候重试,或者某个状态代码正在悄无声息地失败 有人能告诉我们是什么原因导致记录失败而不被记录/重试吗 AllowBulkExecution=true在创建传递给下面代码的容器时设置 public async Task<bool> TryBulkInsertAsync<T>(List<

我们有一个递归函数,用于将记录批量插入Cosmos。 在运行长时间迁移以插入许多记录时,似乎有些记录未能插入,但我们无法从日志中看出原因。 我的假设是,某一类型的状态代码没有在应该重试的时候重试,或者某个状态代码正在悄无声息地失败

有人能告诉我们是什么原因导致记录失败而不被记录/重试吗

AllowBulkExecution=true
在创建传递给下面代码的容器时设置

public async Task<bool> TryBulkInsertAsync<T>(List<T> audits, int retryAttempts, TimeSpan retryDelay, int currentAttempt = 0, Container container = null) where T : BaseCosmosModel
    {
        if (currentAttempt > retryAttempts)
        {
            _logger.LogError($"Failed number of max retries ${retryAttempts}");
            return false;
        }

        if (container == null)
        {
            container = _cosmosContainerFactory.BuildCosmosContainer<T>();
        }
        
        var attemptAudits = audits.Select(a => new CosmosInsertAttempt<T>
        {
            Audit = a,
            RunningTask = container.CreateItemAsync(a)
        }).ToList();

        try
        {
            await Task.WhenAll(attemptAudits.Select(a => a.RunningTask));

            var failedAudits = attemptAudits.Where(a =>
                a.RunningTask.Result.StatusCode == HttpStatusCode.TooManyRequests ||
                a.RunningTask.Result.StatusCode == HttpStatusCode.PreconditionFailed ||
                a.RunningTask.Result.StatusCode == HttpStatusCode.RequestTimeout ||
                a.RunningTask.Result.StatusCode == HttpStatusCode.ServiceUnavailable
            ).Select(a => a.Audit).ToList();

            var nonRetryableAudits = attemptAudits.Where(a =>
                !failedAudits.Contains(a.Audit) && (a.RunningTask.Result.StatusCode < (HttpStatusCode) 200 ||
                a.RunningTask.Result.StatusCode > (HttpStatusCode) 299));

            foreach (var audit in nonRetryableAudits)
            {
                _logger.LogError("Audit failed to bulk insert with non-retryable status code {cosmosAuditInsert}", audit.Audit);
            }

            if (failedAudits.Count > 0)
            {
                _logger.LogError("Retrying bulk insert from incorrect status code but no error, count: {retrySize}", failedAudits.Count);
                return await TryBulkInsertAsync(failedAudits, retryAttempts, retryDelay, currentAttempt + 1, container);
            }

            return true;
        }
        catch (Exception)
        {
            await Task.Delay(retryDelay);
            var failedAuditsWithException = attemptAudits
                .Where(a => a.RunningTask.Exception != null)
                .Select(a => a.Audit).ToList();

            var failedAuditsWithBadStatusCode = attemptAudits.Where(a =>
            (
                a.RunningTask.Exception == null && a.RunningTask.Result != null &&
                (a.RunningTask.Result.StatusCode == HttpStatusCode.TooManyRequests ||
                 a.RunningTask.Result.StatusCode == HttpStatusCode.PreconditionFailed ||
                 a.RunningTask.Result.StatusCode == HttpStatusCode.RequestTimeout ||
                 a.RunningTask.Result.StatusCode == HttpStatusCode.ServiceUnavailable)
            )).Select(a => a.Audit).ToList();

            if (failedAuditsWithBadStatusCode.Any())
            {
                _logger.LogError("Retrying bulk insert from incorrect status code but no error (some have exceptions), count: {retrySize}", failedAuditsWithBadStatusCode.Count);
            }

            var failedAudits = failedAuditsWithException.Concat(failedAuditsWithBadStatusCode).ToList();

            var nonRetryableAudits = attemptAudits.Where(a =>
                !failedAudits.Contains(a.Audit) && a.RunningTask.Exception == null && (a.RunningTask.Result.StatusCode < (HttpStatusCode)200 ||
                                                    a.RunningTask.Result.StatusCode > (HttpStatusCode)299));

            foreach (var audit in nonRetryableAudits)
            {
                _logger.LogError("Audit failed to bulk insert with non-retryable status code {cosmosAuditInsert}", audit.Audit);
            }

            if (failedAudits.Count > 0)
            {
                _logger.LogError("Retrying bulk insert {failedAuditCount}", failedAudits.Count);
                return await TryBulkInsertAsync(failedAudits, retryAttempts, retryDelay, currentAttempt + 1, container);
            }
            return true;
        }
    }
public async Task TryBulkInsertAsync(列表审核,int-retryAttempts,TimeSpan-retryDelay,int-currentAttempty=0,Container-Container=null),其中T:basecosmodel
{
如果(当前尝试>重试尝试)
{
_logger.LogError($“失败的最大重试次数${retryAttempts}”);
返回false;
}
if(容器==null)
{
容器=_cosmosContainerFactory.BuildCosmosContainer();
}
var attemptAudits=audits.Select(a=>newcosmosinservatattent
{
审计=a,
RunningTask=container.CreateItemAsync(a)
}).ToList();
尝试
{
wait Task.WhenAll(attemptAudits.Select(a=>a.RunningTask));
var failedAudits=attemptAudits.Where(a=>
a、 RunningTask.Result.StatusCode==HttpStatusCode.TooManyRequests||
a、 RunningTask.Result.StatusCode==HttpStatusCode.PremissionFailed||
a、 RunningTask.Result.StatusCode==HttpStatusCode.RequestTimeout||
a、 RunningTask.Result.StatusCode==HttpStatusCode.ServiceUnavailable
).Select(a=>a.Audit).ToList();
var nonRetryableAudits=attemptAudits.Where(a=>
!failedAudits.Contains(a.Audit)和&(a.RunningTask.Result.StatusCode)<(HttpStatusCode)200||
a、 RunningTask.Result.StatusCode>(HttpStatusCode)299);
foreach(非风险值审计中的风险值审计)
{
_logger.LogError(“Audit无法大容量插入,状态代码为{cosmosAuditInsert}”,Audit.Audit);
}
如果(failedAudits.Count>0)
{
_logger.LogError(“从错误的状态代码重试大容量插入,但没有错误,计数:{retrySize}”,failedAudits.count);
return wait-TryBulkInsertAsync(失败的音频、重试尝试、重试延迟、当前尝试+1、容器);
}
返回true;
}
捕获(例外)
{
等待任务延迟(retryDelay);
var failedAuditsWithException=attemptAudits
.Where(a=>a.RunningTask.Exception!=null)
.Select(a=>a.Audit).ToList();
var failedAuditsWithBadStatusCode=attemptAudits。其中(a=>
(
a、 RunningTask.Exception==null&&a.RunningTask.Result!=null&&
(a.RunningTask.Result.StatusCode==HttpStatusCode.TooManyRequests||
a、 RunningTask.Result.StatusCode==HttpStatusCode.PremissionFailed||
a、 RunningTask.Result.StatusCode==HttpStatusCode.RequestTimeout||
a、 RunningTask.Result.StatusCode==HttpStatusCode.ServiceUnavailable)
)).Select(a=>a.Audit).ToList();
if(failedAuditsWithBadStatusCode.Any())
{
_logger.LogError(“从不正确的状态代码重试大容量插入,但没有错误(有些有例外),计数:{retrySize}”,failedAuditsWithBadStatusCode.count);
}
var failedAudits=failedAuditsWithException.Concat(failedAuditsWithBadStatusCode.ToList();
var nonRetryableAudits=attemptAudits.Where(a=>
!failedAudits.Contains(a.Audit)和&a.RunningTask.Exception==null和&a.RunningTask.Result.StatusCode<(HttpStatusCode)200||
a、 RunningTask.Result.StatusCode>(HttpStatusCode)299);
foreach(非风险值审计中的风险值审计)
{
_logger.LogError(“Audit无法大容量插入,状态代码为{cosmosAuditInsert}”,Audit.Audit);
}
如果(failedAudits.Count>0)
{
_LogError(“重试大容量插入{failedAuditCount}”,failedAudits.Count);
return wait-TryBulkInsertAsync(失败的音频、重试尝试、重试延迟、当前尝试+1、容器);
}
返回true;
}
}

请分享一个。我的直觉是堆栈溢出,因为你的函数是递归的。因此,在这种情况下,日志记录可能不起作用。为什么要重试?您正在运行Async,因此可以在实际保存数据之前检查是否发生了故障。您正在尝试保存数据库中已有的数据,但由于正在写入重复数据而失败。当您有主键时,您只能使用相同的主键写入一项。因此,重试会导致问题,因为您正在使用相同的密钥保存两个项目。@jdweng正在等待插入请求等待任务。whalll(attemptAudits.Select(a=>a.RunningTask));
var nonRetryableAudits=attemptAudits。其中(
catch中的代码让我觉得很奇怪。名称表明它不可重试,但我看不到任何证据表明您实际上没有重试它。另外,当前面几行代码检查
Result
是否为
null
时,它会读取
a.RunningTask.Result.StatusCode>属性(这意味着它可以为
null
)然而,
null
检查并没有在这里完成(这意味着您可能正在catch中抛出异常?)。