# Orleans Migration Plan for Managing Apps Trading Bot

## Overview
Migrate the `TradingBot` class to Microsoft Orleans grains for improved performance, scalability, and high availability while maintaining backward compatibility with the `Backtester` class.

## Current Architecture Analysis

### TradingBot Key Characteristics
- Long-running stateful service with complex state (positions, signals, candles, indicators)
- Timer-based execution via `InitWorker(Run)` 
- Dependency injection via `IServiceScopeFactory`
- Persistence via `SaveBackup()` and `LoadBackup()`
- SignalR integration for real-time updates

### Backtester Requirements
- Creates TradingBot instances as regular classes (line 198: `_botFactory.CreateBacktestTradingBot`)
- Runs synchronous backtesting without Orleans overhead
- Needs direct object manipulation for performance

## 1. Orleans Grain Design

### A. Create ITradingBotGrain Interface
```csharp
// src/Managing.Application.Abstractions/Grains/ITradingBotGrain.cs
public interface ITradingBotGrain : IGrainWithStringKey
{
    Task StartAsync();
    Task StopAsync();
    Task<BotStatus> GetStatusAsync();
    Task<TradingBotConfig> GetConfigurationAsync();
    Task<bool> UpdateConfigurationAsync(TradingBotConfig newConfig);
    Task<Position> OpenPositionManuallyAsync(TradeDirection direction);
    Task ToggleIsForWatchOnlyAsync();
    Task<TradingBotResponse> GetBotDataAsync();
    Task LoadBackupAsync(BotBackup backup);
}
```

### B. Modify TradingBot Class
```csharp
// src/Managing.Application/Bots/TradingBot.cs
public class TradingBot : Grain, ITradingBotGrain, ITradingBot
{
    // Keep existing implementation but add Orleans-specific methods
    // Add grain lifecycle management
    // Replace IServiceScopeFactory with Orleans DI
}
```

## 2. Program.cs Orleans Configuration

Add to `src/Managing.Api/Program.cs` after line 188:

```csharp
// Orleans Configuration
builder.Host.UseOrleans(siloBuilder =>
{
    siloBuilder
        .UseLocalhostClustering() // For local development
        .ConfigureLogging(logging => logging.AddConsole())
        .UseDashboard(options => { options.Port = 8080; })
        .AddMemoryGrainStorageAsDefault()
        .ConfigureServices(services =>
        {
            // Register existing services for Orleans DI
            services.AddSingleton<IExchangeService, ExchangeService>();
            services.AddSingleton<IAccountService, AccountService>();
            services.AddSingleton<ITradingService, TradingService>();
            services.AddSingleton<IMessengerService, MessengerService>();
            services.AddSingleton<IBackupBotService, BackupBotService>();
        });

    // Production clustering configuration
    if (builder.Environment.IsProduction())
    {
        siloBuilder
            .UseAdoNetClustering(options =>
            {
                options.ConnectionString = postgreSqlConnectionString;
                options.Invariant = "Npgsql";
            })
            .UseAdoNetReminderService(options =>
            {
                options.ConnectionString = postgreSqlConnectionString;
                options.Invariant = "Npgsql";
            });
    }
});

// Orleans Client Configuration (for accessing grains from controllers)
builder.Services.AddOrleansClient(clientBuilder =>
{
    clientBuilder.UseLocalhostClustering();
    
    if (builder.Environment.IsProduction())
    {
        clientBuilder.UseAdoNetClustering(options =>
        {
            options.ConnectionString = postgreSqlConnectionString;
            options.Invariant = "Npgsql";
        });
    }
});
```

## 3. Conditional Bot Instantiation Strategy

### A. Enhanced BotFactory Pattern
```csharp
// src/Managing.Application/Bots/Base/BotFactory.cs
public class BotFactory : IBotFactory
{
    private readonly IClusterClient _clusterClient;
    private readonly IServiceProvider _serviceProvider;

    public async Task<ITradingBot> CreateTradingBotAsync(TradingBotConfig config, bool useGrain = true)
    {
        if (config.IsForBacktest || !useGrain)
        {
            // For backtesting: Create regular class instance
            return new TradingBot(
                _serviceProvider.GetService<ILogger<TradingBot>>(),
                _serviceProvider.GetService<IServiceScopeFactory>(),
                config
            );
        }
        else
        {
            // For live trading: Use Orleans grain
            var grain = _clusterClient.GetGrain<ITradingBotGrain>(config.Name);
            return new TradingBotGrainProxy(grain, config);
        }
    }
}
```

### B. TradingBotGrainProxy (Adapter Pattern)
```csharp
// src/Managing.Application/Bots/TradingBotGrainProxy.cs
public class TradingBotGrainProxy : ITradingBot
{
    private readonly ITradingBotGrain _grain;
    private TradingBotConfig _config;

    public TradingBotGrainProxy(ITradingBotGrain grain, TradingBotConfig config)
    {
        _grain = grain;
        _config = config;
    }

    public async Task Start() => await _grain.StartAsync();
    public async Task Stop() => await _grain.StopAsync();
    
    // Implement all ITradingBot methods by delegating to grain
    // This maintains compatibility with existing bot management code
}
```

### C. Backtester Compatibility
In `Backtester.cs` (line 198), the factory call remains unchanged:
```csharp
// This will automatically create a regular class instance due to IsForBacktest = true
var tradingBot = await _botFactory.CreateBacktestTradingBot(config);
```

## 4. Orleans Grain State Management

```csharp
// src/Managing.Application/Bots/TradingBotGrainState.cs
[GenerateSerializer]
public class TradingBotGrainState
{
    [Id(0)] public TradingBotConfig Config { get; set; }
    [Id(1)] public HashSet<LightSignal> Signals { get; set; }
    [Id(2)] public List<Position> Positions { get; set; }
    [Id(3)] public Dictionary<DateTime, decimal> WalletBalances { get; set; }
    [Id(4)] public BotStatus Status { get; set; }
    [Id(5)] public DateTime StartupTime { get; set; }
    [Id(6)] public DateTime CreateDate { get; set; }
}

// Updated TradingBot grain
public class TradingBot : Grain<TradingBotGrainState>, ITradingBotGrain
{
    private IDisposable _timer;

    public override async Task OnActivateAsync(CancellationToken cancellationToken)
    {
        // Initialize grain state and start timer-based execution
        if (State.Config != null && State.Status == BotStatus.Running)
        {
            await StartTimerAsync();
        }
    }

    private async Task StartTimerAsync()
    {
        var interval = CandleExtensions.GetIntervalFromTimeframe(State.Config.Timeframe);
        _timer = RegisterTimer(async _ => await Run(), null, TimeSpan.Zero, TimeSpan.FromMilliseconds(interval));
    }
}
```

## 5. Implementation Roadmap

### Phase 1: Infrastructure Setup
1. **Add Orleans packages** (already done in Managing.Api.csproj)
2. **Configure Orleans in Program.cs** with clustering and persistence
3. **Create grain interfaces and state classes**

### Phase 2: Core Migration  
1. **Create ITradingBotGrain interface** with async methods
2. **Modify TradingBot class** to inherit from `Grain<TradingBotGrainState>`
3. **Implement TradingBotGrainProxy** for compatibility
4. **Update BotFactory** with conditional instantiation logic

### Phase 3: Service Integration
1. **Replace IServiceScopeFactory** with Orleans dependency injection
2. **Update timer management** to use Orleans grain timers
3. **Migrate state persistence** from SaveBackup/LoadBackup to Orleans state
4. **Update bot management services** to work with grains

### Phase 4: Testing & Optimization
1. **Test backtesting compatibility** (should remain unchanged)
2. **Performance testing** with multiple concurrent bots
3. **High availability testing** with node failures
4. **Memory and resource optimization**

## Key Benefits

1. **High Availability**: Orleans automatic failover and grain migration
2. **Scalability**: Distributed bot execution across multiple nodes  
3. **Performance**: Reduced serialization overhead, efficient state management
4. **Backward Compatibility**: Backtester continues using regular classes
5. **Simplified State Management**: Orleans handles persistence automatically

## Migration Considerations

1. **Async Conversion**: All bot operations become async
2. **State Serialization**: Ensure all state classes are serializable
3. **Timer Management**: Replace custom timers with Orleans grain timers
4. **Dependency Injection**: Adapt from ASP.NET Core DI to Orleans DI
5. **SignalR Integration**: Update to work with distributed grains

## Current Status
- ✅ Orleans package added to Managing.Api.csproj
- ✅ Orleans configuration implemented in Program.cs
- ✅ ITradingBotGrain interface created
- ✅ TradingBotGrainState class created
- ✅ TradingBotGrain implementation completed
- ✅ TradingBotResponse model created
- ✅ TradingBotProxy adapter pattern implemented
- ✅ Original TradingBot class preserved for backtesting
- ✅ BotService conditional logic implemented for all creation methods
- ⏳ Testing Orleans integration