diff --git a/OrleansGettingStarted.sln b/OrleansGettingStarted.sln
index f088b18..3482f8c 100644
--- a/OrleansGettingStarted.sln
+++ b/OrleansGettingStarted.sln
@@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kritner.OrleansGettingStart
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kritner.OrleansGettingStarted.SiloHost", "src\Kritner.OrleansGettingStarted.SiloHost\Kritner.OrleansGettingStarted.SiloHost.csproj", "{60C38B38-65C6-4F8F-AF7B-37ACC1D8E4FB}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kritner.OrleansGettingStarted.Common", "src\Kritner.OrleansGettingStarted.Common\Kritner.OrleansGettingStarted.Common.csproj", "{E7346FF3-2DB9-430A-8A6E-7949A8B470B2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -35,6 +37,10 @@ Global
{60C38B38-65C6-4F8F-AF7B-37ACC1D8E4FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{60C38B38-65C6-4F8F-AF7B-37ACC1D8E4FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{60C38B38-65C6-4F8F-AF7B-37ACC1D8E4FB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E7346FF3-2DB9-430A-8A6E-7949A8B470B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7346FF3-2DB9-430A-8A6E-7949A8B470B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E7346FF3-2DB9-430A-8A6E-7949A8B470B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E7346FF3-2DB9-430A-8A6E-7949A8B470B2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -44,6 +50,7 @@ Global
{A2997108-2330-4544-B3B0-4EF2B4537E14} = {E9107609-5D2A-4988-81F6-EDF031856CD0}
{93D88312-0369-4858-8F2E-1A0F11FCB224} = {E9107609-5D2A-4988-81F6-EDF031856CD0}
{60C38B38-65C6-4F8F-AF7B-37ACC1D8E4FB} = {E9107609-5D2A-4988-81F6-EDF031856CD0}
+ {E7346FF3-2DB9-430A-8A6E-7949A8B470B2} = {E9107609-5D2A-4988-81F6-EDF031856CD0}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A3713286-1C26-4298-9843-247ACCE599CC}
diff --git a/src/Kritner.OrleansGettingStarted.Client/ExtensionMethods/IClientBuilderExtensions.cs b/src/Kritner.OrleansGettingStarted.Client/ExtensionMethods/IClientBuilderExtensions.cs
new file mode 100644
index 0000000..d1083c2
--- /dev/null
+++ b/src/Kritner.OrleansGettingStarted.Client/ExtensionMethods/IClientBuilderExtensions.cs
@@ -0,0 +1,54 @@
+using Kritner.OrleansGettingStarted.Common.Config;
+using Microsoft.Extensions.Options;
+using Orleans;
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Text;
+
+namespace Kritner.OrleansGettingStarted.Client.ExtensionMethods
+{
+ public static class IClientBuilderExtensions
+ {
+ ///
+ /// Configures clustering for the Orleans Client based on
+ /// the Orleans environment.
+ ///
+ /// The client builder.
+ /// The Orleans configuration options.
+ /// The environment.
+ public static IClientBuilder ConfigureClustering(
+ this IClientBuilder builder,
+ IOptions orleansConfigOptions,
+ string environmentName
+ )
+ {
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+ if (orleansConfigOptions.Value == default(OrleansConfig))
+ {
+ throw new ArgumentException(nameof(orleansConfigOptions));
+ }
+
+ switch (environmentName.ToLower())
+ {
+ case "dev":
+ builder.UseLocalhostClustering();
+ break;
+ default:
+ var orleansConfig = orleansConfigOptions.Value;
+ List nodes = new List();
+ foreach (var node in orleansConfig.NodeIpAddresses)
+ {
+ nodes.Add(new IPEndPoint(IPAddress.Parse(node), orleansConfig.GatewayPort));
+ }
+ builder.UseStaticClustering(nodes.ToArray());
+ break;
+ }
+
+ return builder;
+ }
+ }
+}
diff --git a/src/Kritner.OrleansGettingStarted.Client/Kritner.OrleansGettingStarted.Client.csproj b/src/Kritner.OrleansGettingStarted.Client/Kritner.OrleansGettingStarted.Client.csproj
index 9921da6..b142122 100644
--- a/src/Kritner.OrleansGettingStarted.Client/Kritner.OrleansGettingStarted.Client.csproj
+++ b/src/Kritner.OrleansGettingStarted.Client/Kritner.OrleansGettingStarted.Client.csproj
@@ -6,12 +6,19 @@
+
+
+
+
+
+
+
diff --git a/src/Kritner.OrleansGettingStarted.Client/Program.cs b/src/Kritner.OrleansGettingStarted.Client/Program.cs
index dc9009c..01cb673 100644
--- a/src/Kritner.OrleansGettingStarted.Client/Program.cs
+++ b/src/Kritner.OrleansGettingStarted.Client/Program.cs
@@ -1,21 +1,33 @@
using Kritner.OrleansGettingStarted.Client.OrleansFunctionExamples;
+using Kritner.OrleansGettingStarted.Common.Config;
+using Kritner.OrleansGettingStarted.Common.Helpers;
using Kritner.OrleansGettingStarted.GrainInterfaces;
-using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
using Orleans;
using Orleans.Configuration;
using Orleans.Runtime;
using System;
using System.Threading.Tasks;
+using Kritner.OrleansGettingStarted.Common;
+using Kritner.OrleansGettingStarted.Client.ExtensionMethods;
namespace Kritner.OrleansGettingStarted.Client
{
public class Program
{
+ private static Startup Startup;
+ private static IServiceProvider ServiceProvider;
const int initializeAttemptsBeforeFailing = 5;
private static int attempt = 0;
static int Main(string[] args)
{
+ Startup = ConsoleAppConfigurator.BootstrapApp();
+ var serviceCollection = new ServiceCollection();
+ Startup.ConfigureServices(serviceCollection);
+ ServiceProvider = serviceCollection.BuildServiceProvider();
+
return RunMainAsync().Result;
}
@@ -44,7 +56,10 @@ private static async Task StartClientWithRetries()
attempt = 0;
IClusterClient client;
client = new ClientBuilder()
- .UseLocalhostClustering()
+ .ConfigureClustering(
+ ServiceProvider.GetService>(),
+ Startup.HostingEnvironment.EnvironmentName
+ )
.Configure(options =>
{
options.ClusterId = "dev";
diff --git a/src/Kritner.OrleansGettingStarted.Common/Config/OrleansConfig.cs b/src/Kritner.OrleansGettingStarted.Common/Config/OrleansConfig.cs
new file mode 100644
index 0000000..b34ae36
--- /dev/null
+++ b/src/Kritner.OrleansGettingStarted.Common/Config/OrleansConfig.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Kritner.OrleansGettingStarted.Common.Config
+{
+ ///
+ /// Contains properties utilized for configuration Orleans
+ /// Clients and Cluster Nodes.
+ ///
+ public class OrleansConfig
+ {
+ ///
+ /// The IP addresses that will be utilized in the cluster.
+ /// First IP address is the primary.
+ ///
+ public string[] NodeIpAddresses { get; set; }
+ ///
+ /// The port used for Client to Server communication.
+ ///
+ public int GatewayPort { get; set; }
+ ///
+ /// The port for Silo to Silo communication
+ ///
+ public int SiloPort { get; set; }
+ }
+}
diff --git a/src/Kritner.OrleansGettingStarted.Common/Helpers/ConsoleAppConfigurator.cs b/src/Kritner.OrleansGettingStarted.Common/Helpers/ConsoleAppConfigurator.cs
new file mode 100644
index 0000000..6e17e94
--- /dev/null
+++ b/src/Kritner.OrleansGettingStarted.Common/Helpers/ConsoleAppConfigurator.cs
@@ -0,0 +1,55 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Hosting.Internal;
+using System;
+using System.IO;
+
+namespace Kritner.OrleansGettingStarted.Common.Helpers
+{
+ public static class ConsoleAppConfigurator
+ {
+ public static Startup BootstrapApp()
+ {
+ var environment = GetEnvironment();
+ var hostingEnvironment = GetHostingEnvironment(environment);
+ var configurationBuilder = CreateConfigurationBuilder(environment);
+
+ return new Startup(hostingEnvironment, configurationBuilder);
+ }
+
+ private static string GetEnvironment()
+ {
+ var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
+ if (string.IsNullOrEmpty(environmentName))
+ {
+ return "dev";
+ }
+
+ return environmentName;
+ }
+
+ private static IHostingEnvironment GetHostingEnvironment(string environmentName)
+ {
+ return new HostingEnvironment
+ {
+ EnvironmentName = environmentName,
+ ApplicationName = AppDomain.CurrentDomain.FriendlyName,
+ ContentRootPath = AppDomain.CurrentDomain.BaseDirectory,
+ ContentRootFileProvider = new PhysicalFileProvider(AppDomain.CurrentDomain.BaseDirectory)
+ };
+ }
+
+ private static IConfigurationBuilder CreateConfigurationBuilder(string environmentName)
+ {
+ var config = new ConfigurationBuilder()
+ .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true)
+ .AddEnvironmentVariables();
+
+ return config;
+ }
+ }
+}
diff --git a/src/Kritner.OrleansGettingStarted.Common/Kritner.OrleansGettingStarted.Common.csproj b/src/Kritner.OrleansGettingStarted.Common/Kritner.OrleansGettingStarted.Common.csproj
new file mode 100644
index 0000000..666f5aa
--- /dev/null
+++ b/src/Kritner.OrleansGettingStarted.Common/Kritner.OrleansGettingStarted.Common.csproj
@@ -0,0 +1,16 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Kritner.OrleansGettingStarted.Common/Startup.cs b/src/Kritner.OrleansGettingStarted.Common/Startup.cs
new file mode 100644
index 0000000..f51995c
--- /dev/null
+++ b/src/Kritner.OrleansGettingStarted.Common/Startup.cs
@@ -0,0 +1,28 @@
+using Kritner.OrleansGettingStarted.Common.Config;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+
+namespace Kritner.OrleansGettingStarted.Common
+{
+ public class Startup
+ {
+ public IHostingEnvironment HostingEnvironment { get; }
+ public IConfiguration Configuration { get; }
+
+ public Startup(
+ IHostingEnvironment hostingEnvironment,
+ IConfigurationBuilder configurationBuilder
+ )
+ {
+ HostingEnvironment = hostingEnvironment;
+ Configuration = configurationBuilder.Build();
+ }
+
+ public void ConfigureServices(IServiceCollection serviceCollection)
+ {
+ serviceCollection.AddOptions();
+ serviceCollection.Configure(Configuration.GetSection(nameof(OrleansConfig)));
+ }
+ }
+}
diff --git a/src/Kritner.OrleansGettingStarted.SiloHost/ExtensionMethods/ISiloHostBuilderExtensions.cs b/src/Kritner.OrleansGettingStarted.SiloHost/ExtensionMethods/ISiloHostBuilderExtensions.cs
new file mode 100644
index 0000000..5ec46b6
--- /dev/null
+++ b/src/Kritner.OrleansGettingStarted.SiloHost/ExtensionMethods/ISiloHostBuilderExtensions.cs
@@ -0,0 +1,54 @@
+using Kritner.OrleansGettingStarted.Common.Config;
+using Microsoft.Extensions.Options;
+using Orleans.Hosting;
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Text;
+
+namespace Kritner.OrleansGettingStarted.SiloHost.ExtensionMethods
+{
+ public static class ISiloHostBuilderExtensions
+ {
+ ///
+ /// Configures clustering for the Orleans Silo Host based on
+ /// the Orleans environment.
+ ///
+ /// The silo host builder.
+ /// The Orleans configuration options.
+ /// The environment.
+ public static ISiloHostBuilder ConfigureClustering(
+ this ISiloHostBuilder builder,
+ IOptions orleansConfigOptions,
+ string environmentName
+ )
+ {
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+ if (orleansConfigOptions.Value == default(OrleansConfig))
+ {
+ throw new ArgumentException(nameof(orleansConfigOptions));
+ }
+
+ switch (environmentName.ToLower())
+ {
+ case "dev":
+ builder.UseLocalhostClustering();
+ break;
+ default:
+ var orleansConfig = orleansConfigOptions.Value;
+ builder.UseDevelopmentClustering(
+ new IPEndPoint(
+ IPAddress.Parse(orleansConfig.NodeIpAddresses[0]),
+ orleansConfig.SiloPort
+ )
+ );
+ break;
+ }
+
+ return builder;
+ }
+ }
+}
diff --git a/src/Kritner.OrleansGettingStarted.SiloHost/Kritner.OrleansGettingStarted.SiloHost.csproj b/src/Kritner.OrleansGettingStarted.SiloHost/Kritner.OrleansGettingStarted.SiloHost.csproj
index c2670aa..095d23e 100644
--- a/src/Kritner.OrleansGettingStarted.SiloHost/Kritner.OrleansGettingStarted.SiloHost.csproj
+++ b/src/Kritner.OrleansGettingStarted.SiloHost/Kritner.OrleansGettingStarted.SiloHost.csproj
@@ -12,8 +12,14 @@
+
+
+
+
+
+
diff --git a/src/Kritner.OrleansGettingStarted.SiloHost/Program.cs b/src/Kritner.OrleansGettingStarted.SiloHost/Program.cs
index 5df0e62..2fb8b98 100644
--- a/src/Kritner.OrleansGettingStarted.SiloHost/Program.cs
+++ b/src/Kritner.OrleansGettingStarted.SiloHost/Program.cs
@@ -1,8 +1,12 @@
-using Kritner.OrleansGettingStarted.GrainInterfaces;
+using Kritner.OrleansGettingStarted.Common;
+using Kritner.OrleansGettingStarted.Common.Config;
+using Kritner.OrleansGettingStarted.Common.Helpers;
using Kritner.OrleansGettingStarted.Grains;
+using Kritner.OrleansGettingStarted.SiloHost.ExtensionMethods;
using Kritner.OrleansGettingStarted.SiloHost.Helpers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
using Orleans;
using Orleans.Configuration;
using Orleans.Hosting;
@@ -14,8 +18,16 @@ namespace Kritner.OrleansGettingStarted.SiloHost
{
public class Program
{
+ private static Startup Startup;
+ private static IServiceProvider ServiceProvider;
+
public static int Main(string[] args)
{
+ Startup = ConsoleAppConfigurator.BootstrapApp();
+ var serviceCollection = new ServiceCollection();
+ Startup.ConfigureServices(serviceCollection);
+ ServiceProvider = serviceCollection.BuildServiceProvider();
+
return RunMainAsync().Result;
}
@@ -42,7 +54,10 @@ private static async Task StartSilo()
{
// define the cluster configuration
var builder = new SiloHostBuilder()
- .UseLocalhostClustering()
+ .ConfigureClustering(
+ ServiceProvider.GetService>(),
+ Startup.HostingEnvironment.EnvironmentName
+ )
.Configure(options =>
{
options.ClusterId = "dev";
diff --git a/src/_appsettings/appsettings.dev.json b/src/_appsettings/appsettings.dev.json
new file mode 100644
index 0000000..19cec60
--- /dev/null
+++ b/src/_appsettings/appsettings.dev.json
@@ -0,0 +1,7 @@
+{
+ "OrleansConfig" : {
+ "NodeIpAddresses" : ["0.0.0.0"],
+ "GatewayPort" : -1,
+ "SiloPort" : -1
+ }
+}
\ No newline at end of file
diff --git a/src/_appsettings/appsettings.json b/src/_appsettings/appsettings.json
new file mode 100644
index 0000000..5d7d7a1
--- /dev/null
+++ b/src/_appsettings/appsettings.json
@@ -0,0 +1,7 @@
+{
+ "OrleansConfig" : {
+ "NodeIpAddresses" : ["192.168.1.105", "192.168.1.106"],
+ "GatewayPort" : 30000,
+ "SiloPort" : 11111
+ }
+}
\ No newline at end of file