fix: avoid feedback screenshot concurrency save
This commit is contained in:
@@ -38,8 +38,7 @@ public class AttachMyFeedbackScreenshotHandler(
|
||||
Guid reporterUserId = User.GetUserId();
|
||||
|
||||
FeedbackReport? report = await dbContext.FeedbackReports
|
||||
.Include(candidate => candidate.Tags)
|
||||
.Include(candidate => candidate.Screenshot)
|
||||
.AsNoTracking()
|
||||
.SingleOrDefaultAsync(
|
||||
candidate => candidate.Id == id && candidate.ReporterUserId == reporterUserId,
|
||||
ct);
|
||||
@@ -50,7 +49,11 @@ public class AttachMyFeedbackScreenshotHandler(
|
||||
return;
|
||||
}
|
||||
|
||||
if (report.Screenshot is not null)
|
||||
bool hasScreenshot = await dbContext.FeedbackScreenshots
|
||||
.AsNoTracking()
|
||||
.AnyAsync(candidate => candidate.FeedbackReportId == report.Id, ct);
|
||||
|
||||
if (hasScreenshot)
|
||||
{
|
||||
AddError("A screenshot is already attached to this feedback report.");
|
||||
await SendErrorsAsync(StatusCodes.Status409Conflict, ct);
|
||||
@@ -94,7 +97,7 @@ public class AttachMyFeedbackScreenshotHandler(
|
||||
}
|
||||
|
||||
DateTimeOffset now = DateTimeOffset.UtcNow;
|
||||
report.Screenshot = new FeedbackScreenshot
|
||||
FeedbackScreenshot screenshot = new()
|
||||
{
|
||||
Id = screenshotId,
|
||||
FeedbackReportId = report.Id,
|
||||
@@ -105,10 +108,45 @@ public class AttachMyFeedbackScreenshotHandler(
|
||||
BlobName = blobName,
|
||||
CreatedAt = now,
|
||||
};
|
||||
report.LastActivityAt = now;
|
||||
|
||||
await using Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction transaction =
|
||||
await dbContext.Database.BeginTransactionAsync(ct);
|
||||
|
||||
dbContext.FeedbackScreenshots.Add(screenshot);
|
||||
try
|
||||
{
|
||||
await dbContext.SaveChangesAsync(ct);
|
||||
await SendOkAsync(report.ToDto(), ct);
|
||||
}
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
await transaction.RollbackAsync(ct);
|
||||
AddError("A screenshot is already attached to this feedback report.");
|
||||
await SendErrorsAsync(StatusCodes.Status409Conflict, ct);
|
||||
return;
|
||||
}
|
||||
|
||||
int updatedRows = await dbContext.FeedbackReports
|
||||
.Where(candidate => candidate.Id == report.Id && candidate.ReporterUserId == reporterUserId)
|
||||
.ExecuteUpdateAsync(
|
||||
setters => setters.SetProperty(candidate => candidate.LastActivityAt, now),
|
||||
ct);
|
||||
|
||||
if (updatedRows == 0)
|
||||
{
|
||||
await transaction.RollbackAsync(ct);
|
||||
await SendNotFoundAsync(ct);
|
||||
return;
|
||||
}
|
||||
|
||||
await transaction.CommitAsync(ct);
|
||||
|
||||
FeedbackReport responseReport = await dbContext.FeedbackReports
|
||||
.AsNoTracking()
|
||||
.Include(candidate => candidate.Tags)
|
||||
.Include(candidate => candidate.Screenshot)
|
||||
.SingleAsync(candidate => candidate.Id == report.Id, ct);
|
||||
|
||||
await SendOkAsync(responseReport.ToDto(), ct);
|
||||
}
|
||||
|
||||
private static string NormalizeFileName(string? fileName, string extension)
|
||||
|
||||
Reference in New Issue
Block a user