fix: align backend APIs and upload flow
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
using System.Data;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
|
||||
namespace IM.InitCommon.Management;
|
||||
public static class ReceiptStore
|
||||
{
|
||||
public static async Task<ActionReceipt> Execute(DbContext db, InternalAction command, Func<Task<ActionReceipt>> apply, CancellationToken ct)
|
||||
{
|
||||
await using var tx = await db.Database.BeginTransactionAsync(IsolationLevel.Serializable, ct);
|
||||
var connection = db.Database.GetDbConnection();
|
||||
await using var read = connection.CreateCommand(); read.Transaction = tx.GetDbTransaction();
|
||||
var owner = db.GetType().Name;
|
||||
read.CommandText = "SELECT Payload FROM management_receipts WHERE Owner = @owner AND Id = @id FOR UPDATE";
|
||||
var ownerParameter = read.CreateParameter(); ownerParameter.ParameterName = "@owner"; ownerParameter.Value = owner; read.Parameters.Add(ownerParameter);
|
||||
var parameter = read.CreateParameter(); parameter.ParameterName = "@id"; parameter.Value = command.Id.ToString(); read.Parameters.Add(parameter);
|
||||
var existing = await read.ExecuteScalarAsync(ct);
|
||||
if (existing is string json) {
|
||||
var saved = JsonSerializer.Deserialize<SavedReceipt>(json)!;
|
||||
if (saved.Command != command) throw new InvalidOperationException("操作 ID 已被其他请求使用");
|
||||
await tx.CommitAsync(ct); return saved.Result;
|
||||
}
|
||||
var receipt = await apply(); await db.SaveChangesAsync(ct);
|
||||
await db.Database.ExecuteSqlInterpolatedAsync($"INSERT INTO management_receipts (Owner, Id, Payload, CreatedAt) VALUES ({owner}, {command.Id.ToString()}, {JsonSerializer.Serialize(new SavedReceipt(command, receipt))}, {DateTime.UtcNow})", ct);
|
||||
await tx.CommitAsync(ct); return receipt;
|
||||
}
|
||||
private record SavedReceipt(InternalAction Command, ActionReceipt Result);
|
||||
}
|
||||
Reference in New Issue
Block a user