Files
adas-core/adas-core.Infrastructure/Repositories/ObservationArchiveRepository.cs
T

160 lines
5.6 KiB
C#

using System.Diagnostics;
using adas_core.Application.Repositories.Interfaces;
using adas_core.Domain.Models;
using adas_core.Domain.Models.AppSettings;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;
using Serilog;
namespace adas_core.Infrastructure.Repositories;
public class ObservationArchiveRepository : MongoRepository<PatientObservation>, IObservationArchiveRepository
{
private readonly ApiSettings _apiSettings;
public ObservationArchiveRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
_apiSettings = apiSettings.Value;
} //For testing
public async Task<List<PatientObservation>> AggregatedPatientLastObservations(ObjectId patientId, int num,
DateTime lastDate, List<string>? filterObservations = null)
{
filterObservations = await AggregatePatientObservations(patientId, filterObservations);
var results = new List<PatientObservation>();
foreach (var obs in filterObservations)
{
var filter = Builders<PatientObservation>.Filter.And(
Builders<PatientObservation>.Filter.Eq(o => o.PatientId, patientId),
Builders<PatientObservation>.Filter.Eq(o => o.Name, obs),
Builders<PatientObservation>.Filter.Lte(o => o.Time, lastDate)
);
var sort = Builders<PatientObservation>.Sort.Descending(o => o.Time);
results.AddRange(Collection.Find(filter).Sort(sort).Limit(num).ToEnumerable());
}
return results;
}
public override string GetCollectionName()
{
return _apiSettings.ArchivePatientsObservations ?? "archive_patients_observations";
}
public new async Task InsertOneAsync(PatientObservation patientObservation)
{
const int maxRetries = 2; // Número máximo de reintentos
var retryCount = 0;
while (true)
try
{
await Collection.InsertOneAsync(patientObservation);
return;
}
catch (MongoWriteException ex) when (ex.WriteError.Category == ServerErrorCategory.DuplicateKey)
{
retryCount++;
Log.Warning(
"Duplicate key error encountered. Retrying with new ObjectId. Attempt {attempt} of {maxRetries}",
retryCount, maxRetries);
patientObservation.Id = new ObjectId();
Log.Information("Generated ObjectId: {objectId}", patientObservation.Id);
if (retryCount >= maxRetries)
{
Log.Error("Maximum retry attempts reached. Could not insert document due to duplicate key error.");
throw; // Re-lanzar la excepción después de alcanzar el número máximo de reintentos
}
}
catch (Exception ex)
{
Log.Error("Error inserting patient observation: {exMessage}", ex.Message);
throw;
}
}
public async Task DeleteBeforeDate(DateTime date)
{
var filter = Builders<PatientObservation>.Filter.Lt(po => po.Time, date);
await Collection.DeleteManyAsync(filter);
}
public async Task<long> InsertBatch(IEnumerable<PatientObservation> observations)
{
var writes = new List<WriteModel<PatientObservation>>();
writes.AddRange(observations.Select(d => new InsertOneModel<PatientObservation>(d)));
var bulkInsert = await Collection.BulkWriteAsync(writes);
return bulkInsert.InsertedCount;
}
public async Task<List<PatientObservation>> FindAllFromPatient(ObjectId patientId)
{
var filter = Builders<PatientObservation>.Filter.Eq(p => p.PatientId, patientId);
var result = await Collection.FindAsync(filter);
return await result.ToListAsync();
}
private async Task<List<string>> AggregatePatientObservations(ObjectId patientId,
List<string>? filterObservations = null)
{
var matchPatient = new BsonDocument
{
{ "patientid", patientId },
{ "name", new BsonDocument { { "$ne", BsonNull.Value } } }
};
if (filterObservations == null || !filterObservations.Any())
{
// GET DISTINCT OBSERVATIONS
var distinctObs = new BsonDocument
{
{
"$group", new BsonDocument
{
{ "_id", "1" },
{
"obs", new BsonDocument
{
{ "$addToSet", "$name" }
}
}
}
}
};
var distinctPipeline = new[]
{
new()
{
{
"$match", matchPatient
}
},
distinctObs
};
Debug.WriteLine("AggregatedArchivedPatientLastObservations distinct obs: \n" + distinctPipeline.ToJson());
var resultList =
await Collection.AggregateAsync<BsonDocument>(distinctPipeline,
new AggregateOptions { AllowDiskUse = true });
var result = resultList.ToList().FirstOrDefault();
if (result != null && result.Any())
filterObservations = result.GetValue("obs").AsBsonArray.Select(it => it.AsString).ToList();
}
return filterObservations ?? [];
}
}