test: create test for concurrency
This commit is contained in:
@@ -20,7 +20,7 @@ public class SepsisBundleService : ISepsisBundleService
|
||||
if (alertType != AlertType.SofaSepsis)
|
||||
throw new InvalidOperationException(
|
||||
$"Sepsis bundle can only be triggered by SOFA_SEPSIS, not {alertType.ToDbString()}.");
|
||||
|
||||
|
||||
var exists = await _db.SepsisBundles
|
||||
.AnyAsync(b => b.EncounterId == encounterId
|
||||
&& b.ComplianceStatus == SepsisBundleComplianceStatus.InProgress, ct);
|
||||
@@ -28,73 +28,75 @@ public class SepsisBundleService : ISepsisBundleService
|
||||
if (exists)
|
||||
return null;
|
||||
|
||||
var recognizedAt = DateTimeOffset.UtcNow;
|
||||
var bundle = new SepsisBundle
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
EncounterId = encounterId,
|
||||
TriggeringAlertId = triggeringAlertId,
|
||||
TriggeringAlertType = alertType.ToDbString(),
|
||||
RecognizedAt = recognizedAt,
|
||||
DeadlineAt = recognizedAt.AddHours(1),
|
||||
ComplianceStatus = SepsisBundleComplianceStatus.InProgress
|
||||
};
|
||||
|
||||
var elementDefs = new (SepsisBundleElementType Type, OrderType OrderType, string Description)[]
|
||||
{
|
||||
(SepsisBundleElementType.BloodCultures, OrderType.Lab, "SEP-1: Blood cultures"),
|
||||
(SepsisBundleElementType.SerumLactate, OrderType.Lab, "SEP-1: Serum lactate"),
|
||||
(SepsisBundleElementType.BroadSpectrumAntibiotics, OrderType.Medication, "SEP-1: Broad-spectrum antibiotics"),
|
||||
(SepsisBundleElementType.IvFluidResuscitation, OrderType.Procedure, "SEP-1: IV fluid bolus"),
|
||||
};
|
||||
|
||||
foreach (var (elementType, orderType, description) in elementDefs)
|
||||
{
|
||||
var order = await _orderService.CreateAsync(encounterId, new CreateOrderRequest(
|
||||
orderType, description, "sepsis-bundle-engine"));
|
||||
|
||||
bundle.Elements.Add(new SepsisBundleElement
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
ElementType = elementType,
|
||||
Status = SepsisBundleElementStatus.Pending,
|
||||
OrderId = order.Id
|
||||
});
|
||||
}
|
||||
|
||||
_db.SepsisBundles.Add(bundle);
|
||||
|
||||
_db.OutboxEvents.Add(new OutboxEvent
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Topic = "sepsis.bundle.created",
|
||||
Payload = JsonSerializer.Serialize(new
|
||||
{
|
||||
bundleId = bundle.Id,
|
||||
encounterId,
|
||||
triggeringAlertId,
|
||||
triggeringAlertType = alertType.ToDbString(),
|
||||
recognizedAt,
|
||||
deadlineAt = bundle.DeadlineAt,
|
||||
partitionKey = encounterId.ToString()
|
||||
}),
|
||||
PartitionKey = encounterId.ToString(),
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
});
|
||||
|
||||
await using var tx = await _db.Database.BeginTransactionAsync(ct);
|
||||
try
|
||||
{
|
||||
var recognizedAt = DateTimeOffset.UtcNow;
|
||||
var bundle = new SepsisBundle
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
EncounterId = encounterId,
|
||||
TriggeringAlertId = triggeringAlertId,
|
||||
TriggeringAlertType = alertType.ToDbString(),
|
||||
RecognizedAt = recognizedAt,
|
||||
DeadlineAt = recognizedAt.AddHours(1),
|
||||
ComplianceStatus = SepsisBundleComplianceStatus.InProgress
|
||||
};
|
||||
|
||||
var elementDefs = new (SepsisBundleElementType Type, OrderType OrderType, string Description)[]
|
||||
{
|
||||
(SepsisBundleElementType.BloodCultures, OrderType.Lab, "SEP-1: Blood cultures"),
|
||||
(SepsisBundleElementType.SerumLactate, OrderType.Lab, "SEP-1: Serum lactate"),
|
||||
(SepsisBundleElementType.BroadSpectrumAntibiotics, OrderType.Medication, "SEP-1: Broad-spectrum antibiotics"),
|
||||
(SepsisBundleElementType.IvFluidResuscitation, OrderType.Procedure, "SEP-1: IV fluid bolus"),
|
||||
};
|
||||
|
||||
foreach (var (elementType, orderType, description) in elementDefs)
|
||||
{
|
||||
var order = await _orderService.CreateAsync(encounterId, new CreateOrderRequest(
|
||||
orderType, description, "sepsis-bundle-engine"));
|
||||
|
||||
bundle.Elements.Add(new SepsisBundleElement
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
ElementType = elementType,
|
||||
Status = SepsisBundleElementStatus.Pending,
|
||||
OrderId = order.Id
|
||||
});
|
||||
}
|
||||
|
||||
_db.SepsisBundles.Add(bundle);
|
||||
|
||||
_db.OutboxEvents.Add(new OutboxEvent
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Topic = "sepsis.bundle.created",
|
||||
Payload = JsonSerializer.Serialize(new
|
||||
{
|
||||
bundleId = bundle.Id,
|
||||
encounterId,
|
||||
triggeringAlertId,
|
||||
triggeringAlertType = alertType.ToDbString(),
|
||||
recognizedAt,
|
||||
deadlineAt = bundle.DeadlineAt,
|
||||
partitionKey = encounterId.ToString()
|
||||
}),
|
||||
PartitionKey = encounterId.ToString(),
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
});
|
||||
|
||||
await _db.SaveChangesAsync(ct);
|
||||
await tx.CommitAsync(ct);
|
||||
return bundle;
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
when (ex.InnerException is Npgsql.PostgresException { SqlState: "23505" } pg
|
||||
&& pg.ConstraintName == "ix_sepsis_bundles_encounter_in_progress")
|
||||
{
|
||||
await tx.RollbackAsync(ct);
|
||||
_db.ChangeTracker.Clear();
|
||||
return null;
|
||||
}
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
public async Task<SepsisBundle?> GetCurrentByEncounterAsync(Guid encounterId)
|
||||
|
||||
Reference in New Issue
Block a user