fix(site-call-audit): an unknown-status row no longer aborts the rest of a batched page (review 2026-10-21 06/PERF-2 follow-up)

This commit is contained in:
Joseph Doherty
2026-10-22 09:49:54 -04:00
parent 5f7f889a96
commit 46ab5594ec
2 changed files with 60 additions and 5 deletions
@@ -196,19 +196,40 @@ public class SiteCallAuditRepository : ISiteCallAuditRepository
// rethrown at the end, so the caller sees the same exception the old per-row
// loop surfaced (and keeps its cursor), minus the collateral of the rows behind it.
System.Runtime.ExceptionServices.ExceptionDispatchInfo? firstFailure = null;
for (var offset = 0; offset < siteCalls.Count; offset += UpsertManyChunkSize)
// Rows UpsertAsync would reject before touching the database (a null row, an
// unknown status) are validated up front and SKIPPED with their failure captured,
// so one malformed row cannot stop the rest of the page from applying.
var valid = new List<(SiteCall Row, int Rank)>(siteCalls.Count);
foreach (var siteCall in siteCalls)
{
var chunk = siteCalls.Skip(offset).Take(UpsertManyChunkSize).ToList();
try
{
if (siteCall is null)
{
throw new ArgumentException("A null SiteCall row was supplied.", nameof(siteCalls));
}
valid.Add((siteCall, GetRankOrThrow(siteCall.Status)));
}
catch (ArgumentException invalid)
{
firstFailure ??= System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(invalid);
}
}
for (var offset = 0; offset < valid.Count; offset += UpsertManyChunkSize)
{
var chunk = valid.Skip(offset).Take(UpsertManyChunkSize).Select(v => v.Row).ToList();
var ranks = valid.Skip(offset).Take(UpsertManyChunkSize).Select(v => v.Rank).ToList();
var sql = new System.Text.StringBuilder();
var parameters = new List<object>(chunk.Count * 15);
for (var i = 0; i < chunk.Count; i++)
{
var siteCall = chunk[i] ?? throw new ArgumentException("A null SiteCall row was supplied.", nameof(siteCalls));
var rank = GetRankOrThrow(siteCall.Status);
var siteCall = chunk[i];
var suffix = "_" + i.ToString(System.Globalization.CultureInfo.InvariantCulture);
sql.AppendLine(SuffixParameters(InsertIfAbsentSql, suffix));
sql.AppendLine(SuffixParameters(MonotonicUpdateSql, suffix));
foreach (SqlParameter p in BuildUpsertParameters(siteCall, siteCall.TrackedOperationId.Value.ToString("D"), rank))
foreach (SqlParameter p in BuildUpsertParameters(siteCall, siteCall.TrackedOperationId.Value.ToString("D"), ranks[i]))
{
p.ParameterName += suffix;
parameters.Add(p);