From 0966eace58e964f63e429c413cb2e66b369d6c0f Mon Sep 17 00:00:00 2001 From: cryptooda Date: Fri, 15 Aug 2025 16:48:23 +0700 Subject: [PATCH] Disable orleans reminder for deploy and add whitelisted addresses --- src/Managing.Api/Program.cs | 2 +- .../README-ORLEANS-CONFIGURATION.md | 116 ++++++++++++++++++ src/Managing.Api/appsettings.Development.json | 9 ++ src/Managing.Api/appsettings.Oda-Sandbox.json | 1 + src/Managing.Api/appsettings.Oda-docker.json | 1 + src/Managing.Api/appsettings.Oda.json | 1 + src/Managing.Api/appsettings.Production.json | 1 + src/Managing.Api/appsettings.Sandbox.json | 1 + .../appsettings.SandboxLocal.json | 1 + src/Managing.Api/appsettings.json | 1 + src/Managing.Application/Users/UserService.cs | 34 +++-- src/Managing.Bootstrap/ApiBootstrap.cs | 49 ++++++-- 12 files changed, 188 insertions(+), 29 deletions(-) create mode 100644 src/Managing.Api/README-ORLEANS-CONFIGURATION.md create mode 100644 src/Managing.Api/appsettings.Development.json diff --git a/src/Managing.Api/Program.cs b/src/Managing.Api/Program.cs index ec2079f..fc694bf 100644 --- a/src/Managing.Api/Program.cs +++ b/src/Managing.Api/Program.cs @@ -238,7 +238,7 @@ builder.Services.AddScoped(); builder.Services.RegisterApiDependencies(builder.Configuration); -// Orleans Configuration +// Orleans is always configured, but grains can be controlled builder.Host.ConfigureOrleans(builder.Configuration, builder.Environment.IsProduction()); builder.Services.AddEndpointsApiExplorer(); diff --git a/src/Managing.Api/README-ORLEANS-CONFIGURATION.md b/src/Managing.Api/README-ORLEANS-CONFIGURATION.md new file mode 100644 index 0000000..3b545ed --- /dev/null +++ b/src/Managing.Api/README-ORLEANS-CONFIGURATION.md @@ -0,0 +1,116 @@ +# Orleans Configuration + +This document explains how to configure Orleans usage in the Managing API. + +## Overview + +The Managing API now always runs Orleans for infrastructure, but supports configurable grain execution through the `RunOrleansGrains` configuration option. This allows you to control whether Orleans grains (bots, timers, reminders) are active during runtime. + +## Configuration Options + +### 1. Configuration File (appsettings.json) + +Add the Orleans grain control parameter to your appsettings file: + +```json +{ + "RunOrleansGrains": true +} +``` + +- `RunOrleansGrains`: Boolean value that controls whether Orleans grains (bots, timers, reminders) are active + - `true` (default): Grains are active and can run timers/reminders + - `false`: Grains are inactive, no timers or reminders will execute + +**Note**: Orleans infrastructure is always enabled and configured. This flag only controls grain execution. + +### 2. Environment Variables + +You can also control Orleans grain execution through environment variables: + +```bash +# Enable Orleans grains (bots, timers, reminders) +export RUN_ORLEANS_GRAINS=true + +# Disable Orleans grains (infrastructure still runs) +export RUN_ORLEANS_GRAINS=false +``` + +**Note**: Environment variables take precedence over configuration file settings. + +## Configuration Files + +The following configuration files have been updated with Orleans grain control settings: + +- `appsettings.json` - Base configuration (RunOrleansGrains: true) +- `appsettings.Development.json` - Development configuration (RunOrleansGrains: false) +- `appsettings.Oda.json` - Oda environment (RunOrleansGrains: true) +- `appsettings.Oda-docker.json` - Oda Docker environment (RunOrleansGrains: true) +- `appsettings.Sandbox.json` - Sandbox environment (RunOrleansGrains: true) +- `appsettings.SandboxLocal.json` - Local Sandbox environment (RunOrleansGrains: true) +- `appsettings.Production.json` - Production environment (RunOrleansGrains: true) + +## Use Cases + +### Development Environment +- Set `RunOrleansGrains: false` to run Orleans infrastructure without active grains +- Useful for development and testing without bot execution overhead + +### Testing Environment +- Set `RunOrleansGrains: false` to test Orleans infrastructure without running bots +- Useful for integration testing without triggering actual trading operations + +### Production Environment +- Set `RunOrleansGrains: true` to enable full Orleans grain functionality +- Required for production trading bot operations + +### Docker/Container Environment +- Use environment variables for easy configuration +- Example: `docker run -e RUN_ORLEANS_GRAINS=false ...` + +## Implementation Details + +The Orleans configuration is implemented in: + +1. **ApiBootstrap.cs** - Orleans configuration logic +2. **Program.cs** - Application startup Orleans configuration + +## Security Considerations + +- Orleans configuration is not sensitive and can be included in configuration files +- Environment variables provide runtime flexibility without code changes +- Default behavior maintains backward compatibility (Orleans enabled by default) + +## Troubleshooting + +### Orleans Not Starting +1. Orleans infrastructure is always enabled +2. Ensure PostgreSQL connection string for Orleans is configured +3. Check application logs for connection errors + +### Grains Not Running +1. Check `RunOrleansGrains` configuration value +2. Verify environment variable `RUN_ORLEANS_GRAINS` is not set to `false` +3. Ensure Orleans infrastructure is running properly + +### Configuration Not Applied +1. Verify configuration file syntax +2. Check environment variable spelling (`RUN_ORLEANS_GRAINS`) +3. Restart the application after configuration changes + +## Migration + +Existing deployments will continue to work as Orleans grains are enabled by default. To control Orleans grain behavior: + +### Disable Grains (Keep Orleans Infrastructure) +1. Add `"RunOrleansGrains": false` to your appsettings file, or +2. Set environment variable `RUN_ORLEANS_GRAINS=false` + +### Development/Testing Setup +```json +{ + "RunOrleansGrains": false +} +``` + +**Note**: Orleans infrastructure is always enabled and cannot be disabled. diff --git a/src/Managing.Api/appsettings.Development.json b/src/Managing.Api/appsettings.Development.json new file mode 100644 index 0000000..c6a1b25 --- /dev/null +++ b/src/Managing.Api/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "RunOrleansGrains": false, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/src/Managing.Api/appsettings.Oda-Sandbox.json b/src/Managing.Api/appsettings.Oda-Sandbox.json index 47903ff..1472eed 100644 --- a/src/Managing.Api/appsettings.Oda-Sandbox.json +++ b/src/Managing.Api/appsettings.Oda-Sandbox.json @@ -30,5 +30,6 @@ "RequestsChannelId": 1018589494968078356, "ButtonExpirationMinutes": 10 }, + "RunOrleansGrains": true, "AllowedHosts": "*" } \ No newline at end of file diff --git a/src/Managing.Api/appsettings.Oda-docker.json b/src/Managing.Api/appsettings.Oda-docker.json index bb705d9..2925b93 100644 --- a/src/Managing.Api/appsettings.Oda-docker.json +++ b/src/Managing.Api/appsettings.Oda-docker.json @@ -30,5 +30,6 @@ "RequestsChannelId": 1018589494968078356, "ButtonExpirationMinutes": 2 }, + "RunOrleansGrains": true, "AllowedHosts": "*" } \ No newline at end of file diff --git a/src/Managing.Api/appsettings.Oda.json b/src/Managing.Api/appsettings.Oda.json index e8d65d8..6c21b12 100644 --- a/src/Managing.Api/appsettings.Oda.json +++ b/src/Managing.Api/appsettings.Oda.json @@ -37,6 +37,7 @@ "RequestsChannelId": 1018589494968078356, "ButtonExpirationMinutes": 2 }, + "RunOrleansGrains": true, "AllowedHosts": "*", "WorkerBotManager": true, "WorkerBalancesTracking": false, diff --git a/src/Managing.Api/appsettings.Production.json b/src/Managing.Api/appsettings.Production.json index ed1a2ad..4d9fb0c 100644 --- a/src/Managing.Api/appsettings.Production.json +++ b/src/Managing.Api/appsettings.Production.json @@ -30,6 +30,7 @@ "Sentry": { "Dsn": "https://698e00d7cb404b049aff3881e5a47f6b@bugcenter.apps.managing.live/1" }, + "RunOrleansGrains": true, "AllowedHosts": "*", "WorkerBotManager": true, "WorkerBalancesTracking": true, diff --git a/src/Managing.Api/appsettings.Sandbox.json b/src/Managing.Api/appsettings.Sandbox.json index 35aab81..6c1c574 100644 --- a/src/Managing.Api/appsettings.Sandbox.json +++ b/src/Managing.Api/appsettings.Sandbox.json @@ -35,5 +35,6 @@ "Sentry": { "Dsn": "https://698e00d7cb404b049aff3881e5a47f6b@bugcenter.apps.managing.live/1" }, + "RunOrleansGrains": true, "AllowedHosts": "*" } \ No newline at end of file diff --git a/src/Managing.Api/appsettings.SandboxLocal.json b/src/Managing.Api/appsettings.SandboxLocal.json index 9e57225..8815ab6 100644 --- a/src/Managing.Api/appsettings.SandboxLocal.json +++ b/src/Managing.Api/appsettings.SandboxLocal.json @@ -24,6 +24,7 @@ "ElasticConfiguration": { "Uri": "http://elasticsearch:9200" }, + "RunOrleansGrains": true, "AllowedHosts": "*", "WorkerBotManager": false, "WorkerBalancesTracking": false diff --git a/src/Managing.Api/appsettings.json b/src/Managing.Api/appsettings.json index dbfa6c6..b4cd182 100644 --- a/src/Managing.Api/appsettings.json +++ b/src/Managing.Api/appsettings.json @@ -66,5 +66,6 @@ "FundingRateChannelId": 1263566138709774336, "ButtonExpirationMinutes": 10 }, + "RunOrleansGrains": true, "AllowedHosts": "*" } \ No newline at end of file diff --git a/src/Managing.Application/Users/UserService.cs b/src/Managing.Application/Users/UserService.cs index f0cd2b3..707e5d1 100644 --- a/src/Managing.Application/Users/UserService.cs +++ b/src/Managing.Application/Users/UserService.cs @@ -5,6 +5,7 @@ using Managing.Application.Abstractions.Services; using Managing.Common; using Managing.Domain.Accounts; using Managing.Domain.Users; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace Managing.Application.Users; @@ -17,20 +18,7 @@ public class UserService : IUserService private readonly ILogger _logger; private readonly ICacheService _cacheService; private readonly IGrainFactory _grainFactory; - - private string[] authorizedAddresses = - [ - "0x6781920674dA695aa5120d95D80c4B1788046806", // Macbook - "0xA2B43AFF0992a47838DF2e6099A8439981f0B717", // Phone - "0xAD4bcf258852e9d47E580798d312E1a52D59E721", // Razil - "0xAd6D6c80910096b40e45690506a9f1052e072dCB", // Teru - "0x309b9235edbe1C6f840816771c6C21aDa6c275EE", // Cowchain - "0x23AA99254cfaA2c374bE2bA5B55C68018cCdFCb3", // Local optiflex - "0x932167388dD9aad41149b3cA23eBD489E2E2DD78", // Embedded wallet - "0x66CB57Fe3f53cE57376421106dFDa2D39186cBd0", // Embedded wallet optiflex - "0x7baBf95621f22bEf2DB67E500D022Ca110722FaD", // DevCowchain - "0xc8bC497534d0A43bAb2BBA9BA94d46D9Ddfaea6B" // DevCowchain2 - ]; + private readonly string[] _authorizedAddresses; public UserService( IEvmManager evmManager, @@ -38,7 +26,8 @@ public class UserService : IUserService IAccountService accountService, ILogger logger, ICacheService cacheService, - IGrainFactory grainFactory) + IGrainFactory grainFactory, + IConfiguration configuration) { _evmManager = evmManager; _userRepository = userRepository; @@ -46,6 +35,11 @@ public class UserService : IUserService _logger = logger; _cacheService = cacheService; _grainFactory = grainFactory; + + var authorizedAddressesString = configuration["AUTHORIZED_ADDRESSES"] ?? string.Empty; + _authorizedAddresses = string.IsNullOrEmpty(authorizedAddressesString) + ? Array.Empty() + : authorizedAddressesString.Split(';', StringSplitOptions.RemoveEmptyEntries); } public async Task Authenticate(string name, string address, string message, string signature) @@ -60,11 +54,11 @@ public class UserService : IUserService $"Message not good : {message} - Address : {address} - User : {name} - Signature : {signature}"); } - // if (!authorizedAddresses.Contains(recoveredAddress)) - // { - // _logger.LogWarning($"Address {recoveredAddress} not authorized"); - // throw new Exception("Address not authorized"); - // } + if (!_authorizedAddresses.Contains(recoveredAddress.ToLower())) + { + _logger.LogWarning($"Address {recoveredAddress} not authorized"); + throw new Exception("Address not authorized"); + } if (recoveredAddress == null || !recoveredAddress.Equals(address)) { diff --git a/src/Managing.Bootstrap/ApiBootstrap.cs b/src/Managing.Bootstrap/ApiBootstrap.cs index f4296b3..a117f58 100644 --- a/src/Managing.Bootstrap/ApiBootstrap.cs +++ b/src/Managing.Bootstrap/ApiBootstrap.cs @@ -75,6 +75,19 @@ public static class ApiBootstrap public static IHostBuilder ConfigureOrleans(this IHostBuilder hostBuilder, IConfiguration configuration, bool isProduction) { + // Check if Orleans grains should be active using root-level configuration + var runOrleansGrains = configuration.GetValue("RunOrleansGrains", true); + + // Check environment variable as override + var runOrleansGrainsEnv = Environment.GetEnvironmentVariable("RUN_ORLEANS_GRAINS"); + + if (!string.IsNullOrEmpty(runOrleansGrainsEnv) && + bool.TryParse(runOrleansGrainsEnv, out var runOrleansGrainsFromEnv)) + { + runOrleansGrains = runOrleansGrainsFromEnv; + } + + var postgreSqlConnectionString = configuration.GetSection("PostgreSql")["Orleans"]; return hostBuilder.UseOrleans(siloBuilder => @@ -85,12 +98,17 @@ public static class ApiBootstrap { options.ConnectionString = postgreSqlConnectionString; options.Invariant = "Npgsql"; - }) - .UseAdoNetReminderService(options => + }); + + // Conditionally configure reminder service based on flag + if (runOrleansGrains) + { + siloBuilder.UseAdoNetReminderService(options => { options.ConnectionString = postgreSqlConnectionString; options.Invariant = "Npgsql"; }); + } // Configure networking for better silo communication siloBuilder @@ -101,18 +119,33 @@ public static class ApiBootstrap options.ServiceId = "ManagingApp"; options.ClusterId = configuration["ASPNETCORE_ENVIRONMENT"] ?? "Development"; }) - .Configure(options => - { - // Configure grain collection to prevent memory issues - options.CollectionAge = TimeSpan.FromMinutes(10); - options.CollectionQuantum = TimeSpan.FromMinutes(1); - }) .Configure(options => { // Configure messaging for better reliability options.ResponseTimeout = TimeSpan.FromSeconds(30); }); + // Conditionally configure grain execution based on flag + if (runOrleansGrains) + { + siloBuilder.Configure(options => + { + // Enable grain collection for active grains + options.CollectionAge = TimeSpan.FromMinutes(10); + options.CollectionQuantum = TimeSpan.FromMinutes(1); + }); + } + else + { + // Disable grain execution completely + siloBuilder.Configure(options => + { + // Disable grain collection to prevent grains from running + options.CollectionAge = TimeSpan.FromDays(365); // Very long collection age + options.CollectionQuantum = TimeSpan.FromDays(1); // Very long quantum + }); + } + siloBuilder .ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Information));