Add caches
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user