Add monitoring on queries with sentry alert + Fix check position list in db for backtest

This commit is contained in:
2025-10-10 00:15:02 +07:00
parent ffb98fe359
commit e4c2f8b7a5
24 changed files with 3340 additions and 179 deletions

View File

@@ -1,119 +1,128 @@
using Managing.Application.Abstractions.Repositories;
using Managing.Domain.Users;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace Managing.Infrastructure.Databases.PostgreSql;
public class PostgreSqlUserRepository : IUserRepository
public class PostgreSqlUserRepository : BaseRepositoryWithLogging, IUserRepository
{
private readonly ManagingDbContext _context;
public PostgreSqlUserRepository(ManagingDbContext context)
public PostgreSqlUserRepository(ManagingDbContext context, ILogger<SqlQueryLogger> logger, SentrySqlMonitoringService sentryMonitoringService)
: base(context, logger, sentryMonitoringService)
{
_context = context;
}
public async Task<User> GetUserByAgentNameAsync(string agentName)
{
try
return await ExecuteWithLoggingAsync(async () =>
{
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
try
{
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
var userEntity = await _context.Users
.AsNoTracking()
.FirstOrDefaultAsync(u => u.AgentName == agentName)
.ConfigureAwait(false);
var userEntity = await _context.Users
.AsNoTracking()
.FirstOrDefaultAsync(u => u.AgentName == agentName)
.ConfigureAwait(false);
return PostgreSqlMappers.Map(userEntity);
}
finally
{
// Always ensure the connection is closed after the operation
await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context);
}
return PostgreSqlMappers.Map(userEntity ?? throw new InvalidOperationException("User not found"));
}
finally
{
// Always ensure the connection is closed after the operation
await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context);
}
}, nameof(GetUserByAgentNameAsync), ("agentName", agentName));
}
public async Task<User> GetUserByNameAsync(string name)
{
try
return await ExecuteWithLoggingAsync(async () =>
{
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
try
{
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
var userEntity = await _context.Users
.AsNoTracking()
.FirstOrDefaultAsync(u => u.Name == name)
.ConfigureAwait(false);
var userEntity = await _context.Users
.AsNoTracking()
.FirstOrDefaultAsync(u => u.Name == name)
.ConfigureAwait(false);
return PostgreSqlMappers.Map(userEntity);
}
finally
{
// Always ensure the connection is closed after the operation
await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context);
}
return PostgreSqlMappers.Map(userEntity ?? throw new InvalidOperationException("User not found"));
}
finally
{
// Always ensure the connection is closed after the operation
await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context);
}
}, nameof(GetUserByNameAsync), ("name", name));
}
public async Task<IEnumerable<User>> GetAllUsersAsync()
{
try
return await ExecuteWithLoggingAsync(async () =>
{
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
try
{
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
var userEntities = await _context.Users
.AsNoTracking()
.ToListAsync()
.ConfigureAwait(false);
var userEntities = await _context.Users
.AsNoTracking()
.ToListAsync()
.ConfigureAwait(false);
return userEntities.Select(PostgreSqlMappers.Map);
}
finally
{
// Always ensure the connection is closed after the operation
await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context);
}
return userEntities.Select(PostgreSqlMappers.Map);
}
finally
{
// Always ensure the connection is closed after the operation
await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context);
}
}, nameof(GetAllUsersAsync));
}
public async Task SaveOrUpdateUserAsync(User user)
{
try
await ExecuteWithLoggingAsync(async () =>
{
var existingUser = await _context.Users
.AsTracking()
.FirstOrDefaultAsync(u => u.Name == user.Name)
.ConfigureAwait(false);
if (existingUser != null)
try
{
// Update existing user
existingUser.AgentName = user.AgentName;
existingUser.AvatarUrl = user.AvatarUrl;
existingUser.TelegramChannel = user.TelegramChannel;
var existingUser = await _context.Users
.AsTracking()
.FirstOrDefaultAsync(u => u.Name == user.Name)
.ConfigureAwait(false);
_context.Users.Update(existingUser);
if (existingUser != null)
{
// Update existing user
existingUser.AgentName = user.AgentName;
existingUser.AvatarUrl = user.AvatarUrl;
existingUser.TelegramChannel = user.TelegramChannel;
// Update the user object with the existing user's ID
user.Id = existingUser.Id;
}
else
{
// Insert new user
var userEntity = PostgreSqlMappers.Map(user);
_context.Users.Add(userEntity);
_context.Users.Update(existingUser);
// Update the user object with the existing user's ID
user.Id = existingUser.Id;
}
else
{
// Insert new user
var userEntity = PostgreSqlMappers.Map(user);
_context.Users.Add(userEntity);
// Update the user object with the database-generated ID after save
await _context.SaveChangesAsync().ConfigureAwait(false);
user.Id = userEntity.Id;
return; // Exit early since we already saved
}
// Update the user object with the database-generated ID after save
await _context.SaveChangesAsync().ConfigureAwait(false);
user.Id = userEntity.Id;
return; // Exit early since we already saved
}
await _context.SaveChangesAsync().ConfigureAwait(false);
}
catch (Exception e)
{
Console.WriteLine(e);
throw new Exception("Cannot save or update user");
}
catch (Exception e)
{
Console.WriteLine(e);
throw new Exception("Cannot save or update user");
}
}, nameof(SaveOrUpdateUserAsync), ("userName", user.Name), ("userId", user.Id));
}
}