Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Orleans.TestingHost support test clusters without legacy configuration #3878

Merged
merged 1 commit into from
Jan 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Orleans.sln
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AWS", "AWS", "{DA8E126B-BCD
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orleans.Clustering.AdoNet", "src\AdoNet\Orleans.Clustering.AdoNet\Orleans.Clustering.AdoNet.csproj", "{CE21A15A-E376-4B81-BDA6-3AB610CFE03A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orleans.TestingHost.Tests", "test\Orleans.TestingHost.Tests\Orleans.TestingHost.Tests.csproj", "{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orleans.Persistence.AdoNet", "src\AdoNet\Orleans.Persistence.AdoNet\Orleans.Persistence.AdoNet.csproj", "{3E2C5440-D6C5-4EB8-8D34-10707B322263}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orleans.Statistics.AdoNet", "src\AdoNet\Orleans.Statistics.AdoNet\Orleans.Statistics.AdoNet.csproj", "{57004849-FB72-4278-B587-671904ED455C}"
Expand Down Expand Up @@ -1098,6 +1100,18 @@ Global
{CE21A15A-E376-4B81-BDA6-3AB610CFE03A}.Release|x64.Build.0 = Release|Any CPU
{CE21A15A-E376-4B81-BDA6-3AB610CFE03A}.Release|x86.ActiveCfg = Release|Any CPU
{CE21A15A-E376-4B81-BDA6-3AB610CFE03A}.Release|x86.Build.0 = Release|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Debug|x64.ActiveCfg = Debug|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Debug|x64.Build.0 = Debug|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Debug|x86.ActiveCfg = Debug|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Debug|x86.Build.0 = Debug|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Release|Any CPU.Build.0 = Release|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Release|x64.ActiveCfg = Release|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Release|x64.Build.0 = Release|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Release|x86.ActiveCfg = Release|Any CPU
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8}.Release|x86.Build.0 = Release|Any CPU
{3E2C5440-D6C5-4EB8-8D34-10707B322263}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E2C5440-D6C5-4EB8-8D34-10707B322263}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E2C5440-D6C5-4EB8-8D34-10707B322263}.Debug|x64.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -1279,6 +1293,7 @@ Global
{1F28D680-7B22-4EA7-BA92-163D4FD76F5E} = {A6573187-FD0D-4DF7-91D1-03E07E470C0A}
{4C5D66BF-EE1C-4DD8-8551-D1B7F3768A34} = {FE2E08C6-9C3B-4AEE-AE07-CCA387580D7A}
{DA8E126B-BCDB-4E8F-BFB9-2DBFD41F8F70} = {FE2E08C6-9C3B-4AEE-AE07-CCA387580D7A}
{18B9F2D3-ABA1-4D0C-88A9-25FEC3F79CE8} = {A6573187-FD0D-4DF7-91D1-03E07E470C0A}
{CE21A15A-E376-4B81-BDA6-3AB610CFE03A} = {EB2EDE59-5021-42EE-A97A-D59939B39C66}
{3E2C5440-D6C5-4EB8-8D34-10707B322263} = {EB2EDE59-5021-42EE-A97A-D59939B39C66}
{57004849-FB72-4278-B587-671904ED455C} = {EB2EDE59-5021-42EE-A97A-D59939B39C66}
Expand Down
19 changes: 18 additions & 1 deletion Test.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,24 @@ if not exist %CMDHOME%\test\Tester\%_Directory%\TestVersionGrainsV2\ mkdir %CMDH
copy %CMDHOME%\test\Versions\TestVersionGrains\%_Directory%\* %CMDHOME%\test\Tester\%_Directory%\TestVersionGrainsV1\
copy %CMDHOME%\test\Versions\TestVersionGrains2\%_Directory%\* %CMDHOME%\test\Tester\%_Directory%\TestVersionGrainsV2\

set TESTS=%CMDHOME%\test\TesterAzureUtils,%CMDHOME%\test\TesterInternal,%CMDHOME%\test\Tester,%CMDHOME%\test\DefaultCluster.Tests,%CMDHOME%\test\NonSilo.Tests,%CMDHOME%\test\AWSUtils.Tests,%CMDHOME%\test\BondUtils.Tests,%CMDHOME%\test\Consul.Tests,%CMDHOME%\test\GoogleUtils.Tests,%CMDHOME%\test\ServiceBus.Tests,%CMDHOME%\test\TestServiceFabric,%CMDHOME%\test\TesterSQLUtils,%CMDHOME%\test\TesterZooKeeperUtils,%CMDHOME%\test\RuntimeCodeGen.Tests,%CMDHOME%\test\Orleans.Transactions.Tests,%CMDHOME%\test\Orleans.Transactions.Azure.Test
set TESTS=^
%CMDHOME%\test\TesterAzureUtils,^
%CMDHOME%\test\TesterInternal,^
%CMDHOME%\test\Tester,^
%CMDHOME%\test\DefaultCluster.Tests,^
%CMDHOME%\test\NonSilo.Tests,^
%CMDHOME%\test\AWSUtils.Tests,^
%CMDHOME%\test\BondUtils.Tests,^
%CMDHOME%\test\Consul.Tests,^
%CMDHOME%\test\GoogleUtils.Tests,^
%CMDHOME%\test\ServiceBus.Tests,^
%CMDHOME%\test\TestServiceFabric,^
%CMDHOME%\test\TesterSQLUtils,^
%CMDHOME%\test\TesterZooKeeperUtils,^
%CMDHOME%\test\RuntimeCodeGen.Tests,^
%CMDHOME%\test\Orleans.Transactions.Tests,^
%CMDHOME%\test\Orleans.Transactions.Azure.Test,^
%CMDHOME%\test\Orleans.TestingHost.Tests

if []==[%TEST_FILTERS%] set TEST_FILTERS=-trait Category=BVT -trait Category=SlowBVT

Expand Down
1 change: 1 addition & 0 deletions src/Orleans.Core/Configuration/ClientConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace Orleans.Runtime.Configuration
/// <summary>
/// Orleans client configuration parameters.
/// </summary>
[Serializable]
public class ClientConfiguration : MessagingConfiguration, IStatisticsConfiguration
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
Expand All @@ -16,13 +17,25 @@ internal static class LegacyConfigurationExtensions
private const int ClusterClientDefaultProviderInitStage = 1000;
private const int ClusterClientDefaultProviderStartStage = 2000;

public static IServiceCollection AddLegacyClientConfigurationSupport(this IServiceCollection services, ClientConfiguration configuration)
public static IServiceCollection AddLegacyClientConfigurationSupport(this IServiceCollection services, ClientConfiguration configuration = null)
{
if (services.Any(service => service.ServiceType == typeof(ClientConfiguration)))
if (TryGetClientConfiguration(services) != null)
{
throw new InvalidOperationException("Cannot configure legacy ClientConfiguration support twice");
}

if (configuration == null)
{
try
{
configuration = ClientConfiguration.StandardLoad();
}
catch (FileNotFoundException)
{
configuration = new ClientConfiguration();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure swallowing FileNotFoundException is a good idea, didn't this change original behavior? And for users who wanted to do StandardLoad from a config file, it hided exception from them which make it harder for them to notice that they made a mistake somewhere.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, this is for the path we're users didn't explicitly pass a config object. If they do want, then they'll get the exception in their code when they try to load the config.
Btw, this code path will be removed as soon as the runtime itself stops requiring the legacy config in the first place

}
}

// these will eventually be removed once our code doesn't depend on the old ClientConfiguration
services.TryAddSingleton(configuration);
services.TryAddFromExisting<IMessagingConfiguration, ClientConfiguration>();
Expand Down Expand Up @@ -79,6 +92,13 @@ internal static void CopyTelemetryOptions(TelemetryConfiguration telemetryConfig
options.Consumers.Add(consumer.ConsumerType);
}
}

public static ClientConfiguration TryGetClientConfiguration(this IServiceCollection services)
{
return services
.FirstOrDefault(s => s.ServiceType == typeof(ClientConfiguration))
?.ImplementationInstance as ClientConfiguration;
}

internal static void CopyCommonMessagingOptions(IMessagingConfiguration configuration, MessagingOptions options)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Orleans.Hosting
/// </summary>
public class SerializationProviderOptions
{
public List<TypeInfo> SerializationProviders { get; set; }
public List<TypeInfo> SerializationProviders { get; set; } = new List<TypeInfo>();
public TypeInfo FallbackSerializationProvider { get; set; }
}

Expand Down
18 changes: 10 additions & 8 deletions src/Orleans.Core/Core/ClientBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Orleans.Configuration;
using Orleans.Hosting;
Expand All @@ -16,7 +17,6 @@ public class ClientBuilder : IClientBuilder
{
private readonly ServiceProviderBuilder serviceProviderBuilder = new ServiceProviderBuilder();
private bool built;
private bool clientConfigurationRegistered;

/// <inheritdoc />
public IDictionary<object, object> Properties { get; } = new Dictionary<object, object>();
Expand All @@ -40,11 +40,7 @@ public IClusterClient Build()
this.built = true;

// Configure default services and build the container.
if (!this.clientConfigurationRegistered)
{
this.UseConfiguration(ClientConfiguration.StandardLoad());
}

this.ConfigureServices(EnsureClientConfigurationConfigured);
this.ConfigureDefaults();

var serviceProvider = this.serviceProviderBuilder.BuildServiceProvider(new HostBuilderContext(this.Properties));
Expand All @@ -60,8 +56,6 @@ public IClusterClient Build()
public IClientBuilder UseConfiguration(ClientConfiguration configuration)
{
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
if (this.clientConfigurationRegistered) throw new InvalidOperationException("Base configuration has already been specified and cannot be overridden.");
this.clientConfigurationRegistered = true;

this.serviceProviderBuilder.ConfigureServices((context, services) => services.AddLegacyClientConfigurationSupport(configuration));
return this;
Expand Down Expand Up @@ -97,5 +91,13 @@ private static void ValidateSystemConfiguration(IServiceProvider serviceProvider
validator.ValidateConfiguration();
}
}

private static void EnsureClientConfigurationConfigured(IServiceCollection services)
{
if (services.TryGetClientConfiguration() == null)
{
services.AddLegacyClientConfigurationSupport();
}
}
}
}
2 changes: 1 addition & 1 deletion src/Orleans.Core/Core/ClusterClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ private void Dispose(bool disposing)
private void ThrowIfDisposedOrNotInitialized()
{
this.ThrowIfDisposed();
if (!this.IsInitialized) throw new InvalidOperationException("Client is not initialized.");
if (!this.IsInitialized) throw new InvalidOperationException($"Client is not initialized. Current client state is {this.state}.");
}

private void ThrowIfDisposedOrAlreadyInitialized()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
Expand All @@ -22,9 +22,13 @@ public interface ILegacyGatewayListProviderConfigurator

internal class LegacyGatewayListProviderConfigurator
{
public static void ConfigureServices(ClientConfiguration clientConfiguration,
public static void ConfigureServices(
ClientConfiguration clientConfiguration,
IServiceCollection services)
{
// If a gateway list provider has already been configured in the service collection, use that instead.
if (services.Any(reg => reg.ServiceType == typeof(IGatewayListProvider))) return;

ILegacyGatewayListProviderConfigurator configurator = null;
switch (clientConfiguration.GatewayProviderToUse)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

namespace Orleans.Hosting
{
internal static class LegacyClusterConfigurationExtensions
public static class LegacyClusterConfigurationExtensions
{
private const int SiloDefaultProviderInitStage = SiloLifecycleStage.RuntimeStorageServices;
private const int SiloDefaultProviderStartStage = SiloLifecycleStage.ApplicationServices;
Expand All @@ -23,7 +23,7 @@ public static IServiceCollection AddLegacyClusterConfigurationSupport(this IServ
{
if (configuration == null) throw new ArgumentNullException(nameof(configuration));

if (services.Any(service => service.ServiceType == typeof(ClusterConfiguration)))
if (services.TryGetClusterConfiguration() != null)
{
throw new InvalidOperationException("Cannot configure legacy ClusterConfiguration support twice");
}
Expand Down Expand Up @@ -136,5 +136,12 @@ public static IServiceCollection AddLegacyClusterConfigurationSupport(this IServ

return services;
}

public static ClusterConfiguration TryGetClusterConfiguration(this IServiceCollection services)
{
return services
.FirstOrDefault(s => s.ServiceType == typeof(ClusterConfiguration))
?.ImplementationInstance as ClusterConfiguration;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
Expand Down
3 changes: 2 additions & 1 deletion src/Orleans.Runtime/Silo/LegacyConfigurationWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ namespace Orleans.Runtime
{
internal class LegacyConfigurationWrapper
{
public LegacyConfigurationWrapper(IOptions<SiloOptions> siloOptions,
public LegacyConfigurationWrapper(
IOptions<SiloOptions> siloOptions,
ClusterConfiguration config)
{
var siloName = siloOptions.Value.SiloName;
Expand Down
24 changes: 12 additions & 12 deletions src/Orleans.TestingHost/AppDomainSiloHandle.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using System;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.Remoting;
using System.Threading.Tasks;
using Orleans.Runtime;
using Orleans.Runtime.Configuration;
using Microsoft.Extensions.Configuration;

namespace Orleans.TestingHost
{
Expand All @@ -28,21 +27,23 @@ public class AppDomainSiloHandle : SiloHandle
/// <summary>Creates a new silo in a remote app domain and returns a handle to it.</summary>
public static SiloHandle Create(
string siloName,
Silo.SiloType type,
Type siloBuilderFactory,
ClusterConfiguration config,
NodeConfiguration nodeConfiguration,
string applicationBase = null)
IList<IConfigurationSource> configurationSources)
{
var configBuilder = new ConfigurationBuilder();
foreach (var source in configurationSources) configBuilder.Add(source);
var configuration = configBuilder.Build();

var applicationBase = configuration[nameof(TestClusterOptions.ApplicationBaseDirectory)];
AppDomainSetup setup = GetAppDomainSetupInfo(applicationBase);

var appDomain = AppDomain.CreateDomain(siloName, null, setup);

try
{
var args = new object[] {siloName, siloBuilderFactory, config};
var serializedHostConfiguration = TestClusterHostFactory.SerializeConfigurationSources(configurationSources);
var args = new object[] {siloName, serializedHostConfiguration };

var siloHost = (AppDomainSiloHost) appDomain.CreateInstanceAndUnwrap(
var siloHost = (AppDomainSiloHost)appDomain.CreateInstanceAndUnwrap(
typeof(AppDomainSiloHost).Assembly.FullName,
typeof(AppDomainSiloHost).FullName,
false,
Expand All @@ -60,9 +61,8 @@ public static SiloHandle Create(
{
Name = siloName,
SiloHost = siloHost,
NodeConfiguration = nodeConfiguration,
SiloAddress = siloHost.SiloAddress,
Type = type,
GatewayAddress = siloHost.GatewayAddress,
AppDomain = appDomain,
AppDomainTestHook = siloHost.AppDomainTestHook,
};
Expand Down
31 changes: 9 additions & 22 deletions src/Orleans.TestingHost/AppDomainSiloHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,13 @@
using Microsoft.Extensions.DependencyInjection;
using Orleans.Providers;
using Orleans.Runtime;
using Orleans.Runtime.Configuration;
using Orleans.Runtime.GrainDirectory;
using Orleans.Runtime.Messaging;
using Orleans.Runtime.Placement;
using Orleans.Storage;
using Orleans.MultiCluster;
using Orleans.Hosting;
using Orleans.Runtime.MultiClusterNetwork;
using Orleans.Runtime.TestHooks;
using Orleans.Runtime.Providers;

namespace Orleans.TestingHost
{
Expand All @@ -25,24 +22,21 @@ public class AppDomainSiloHost : MarshalByRefObject
private readonly ISiloHost host;

/// <summary>Creates and initializes a silo in the current app domain.</summary>
/// <param name="name">Name of this silo.</param>
/// <param name="siloBuilderFactoryType">Type of silo host builder factory.</param>
/// <param name="config">Silo config data to be used for this silo.</param>
public AppDomainSiloHost(string name, Type siloBuilderFactoryType, ClusterConfiguration config)
/// <param name="appDomainName">Name of this silo.</param>
/// <param name="serializedConfigurationSources">Silo config data to be used for this silo.</param>
public AppDomainSiloHost(string appDomainName, string serializedConfigurationSources)
{
var builderFactory = (ISiloBuilderFactory)Activator.CreateInstance(siloBuilderFactoryType);
ISiloHostBuilder builder = builderFactory
.CreateSiloBuilder(name, config)
.ConfigureServices(services => services.AddSingleton<TestHooksSystemTarget>())
.ConfigureApplicationParts(parts => parts.AddFromAppDomain().AddFromApplicationBaseDirectory());
this.host = builder.Build();
InitializeTestHooksSystemTarget();
var deserializedSources = TestClusterHostFactory.DeserializeConfigurationSources(serializedConfigurationSources);
this.host = TestClusterHostFactory.CreateSiloHost(appDomainName, deserializedSources);
this.AppDomainTestHook = new AppDomainTestHooks(this.host);
}

/// <summary> SiloAddress for this silo. </summary>
public SiloAddress SiloAddress => this.host.Services.GetRequiredService<ILocalSiloDetails>().SiloAddress;


/// <summary> Gateway address for this silo. </summary>
public SiloAddress GatewayAddress => this.host.Services.GetRequiredService<ILocalSiloDetails>().GatewayAddress;

internal AppDomainTestHooks AppDomainTestHook { get; }

/// <summary>Starts the silo</summary>
Expand All @@ -56,13 +50,6 @@ public void Shutdown()
{
this.host.StopAsync().GetAwaiter().GetResult();
}

private void InitializeTestHooksSystemTarget()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is this part of logic moved to ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{
var testHook = this.host.Services.GetRequiredService<TestHooksSystemTarget>();
var providerRuntime = this.host.Services.GetRequiredService<SiloProviderRuntime>();
providerRuntime.RegisterSystemTarget(testHook);
}
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Orleans.TestingHost/ClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal static class ClientExtensions
public static ITestHooks GetTestHooks(this IClusterClient client, SiloHandle silo)
{
var internalClient = (IInternalClusterClient) client;
return internalClient.GetSystemTarget<ITestHooksSystemTarget>(Constants.TestHooksSystemTargetId, silo.ProxyAddress);
return internalClient.GetSystemTarget<ITestHooksSystemTarget>(Constants.TestHooksSystemTargetId, silo.GatewayAddress);
}
}
}
Loading