Add cache for position
This commit is contained in:
@@ -480,8 +480,23 @@ public class DataController : ControllerBase
|
|||||||
decimal totalVolume = strategy.Volume;
|
decimal totalVolume = strategy.Volume;
|
||||||
decimal volumeLast24h = strategy.Volume;
|
decimal volumeLast24h = strategy.Volume;
|
||||||
|
|
||||||
|
// Use caching for position data in UI context (not critical trading operations)
|
||||||
|
var cacheKey = $"positions_{strategy.Identifier}";
|
||||||
|
var cachedPositions = _cacheService.GetValue<List<Position>>(cacheKey);
|
||||||
|
|
||||||
|
List<Position> positions;
|
||||||
|
if (cachedPositions != null)
|
||||||
|
{
|
||||||
|
positions = cachedPositions;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Fetch positions associated with this bot using the provided trading service
|
// Fetch positions associated with this bot using the provided trading service
|
||||||
var positions = await tradingService.GetPositionsByInitiatorIdentifierAsync(strategy.Identifier);
|
positions = (await tradingService.GetPositionsByInitiatorIdentifierAsync(strategy.Identifier)).ToList();
|
||||||
|
|
||||||
|
// Cache positions for 2 minutes for UI display purposes
|
||||||
|
_cacheService.SaveValue(cacheKey, positions, TimeSpan.FromMinutes(2));
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate win/loss statistics from actual positions (including open positions)
|
// Calculate win/loss statistics from actual positions (including open positions)
|
||||||
int wins = positions.Count(p => p.ProfitAndLoss != null && p.ProfitAndLoss.Realized > 0);
|
int wins = positions.Count(p => p.ProfitAndLoss != null && p.ProfitAndLoss.Realized > 0);
|
||||||
|
|||||||
@@ -273,17 +273,33 @@ public class PostgreSqlTradingRepository : BaseRepositoryWithLogging, ITradingRe
|
|||||||
{
|
{
|
||||||
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
|
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
|
||||||
|
|
||||||
|
// Optimized query with explicit JOINs to avoid N+1 queries
|
||||||
var position = await _context.Positions
|
var position = await _context.Positions
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Include(p => p.User)
|
.Where(p => p.Identifier == identifier)
|
||||||
.Include(p => p.OpenTrade)
|
.Select(p => new
|
||||||
.Include(p => p.StopLossTrade)
|
{
|
||||||
.Include(p => p.TakeProfit1Trade)
|
Position = p,
|
||||||
.Include(p => p.TakeProfit2Trade)
|
User = p.User,
|
||||||
.FirstOrDefaultAsync(p => p.Identifier == identifier)
|
OpenTrade = p.OpenTrade,
|
||||||
|
StopLossTrade = p.StopLossTrade,
|
||||||
|
TakeProfit1Trade = p.TakeProfit1Trade,
|
||||||
|
TakeProfit2Trade = p.TakeProfit2Trade
|
||||||
|
})
|
||||||
|
.FirstOrDefaultAsync()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
return PostgreSqlMappers.Map(position ?? throw new InvalidOperationException("Position not found"));
|
if (position == null)
|
||||||
|
throw new InvalidOperationException("Position not found");
|
||||||
|
|
||||||
|
// Manually assign navigation properties to avoid lazy loading
|
||||||
|
position.Position.User = position.User;
|
||||||
|
position.Position.OpenTrade = position.OpenTrade;
|
||||||
|
position.Position.StopLossTrade = position.StopLossTrade;
|
||||||
|
position.Position.TakeProfit1Trade = position.TakeProfit1Trade;
|
||||||
|
position.Position.TakeProfit2Trade = position.TakeProfit2Trade;
|
||||||
|
|
||||||
|
return PostgreSqlMappers.Map(position.Position);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user