fix(cv-qa): protect import lifecycle races and terminal receipts
This commit is contained in:
@@ -311,6 +311,7 @@ public sealed partial class ProfileCvController : ControllerBase
|
||||
}, HttpContext.RequestAborted);
|
||||
}
|
||||
catch (DbUpdateConcurrencyException) { return Conflict(new { code = "revision_conflict", message = "The career profile changed. Review the import again before accepting." }); }
|
||||
catch (DbUpdateException ex) when (ex.InnerException is MySqlConnector.MySqlException { Number: 1020 }) { return Conflict(new { code = "revision_conflict", message = "The import changed. Review it again before accepting." }); }
|
||||
catch (CareerProjectionException ex) { return BadRequest(ex.Message); }
|
||||
}
|
||||
|
||||
@@ -325,7 +326,12 @@ public sealed partial class ProfileCvController : ControllerBase
|
||||
if (run.Status != "pending_review") return Conflict("This extraction run is not awaiting review.");
|
||||
|
||||
run.Status = "discarded";
|
||||
await _db.SaveChangesAsync(HttpContext.RequestAborted);
|
||||
try { await _db.SaveChangesAsync(HttpContext.RequestAborted); }
|
||||
catch (DbUpdateException ex) when (ex is DbUpdateConcurrencyException || ex.InnerException is MySqlConnector.MySqlException { Number: 1020 })
|
||||
{
|
||||
_db.Entry(run).State = EntityState.Detached;
|
||||
return Conflict("This extraction run changed. Refresh before discarding it.");
|
||||
}
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user