feature: Degraded Operations Visibility
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Minio;
|
||||
using Minio.DataModel.Args;
|
||||
using Minio.Exceptions;
|
||||
|
||||
public sealed class DischargeSummaryService : IDischargeSummaryService
|
||||
{
|
||||
private readonly AppDbContext _db;
|
||||
private readonly MinioOptions _minioOpts;
|
||||
|
||||
public DischargeSummaryService(AppDbContext db, IOptions<MinioOptions> minioOpts)
|
||||
{
|
||||
_db = db;
|
||||
_minioOpts = minioOpts.Value;
|
||||
}
|
||||
|
||||
public async Task<DischargeSummaryInfo> GetInfoAsync(Guid encounterId, CancellationToken ct = default)
|
||||
{
|
||||
var encounter = await _db.Encounters
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync(e => e.Id == encounterId, ct);
|
||||
|
||||
if (encounter is null)
|
||||
throw new NotFoundException("Encounter not found.");
|
||||
|
||||
if (encounter.Status != EncounterStatus.Discharged)
|
||||
{
|
||||
return new DischargeSummaryInfo(
|
||||
"NotDischarged",
|
||||
encounter.DischargedAt,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
var exists = await ObjectExistsAsync(encounterId, ct);
|
||||
if (!exists)
|
||||
{
|
||||
return new DischargeSummaryInfo(
|
||||
"Pending",
|
||||
encounter.DischargedAt,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
return new DischargeSummaryInfo(
|
||||
"Ready",
|
||||
encounter.DischargedAt,
|
||||
"text/plain",
|
||||
"discharge-summary.pdf");
|
||||
}
|
||||
|
||||
public async Task<DischargeSummaryContent> GetContentAsync(Guid encounterId, CancellationToken ct = default)
|
||||
{
|
||||
var info = await GetInfoAsync(encounterId, ct);
|
||||
|
||||
if (info.Status == "NotDischarged")
|
||||
{
|
||||
throw new ConflictException(
|
||||
"Discharge summary is only available for discharged encounters.",
|
||||
"ENCOUNTER_NOT_DISCHARGED");
|
||||
}
|
||||
|
||||
if (info.Status == "Pending")
|
||||
{
|
||||
throw new NotFoundException(
|
||||
"Discharge summary is still being generated.",
|
||||
"DISCHARGE_SUMMARY_PENDING");
|
||||
}
|
||||
|
||||
var client = MinioClientFactory.Build(_minioOpts);
|
||||
var bucket = _minioOpts.BucketName;
|
||||
var objectKey = ObjectKey(encounterId);
|
||||
var ms = new MemoryStream();
|
||||
|
||||
await client.GetObjectAsync(new GetObjectArgs()
|
||||
.WithBucket(bucket)
|
||||
.WithObject(objectKey)
|
||||
.WithCallbackStream(stream => stream.CopyTo(ms)), ct);
|
||||
|
||||
ms.Position = 0;
|
||||
return new DischargeSummaryContent(ms, info.ContentType!, info.FileName!);
|
||||
}
|
||||
|
||||
private async Task<bool> ObjectExistsAsync(Guid encounterId, CancellationToken ct)
|
||||
{
|
||||
var client = MinioClientFactory.Build(_minioOpts);
|
||||
var bucket = _minioOpts.BucketName;
|
||||
var objectKey = ObjectKey(encounterId);
|
||||
|
||||
try
|
||||
{
|
||||
await client.StatObjectAsync(new StatObjectArgs()
|
||||
.WithBucket(bucket)
|
||||
.WithObject(objectKey), ct);
|
||||
return true;
|
||||
}
|
||||
catch (ObjectNotFoundException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static string ObjectKey(Guid encounterId) =>
|
||||
$"discharge-summaries/{encounterId}/summary.pdf";
|
||||
}
|
||||
Reference in New Issue
Block a user