classlib/ExpenseTracker.Persistence/MongoDb/MongoDbContext.cs
2024-08-07 21:12:02 +03:00

116 lines
3.9 KiB
C#

using System.Diagnostics;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Core.Events;
namespace ExpenseTracker.Persistence.MongoDb;
public class MongoDbContext : IDisposable
{
private IMongoDatabase Database { get; set; }
private MongoClient Client { get; set; }
public IClientSessionHandle Session { get; private set; }
private readonly List<Func<Task>> _commands;
public MongoDbContext(IConfiguration configuration, ILogger<MongoDbContext> logger)
{
var settings = new MongoClientSettings();
settings.ClusterConfigurator = cb =>
{
cb.Subscribe<CommandStartedEvent>(e =>
{
logger.LogDebug(
"{@DateUtc} {@TimeUtc} {@TraceId} {@SpanId} Starting performing MongoDB command {@CommandName}.\nQuery: {@Query}.",
DateTime.UtcNow.ToString("yyyy-MM-dd"),
DateTime.UtcNow.ToString("HH:mm:ss.FFF"),
Activity.Current?.TraceId.ToString(),
Activity.Current?.SpanId.ToString(),
e.CommandName,
e.Command.ToString());
});
cb.Subscribe<CommandFailedEvent>(e =>
{
logger.LogCritical(
"{@DateUtc} {@TimeUtc} {@TraceId} {@SpanId} MongoDB command {@CommandName} failed with exception {@Exception}.",
DateTime.UtcNow.ToString("yyyy-MM-dd"),
DateTime.UtcNow.ToString("HH:mm:ss.FFF"),
Activity.Current?.TraceId.ToString(),
Activity.Current?.SpanId.ToString(),
e.CommandName,
e.Failure);
});
cb.Subscribe<CommandSucceededEvent>(e =>
{
logger.LogDebug(
"{@DateUtc} {@TimeUtc} {@TraceId} {@SpanId} Finished performing MongoDB command {@CommandName} in {@DurationInSeconds} seconds.",
DateTime.UtcNow.ToString("yyyy-MM-dd"),
DateTime.UtcNow.ToString("HH:mm:ss.FFF"),
Activity.Current?.TraceId.ToString(),
Activity.Current?.SpanId.ToString(),
e.CommandName,
e.Duration.TotalSeconds);
});
};
settings.Server = new MongoServerAddress(configuration["Database:ConnectionString"].Split(':')[0]);
Client = new MongoClient(settings);
Database = Client.GetDatabase(configuration["Database:DomainPartitionName"]);
_commands = new List<Func<Task>>();
}
public async Task<int> SaveAsync(CancellationToken cancellationToken)
{
// Console.WriteLine($"\n\n\n{_commands.Count}\n\n\n");
// if (_commands.Count == 1)
// {
// var task = _commands.First();
// await task();
//
// return 1;
// }
using (Session = await Client.StartSessionAsync())
{
Session.StartTransaction();
try
{
var commandTasks = _commands.Select(c => c());
await Task.WhenAll(commandTasks);
}
catch (Exception)
{
await Session.AbortTransactionAsync(cancellationToken);
throw;
}
await Session.CommitTransactionAsync(cancellationToken);
}
return _commands.Count;
}
public IMongoCollection<T> GetCollection<T>(string name)
{
return Database.GetCollection<T>(name);
}
public void AddCommand(Func<Task> command)
{
_commands.Add(command);
}
public void Dispose()
{
Session?.Dispose();
GC.SuppressFinalize(this);
}
}