Reduce Agent Summary call
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Abstractions.Grains;
|
||||
using Managing.Application.Abstractions.Models;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Bots.Models;
|
||||
using Managing.Application.Shared;
|
||||
using Managing.Domain.Statistics;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.Bots.Grains;
|
||||
|
||||
public class AgentGrain : Grain, IAgentGrain, IRemindable
|
||||
public class AgentGrain : Grain, IAgentGrain
|
||||
{
|
||||
private readonly IPersistentState<AgentGrainState> _state;
|
||||
private readonly ILogger<AgentGrain> _logger;
|
||||
@@ -19,7 +19,6 @@ public class AgentGrain : Grain, IAgentGrain, IRemindable
|
||||
private readonly IUserService _userService;
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly ITradingService _tradingService;
|
||||
private const string _updateSummaryReminderName = "UpdateAgentSummary";
|
||||
|
||||
public AgentGrain(
|
||||
[PersistentState("agent-state", "agent-store")]
|
||||
@@ -54,42 +53,25 @@ public class AgentGrain : Grain, IAgentGrain, IRemindable
|
||||
await _state.WriteStateAsync();
|
||||
await UpdateSummary();
|
||||
_logger.LogInformation("Agent {UserId} initialized with name {AgentName}", userId, agentName);
|
||||
await RegisterReminderAsync();
|
||||
}
|
||||
|
||||
private async Task RegisterReminderAsync()
|
||||
public async Task OnAgentSummaryUpdateAsync(AgentSummaryUpdateEvent updateEvent)
|
||||
{
|
||||
try
|
||||
{
|
||||
var options = GrainHelpers.GetDynamicRandomizedTimerOptions(TimeSpan.FromMinutes(2), 200);
|
||||
|
||||
// Register a reminder that fires every 5 minutes
|
||||
await this.RegisterOrUpdateReminder(_updateSummaryReminderName, options.dueTime,
|
||||
options.period);
|
||||
_logger.LogInformation("Reminder registered for agent {UserId} to update summary every 5 minutes",
|
||||
this.GetPrimaryKeyLong());
|
||||
_logger.LogInformation("Received agent summary update event for user {UserId}, event type: {EventType}",
|
||||
this.GetPrimaryKeyLong(), updateEvent.EventType);
|
||||
|
||||
// Only update summary if the event is for this agent's bots
|
||||
if (_state.State.BotIds.Contains(updateEvent.BotId))
|
||||
{
|
||||
await UpdateSummary();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to register reminder for agent {UserId}", this.GetPrimaryKeyLong());
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ReceiveReminder(string reminderName, TickStatus status)
|
||||
{
|
||||
if (reminderName == _updateSummaryReminderName)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("Reminder triggered for agent {UserId} to update summary",
|
||||
this.GetPrimaryKeyLong());
|
||||
await UpdateSummary();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error updating agent summary from reminder for user {UserId}",
|
||||
this.GetPrimaryKeyLong());
|
||||
}
|
||||
_logger.LogError(ex, "Error processing agent summary update event for user {UserId}",
|
||||
this.GetPrimaryKeyLong());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,6 +185,9 @@ public class AgentGrain : Grain, IAgentGrain, IRemindable
|
||||
{
|
||||
await _state.WriteStateAsync();
|
||||
_logger.LogInformation("Bot {BotId} registered to Agent {UserId}", botId, this.GetPrimaryKeyLong());
|
||||
|
||||
// Update summary after registering bot
|
||||
await UpdateSummary();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,6 +197,9 @@ public class AgentGrain : Grain, IAgentGrain, IRemindable
|
||||
{
|
||||
await _state.WriteStateAsync();
|
||||
_logger.LogInformation("Bot {BotId} unregistered from Agent {UserId}", botId, this.GetPrimaryKeyLong());
|
||||
|
||||
// Update summary after unregistering bot
|
||||
await UpdateSummary();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Abstractions.Grains;
|
||||
using Managing.Application.Abstractions.Models;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Trading.Commands;
|
||||
using Managing.Application.Trading.Handlers;
|
||||
@@ -93,6 +94,9 @@ public class TradingBotBase : ITradingBot
|
||||
$"📢 I'll notify you when signals are triggered.";
|
||||
|
||||
await LogInformation(startupMessage);
|
||||
|
||||
// Notify AgentGrain about bot startup
|
||||
await NotifyAgentGrainAsync(AgentSummaryEventType.BotStarted, $"Bot: {Config.Name}, Ticker: {Config.Ticker}");
|
||||
break;
|
||||
|
||||
case BotStatus.Running:
|
||||
@@ -191,7 +195,7 @@ public class TradingBotBase : ITradingBot
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateSignals(HashSet<Candle>? candles = null)
|
||||
public async Task UpdateSignals(HashSet<Candle> candles = null)
|
||||
{
|
||||
// If position open and not flipped, do not update signals
|
||||
if (!Config.FlipPosition && Positions.Any(p => !p.Value.IsFinished())) return;
|
||||
@@ -765,6 +769,9 @@ public class TradingBotBase : ITradingBot
|
||||
async messengerService => { await messengerService.SendPosition(position); });
|
||||
}
|
||||
|
||||
// Notify AgentGrain about position opening
|
||||
await NotifyAgentGrainAsync(AgentSummaryEventType.PositionOpened, $"Signal: {signal.Identifier}");
|
||||
|
||||
Logger.LogInformation($"Position requested");
|
||||
return position; // Return the created position without adding to list
|
||||
}
|
||||
@@ -1195,6 +1202,10 @@ public class TradingBotBase : ITradingBot
|
||||
Logger.LogInformation(
|
||||
$"💰 **Balance Updated**\nNew bot trading balance: `${Config.BotTradingBalance:F2}`");
|
||||
}
|
||||
|
||||
// Notify AgentGrain about position closing
|
||||
var pnlInfo = position.ProfitAndLoss?.Realized != null ? $"PnL: {position.ProfitAndLoss.Realized:F2}" : "PnL: Unknown";
|
||||
await NotifyAgentGrainAsync(AgentSummaryEventType.PositionClosed, $"Signal: {position.SignalIdentifier}, {pnlInfo}");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1875,4 +1886,42 @@ public class TradingBotBase : ITradingBot
|
||||
|
||||
return isInCooldown;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a notification to the AgentGrain to trigger summary updates
|
||||
/// </summary>
|
||||
/// <param name="eventType">The type of event (e.g., PositionOpened, PositionClosed)</param>
|
||||
/// <param name="additionalData">Optional additional context data</param>
|
||||
private async Task NotifyAgentGrainAsync(AgentSummaryEventType eventType, string additionalData = null)
|
||||
{
|
||||
if (Config.IsForBacktest || Account?.User == null)
|
||||
{
|
||||
return; // Skip notifications for backtest or when no user context
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await ServiceScopeHelpers.WithScopedService<IGrainFactory>(_scopeFactory, async grainFactory =>
|
||||
{
|
||||
var agentGrain = grainFactory.GetGrain<IAgentGrain>(Account.User.Id);
|
||||
|
||||
var updateEvent = new AgentSummaryUpdateEvent
|
||||
{
|
||||
UserId = Account.User.Id,
|
||||
BotId = Identifier,
|
||||
EventType = eventType,
|
||||
Timestamp = DateTime.UtcNow,
|
||||
AdditionalData = additionalData
|
||||
};
|
||||
|
||||
await agentGrain.OnAgentSummaryUpdateAsync(updateEvent);
|
||||
|
||||
Logger.LogDebug("Sent agent notification: {EventType} for bot {BotId}", eventType, Identifier);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Failed to send agent notification: {EventType} for bot {BotId}", eventType, Identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user