diff --git a/src/Managing.Bootstrap/ApiBootstrap.cs b/src/Managing.Bootstrap/ApiBootstrap.cs index 2d238aae..5cdfcc8f 100644 --- a/src/Managing.Bootstrap/ApiBootstrap.cs +++ b/src/Managing.Bootstrap/ApiBootstrap.cs @@ -106,8 +106,17 @@ public static class ApiBootstrap var gatewayPort = 30000 + (taskSlot - 1) * 10; // 30000, 30010, 30020, etc. var dashboardPort = 9999 + (taskSlot - 1); // 9999, 10000, 10001, etc. + // Get hostname for clustering - prioritize external IP for multi-server setups + var hostname = Environment.GetEnvironmentVariable("CAPROVER_SERVER_IP") ?? // CapRover server IP + Environment.GetEnvironmentVariable("EXTERNAL_IP") ?? // Custom external IP + Environment.GetEnvironmentVariable("HOSTNAME") ?? // Container hostname + Environment.GetEnvironmentVariable("COMPUTERNAME") ?? // Windows hostname + "localhost"; + var postgreSqlConnectionString = configuration.GetSection("PostgreSql")["Orleans"]; + Console.WriteLine($"Task Slot: {taskSlot}"); + Console.WriteLine($"Hostname: {hostname}"); Console.WriteLine($"Silo port: {siloPort}"); Console.WriteLine($"Gateway port: {gatewayPort}"); Console.WriteLine($"Dashboard port: {dashboardPort}"); @@ -122,12 +131,24 @@ public static class ApiBootstrap { options.ConnectionString = postgreSqlConnectionString; options.Invariant = "Npgsql"; + }) + .ConfigureEndpoints(IPAddress.Any, siloPort, gatewayPort) + .Configure(options => + { + options.ServiceId = "ManagingApp"; + options.ClusterId = configuration["ASPNETCORE_ENVIRONMENT"] ?? "Development"; + }) + .Configure(options => + { + // Configure silo address for multi-server clustering + options.SiloName = $"ManagingApi-{taskSlot}"; + // Orleans will use the configured endpoints for clustering }); } else { // Fallback to localhost clustering for testing or when database is unavailable - siloBuilder.UseLocalhostClustering(); + siloBuilder.UseLocalhostClustering(siloPort, gatewayPort); } // Conditionally configure reminder service based on flag @@ -140,38 +161,19 @@ public static class ApiBootstrap }); } - // Configure networking - simplified for Docker compatibility with unique ports per instance + // Configure networking - use Any for Docker containerized environments if (disableOrleansClustering) { // Use localhost clustering when clustering is disabled siloBuilder.ConfigureEndpoints(IPAddress.Loopback, siloPort, gatewayPort); } - else + else if (string.IsNullOrEmpty(postgreSqlConnectionString)) { - // Use localhost for development, proper hostname for production - if (isProduction) - { - // In production, use all interfaces with unique ports per instance - siloBuilder.ConfigureEndpoints(IPAddress.Any, siloPort, gatewayPort); - } - else - { - // In development, use localhost with unique ports per instance - siloBuilder.ConfigureEndpoints(IPAddress.Loopback, siloPort, gatewayPort); - } + // In Docker/containerized environments, use Any to allow inter-container communication + siloBuilder.ConfigureEndpoints(IPAddress.Any, siloPort, gatewayPort); } siloBuilder - .Configure(options => - { - // Configure cluster options with unique identifiers including task slot - options.ServiceId = "ManagingApp"; - options.ClusterId = configuration["ASPNETCORE_ENVIRONMENT"] ?? "Development"; - - // Add task slot to silo identity for better tracking - var siloName = $"ManagingApi-{taskSlot}"; - // Orleans will use this for internal identification - }) .Configure(options => { // Configure messaging for better reliability with increased timeouts