Add caches

This commit is contained in:
2025-10-10 03:12:39 +07:00
parent ba3b0f6232
commit bdda24cb60
3 changed files with 104 additions and 9 deletions

View File

@@ -95,9 +95,9 @@
"MaxMethodExecutionsPerWindow": 50, "MaxMethodExecutionsPerWindow": 50,
"LongRunningQueryThresholdMs": 1000, "LongRunningQueryThresholdMs": 1000,
"SentryAlertThreshold": 5, "SentryAlertThreshold": 5,
"SlowQueryThresholdMs": 2000, "SlowQueryThresholdMs": 1500,
"LogSlowQueriesOnly": false, "LogSlowQueriesOnly": false,
"LogErrorsOnly": false, "LogErrorsOnly": false,
"DataRetentionMinutes": 30 "DataRetentionMinutes": 300
} }
} }

View File

@@ -27,6 +27,16 @@ public class PostgreSqlAccountRepository : IAccountRepository
{ {
_context.Accounts.Remove(accountEntity); _context.Accounts.Remove(accountEntity);
_context.SaveChanges(); _context.SaveChanges();
// Invalidate all relevant caches for this account
var nameCacheKey = $"account_{name}";
var keyCacheKey = $"account_key_{accountEntity.Key}";
var idCacheKey = $"account_id_{accountEntity.Id}";
_cacheService.RemoveValue(nameCacheKey);
_cacheService.RemoveValue(keyCacheKey);
_cacheService.RemoveValue(idCacheKey);
_cacheService.RemoveValue("all_accounts");
} }
} }
@@ -34,6 +44,14 @@ public class PostgreSqlAccountRepository : IAccountRepository
{ {
try try
{ {
// Check cache first for account by key
var cacheKey = $"account_key_{key}";
var cachedAccount = _cacheService.GetValue<Account>(cacheKey);
if (cachedAccount != null)
{
return cachedAccount;
}
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context); await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
var accountEntity = await _context.Accounts var accountEntity = await _context.Accounts
@@ -42,7 +60,12 @@ public class PostgreSqlAccountRepository : IAccountRepository
.FirstOrDefaultAsync(a => a.Key == key) .FirstOrDefaultAsync(a => a.Key == key)
.ConfigureAwait(false); .ConfigureAwait(false);
return PostgreSqlMappers.Map(accountEntity); var account = PostgreSqlMappers.Map(accountEntity);
// Cache account for 1 hour since accounts rarely change
_cacheService.SaveValue(cacheKey, account, TimeSpan.FromHours(1));
return account;
} }
finally finally
{ {
@@ -86,6 +109,14 @@ public class PostgreSqlAccountRepository : IAccountRepository
{ {
try try
{ {
// Check cache first for account by ID
var cacheKey = $"account_id_{id}";
var cachedAccount = _cacheService.GetValue<Account>(cacheKey);
if (cachedAccount != null)
{
return cachedAccount;
}
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context); await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
var accountEntity = await _context.Accounts var accountEntity = await _context.Accounts
@@ -94,7 +125,12 @@ public class PostgreSqlAccountRepository : IAccountRepository
.FirstOrDefaultAsync(a => a.Id == id) .FirstOrDefaultAsync(a => a.Id == id)
.ConfigureAwait(false); .ConfigureAwait(false);
return PostgreSqlMappers.Map(accountEntity); var account = PostgreSqlMappers.Map(accountEntity);
// Cache account for 1 hour since accounts rarely change
_cacheService.SaveValue(cacheKey, account, TimeSpan.FromHours(1));
return account;
} }
finally finally
{ {
@@ -107,6 +143,14 @@ public class PostgreSqlAccountRepository : IAccountRepository
{ {
try try
{ {
// Check cache first for all accounts
var cacheKey = "all_accounts";
var cachedAccounts = _cacheService.GetValue<List<Account>>(cacheKey);
if (cachedAccounts != null)
{
return cachedAccounts;
}
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context); await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
// Use proper async operations with AsNoTracking for optimal performance // Use proper async operations with AsNoTracking for optimal performance
@@ -116,7 +160,12 @@ public class PostgreSqlAccountRepository : IAccountRepository
.ToListAsync() .ToListAsync()
.ConfigureAwait(false); .ConfigureAwait(false);
return PostgreSqlMappers.Map(accountEntities); var accounts = PostgreSqlMappers.Map(accountEntities).ToList();
// Cache all accounts for 1 hour since accounts rarely change
_cacheService.SaveValue(cacheKey, accounts, TimeSpan.FromHours(1));
return accounts;
} }
finally finally
{ {
@@ -137,6 +186,18 @@ public class PostgreSqlAccountRepository : IAccountRepository
_context.Accounts.Add(accountEntity); _context.Accounts.Add(accountEntity);
await _context.SaveChangesAsync().ConfigureAwait(false); await _context.SaveChangesAsync().ConfigureAwait(false);
// Invalidate all accounts cache since we added a new account
_cacheService.RemoveValue("all_accounts");
// Cache the new account for future lookups
var nameCacheKey = $"account_{account.Name}";
var keyCacheKey = $"account_key_{account.Key}";
var idCacheKey = $"account_id_{account.Id}";
_cacheService.SaveValue(nameCacheKey, account, TimeSpan.FromHours(1));
_cacheService.SaveValue(keyCacheKey, account, TimeSpan.FromHours(1));
_cacheService.SaveValue(idCacheKey, account, TimeSpan.FromHours(1));
} }
public async Task UpdateAccountAsync(Account account) public async Task UpdateAccountAsync(Account account)
@@ -159,9 +220,15 @@ public class PostgreSqlAccountRepository : IAccountRepository
existingEntity.IsGmxInitialized = account.IsGmxInitialized; existingEntity.IsGmxInitialized = account.IsGmxInitialized;
await _context.SaveChangesAsync().ConfigureAwait(false); await _context.SaveChangesAsync().ConfigureAwait(false);
// Clear cache for this account // Invalidate all relevant caches for this account
var cacheKey = $"account_{account.Name}"; var nameCacheKey = $"account_{account.Name}";
_cacheService.RemoveValue(cacheKey); var keyCacheKey = $"account_key_{account.Key}";
var idCacheKey = $"account_id_{account.Id}";
_cacheService.RemoveValue(nameCacheKey);
_cacheService.RemoveValue(keyCacheKey);
_cacheService.RemoveValue(idCacheKey);
_cacheService.RemoveValue("all_accounts");
} }
finally finally
{ {

View File

@@ -118,16 +118,38 @@ public class PostgreSqlUserRepository : BaseRepositoryWithLogging, IUserReposito
{ {
return await ExecuteWithLoggingAsync(async () => return await ExecuteWithLoggingAsync(async () =>
{ {
// Check cache first for all users
var cacheKey = "all_users";
var cachedUsers = _cacheService.GetValue<List<User>>(cacheKey);
if (cachedUsers != null)
{
return cachedUsers;
}
try try
{ {
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context); await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
// Optimized query with explicit SELECT to avoid loading unnecessary data
var userEntities = await _context.Users var userEntities = await _context.Users
.AsNoTracking() .AsNoTracking()
.Select(u => new UserEntity
{
Id = u.Id,
Name = u.Name,
AgentName = u.AgentName,
AvatarUrl = u.AvatarUrl,
TelegramChannel = u.TelegramChannel
})
.ToListAsync() .ToListAsync()
.ConfigureAwait(false); .ConfigureAwait(false);
return userEntities.Select(PostgreSqlMappers.Map); var users = userEntities.Select(PostgreSqlMappers.Map).ToList();
// Cache all users for 10 minutes since this data changes infrequently
_cacheService.SaveValue(cacheKey, users, TimeSpan.FromMinutes(10));
return users;
} }
finally finally
{ {
@@ -182,6 +204,9 @@ public class PostgreSqlUserRepository : BaseRepositoryWithLogging, IUserReposito
{ {
_cacheService.SaveValue(newUserAgentCacheKey, user, TimeSpan.FromMinutes(5)); _cacheService.SaveValue(newUserAgentCacheKey, user, TimeSpan.FromMinutes(5));
} }
// Invalidate all users cache since we added a new user
_cacheService.RemoveValue("all_users");
return; // Exit early since we already saved return; // Exit early since we already saved
} }
@@ -204,6 +229,9 @@ public class PostgreSqlUserRepository : BaseRepositoryWithLogging, IUserReposito
var newAgentCacheKey = $"user_agent_{user.AgentName}"; var newAgentCacheKey = $"user_agent_{user.AgentName}";
_cacheService.RemoveValue(newAgentCacheKey); _cacheService.RemoveValue(newAgentCacheKey);
} }
// Invalidate all users cache since we updated a user
_cacheService.RemoveValue("all_users");
} }
catch (Exception e) catch (Exception e)
{ {