From 83fff96a6d621dc65d7dcc714c4d7fb0eba738d1 Mon Sep 17 00:00:00 2001 From: jason-bragg Date: Tue, 20 Feb 2018 11:20:13 -0800 Subject: [PATCH 1/2] Replaced AzureTableStorage with AzureTableGrainStorage. --- .../Hosting/ClientBuilderExtensions.cs | 46 ++++ .../Hosting/SiloBuilderExtensions.cs | 45 ++++ .../Orleans.Streaming.SQS.csproj | 1 + .../Streams/SQSAdapterFactory.cs | 68 +++-- .../Streams/SQSStreamProvider.cs | 12 - .../Streams/SQSStreamProviderUtils.cs | 9 +- .../Streams/SqsStreamOptions.cs | 17 ++ .../Storage/Provider/SiloBuilderExtensions.cs | 2 - .../Providers/Storage/AzureBlobStorage.cs | 4 +- .../Storage/AzureBlobStorageOptions.cs | 8 +- .../Hosting/ClientBuilderExtensions.cs | 49 ++++ .../Hosting/SiloBuilderExtensions.cs | 49 ++++ .../Orleans.Streaming.AzureStorage.csproj | 2 +- .../Providers/AzureConfigurationExtensions.cs | 173 ------------ .../AzureQueue/AzureQueueAdapterConstants.cs | 22 -- .../AzureQueue/AzureQueueAdapterFactory.cs | 87 +++---- .../AzureQueue/AzureQueueStreamOptions.cs | 24 ++ .../AzureQueue/AzureQueueStreamProvider.cs | 21 -- .../AzureQueueStreamProviderUtils.cs | 7 +- .../SimpleAzureQueueAdapterFactory.cs | 23 +- .../SimpleAzureQueueStreamOptions.cs | 14 + .../SimpleAzureQueueStreamProvider.cs | 11 - .../Hosting/ClientBuilderExtensions.cs | 46 ++++ .../Hosting/SiloBuilderExtensions.cs | 45 ++++ .../Orleans.Streaming.EventHubs.csproj | 1 + .../EventDataGeneratorAdapterFactory.cs | 181 +++++++++++++ .../EventDataGeneratorStreamOptions.cs | 19 ++ .../EventDataGeneratorStreamProvider.cs | 246 ------------------ .../EventHubPartitionDataGenerator.cs | 30 ++- .../MockEventHubSettings.cs | 35 --- .../AveragingCachePressureMonitor.cs | 17 +- .../EventHub/EventHubAdapterFactory.cs | 84 +++--- .../EventHub/EventHubAdapterReceiver.cs | 3 +- .../Streams/EventHub/EventHubCheckpointer.cs | 17 +- .../EventHub/EventHubQueueCacheFactory.cs | 44 ++-- .../Streams/EventHub/EventHubSettings.cs | 123 --------- .../Streams/EventHub/EventHubStreamOptions.cs | 75 ++++++ .../EventHub/EventHubStreamProvider.cs | 12 - .../EventHubStreamProviderSettings.cs | 193 -------------- .../Streams/EventHub/ICheckpointerSettings.cs | 130 --------- .../Streams/EventHub/IEventHubSettings.cs | 34 --- .../LegacyConfigurationExtensions.cs | 6 +- .../OptionLogger/IOptionsLogger.cs | 17 +- .../Configuration/Options/MessagingOptions.cs | 1 - src/Orleans.Core/Core/IClientBuilder.cs | 2 - .../ClusterClientLifecycleExtensions.cs | 33 +++ src/Orleans.Core/Logging/ErrorCodes.cs | 4 +- .../Providers/LegacyProviderConfigurator.cs | 63 +---- .../Streams/ClientStreamExtensions.cs | 53 ++++ .../Internal/IInternalStreamProvider.cs | 2 +- .../Streams/Internal/StreamConsumer.cs | 21 +- .../PersistentStreams/IStreamQueueBalancer.cs | 6 +- .../PersistentStreamProvider.cs | 131 +++++----- .../PersistentStreamProviderOptions.cs | 52 ++++ .../Providers/IStreamProviderRuntime.cs | 107 +------- ...viderImpl.cs => ProviderStartException.cs} | 7 - .../QueueAdapters/IQueueAdapterFactory.cs | 2 - .../SimpleMessageStreamProvider.cs | 4 +- src/Orleans.Core/Utils/KeyedService.cs | 43 ++- .../Hosting/StreamHostingExtensions.cs | 55 ++++ .../Orleans.Runtime.Abstractions.csproj | 4 + .../LegacyClusterConfigurationExtensions.cs | 6 +- src/Orleans.Runtime/Silo/Silo.cs | 2 +- .../Silo/SiloProviderRuntime.cs | 21 +- .../PersistentStreamPullingAgent.cs | 23 +- .../PersistentStreamPullingManager.cs | 28 +- .../ConsistentRingQueueBalancer.cs | 4 +- .../DeploymentBasedQueueBalancer.cs | 3 +- .../QueueBalancer/LeaseBasedQueueBalancer.cs | 81 +----- .../LeaseBasedQueueBalancerOptions.cs | 28 ++ .../QueueBalancer/QueueBalancerBaseClass.cs | 10 +- .../Hosting/ClientBuilderExtensions.cs | 49 ++++ .../Hosting/SiloBuilderExtensions.cs | 49 ++++ .../Orleans.Streaming.GCP.csproj | 1 + .../Streams/PubSub/PubSubAdapterConstants.cs | 17 -- .../Streams/PubSub/PubSubAdapterFactory.cs | 98 +++---- .../Streams/PubSub/PubSubStreamOptions.cs | 31 +++ .../Streams/PubSub/PubSubStreamProvider.cs | 11 - .../Hosting/ClientBuilderExtensions.cs | 49 ++++ .../Hosting/SiloBuilderExtensions.cs | 49 ++++ src/OrleansProviders/OrleansProviders.csproj | 1 + .../Common/RecoverableStreamOptions.cs | 39 +++ .../RecoverableStreamProviderSettings.cs | 75 ------ .../Generator/GeneratedStreamOptions.cs | 16 ++ .../Generator/GeneratorAdapterConfig.cs | 77 ------ .../Generator/GeneratorAdapterFactory.cs | 80 +++--- .../Generator/GeneratorStreamProvider.cs | 13 - .../Generator/Generators/SimpleGenerator.cs | 13 +- .../Generators/SimpleGeneratorConfig.cs | 62 +++-- .../Streams/Generator/IStreamGenerator.cs | 6 - .../Streams/Memory/MemoryAdapterConfig.cs | 73 ------ .../Streams/Memory/MemoryAdapterFactory.cs | 71 ++--- .../Streams/Memory/MemoryAdapterOptions.cs | 22 ++ .../Streams/Memory/MemoryStreamProvider.cs | 21 -- .../Streaming/SQSAdapterTests.cs | 36 ++- .../Streaming/SQSClientStreamTests.cs | 38 ++- .../Streaming/SQSStreamTests.cs | 42 ++- .../SQSSubscriptionMultiplicityTests.cs | 47 +++- .../Streaming/PubSubClientStreamTests.cs | 46 +++- .../Streaming/PubSubStreamTests.cs | 50 +++- .../PubSubSubscriptionMultiplicityTests.cs | 46 +++- .../EHPurgeLogicTests.cs | 3 +- .../PluggableQueueBalancerTests.cs | 38 +-- .../EHSlowConsumingTests.cs | 50 ++-- .../EventHubStreamProviderSettingsTests.cs | 84 ------ .../EHStatisticMonitorTests.cs | 62 +++-- .../Streaming/EHClientStreamTests.cs | 74 +++--- ...ImplicitSubscriptionStreamRecoveryTests.cs | 65 +++-- .../Streaming/EHProgrammaticSubscribeTests.cs | 65 ++--- .../Streaming/EHStreamPerPartitionTests.cs | 75 +++--- .../EHStreamProviderCheckpointTests.cs | 93 +++---- .../EHSubscriptionMultiplicityTests.cs | 46 ++-- .../EHStreamProviderForMonitorTests.cs | 157 +++++------ .../EHStreamProviderWithCreatedCacheList.cs | 162 ++++++------ ...treamPerPartitionEventHubStreamProvider.cs | 67 +++-- .../TestEventHubStreamProvider.cs | 24 +- test/Tester/Forwarding/ShutdownSiloTests.cs | 8 +- ...ontrollableStreamGeneratorProviderTests.cs | 51 ++-- .../ControllableStreamProviderTests.cs | 28 +- .../GeneratedStreamRecoveryTests.cs | 48 ++-- .../MemoryStreamProviderClientTests.cs | 38 ++- .../LeaseBasedQueueBalancer.cs | 11 +- .../PluggableQueueBalancerTestBase.cs | 26 +- ...ueBalancerTestsWithMemoryStreamProvider.cs | 44 ++-- .../ProgrammaticSubcribeTestsRunner.cs | 4 - .../PullingAgentManagementTests.cs | 37 +-- .../StreamGeneratorProviderTests.cs | 45 ++-- .../ControllableTestStreamProvider.cs | 93 +++---- .../FailureInjectionStreamProvider.cs | 57 ---- .../Lease/LeaseBasedQueueBalancerTests.cs | 34 ++- .../PersistenceGrainTests_AzureBlobStore.cs | 2 +- .../Streaming/AQClientStreamTests.cs | 35 ++- .../Streaming/AQProgrammaticSubscribeTest.cs | 27 +- .../Streaming/AQStreamFilteringTests.cs | 22 +- .../Streaming/AQStreamingTests.cs | 35 ++- .../AQSubscriptionMultiplicityTests.cs | 35 ++- .../Streaming/AzureQueueAdapterTests.cs | 28 +- .../Streaming/DelayedQueueRebalancingTests.cs | 31 ++- .../Streaming/HaloStreamSubscribeTests.cs | 15 +- .../SampleAzureQueueStreamingTests.cs | 18 +- .../Streaming/StreamLifecycleTests.cs | 36 ++- .../Streaming/StreamLimitTests.cs | 16 +- .../Streaming/StreamReliabilityTests.cs | 23 +- .../Streaming/TestAzureQueueStreamProvider.cs | 18 -- .../GeoClusterTests/TestingClusterHost.cs | 7 +- 145 files changed, 2893 insertions(+), 3120 deletions(-) create mode 100644 src/AWS/Orleans.Streaming.SQS/Hosting/ClientBuilderExtensions.cs create mode 100644 src/AWS/Orleans.Streaming.SQS/Hosting/SiloBuilderExtensions.cs delete mode 100644 src/AWS/Orleans.Streaming.SQS/Streams/SQSStreamProvider.cs create mode 100644 src/AWS/Orleans.Streaming.SQS/Streams/SqsStreamOptions.cs create mode 100644 src/Azure/Orleans.Streaming.AzureStorage/Hosting/ClientBuilderExtensions.cs create mode 100644 src/Azure/Orleans.Streaming.AzureStorage/Hosting/SiloBuilderExtensions.cs delete mode 100644 src/Azure/Orleans.Streaming.AzureStorage/Providers/AzureConfigurationExtensions.cs delete mode 100644 src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueAdapterConstants.cs create mode 100644 src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamOptions.cs delete mode 100644 src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamProvider.cs create mode 100644 src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueStreamOptions.cs delete mode 100644 src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueStreamProvider.cs create mode 100644 src/Azure/Orleans.Streaming.EventHubs/Hosting/ClientBuilderExtensions.cs create mode 100644 src/Azure/Orleans.Streaming.EventHubs/Hosting/SiloBuilderExtensions.cs create mode 100644 src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorAdapterFactory.cs create mode 100644 src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorStreamOptions.cs delete mode 100644 src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorStreamProvider.cs delete mode 100644 src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/MockEventHubSettings.cs delete mode 100644 src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubSettings.cs create mode 100644 src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamOptions.cs delete mode 100644 src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamProvider.cs delete mode 100644 src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamProviderSettings.cs delete mode 100644 src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/ICheckpointerSettings.cs delete mode 100644 src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/IEventHubSettings.cs create mode 100644 src/Orleans.Core/Lifecycle/ClusterClientLifecycleExtensions.cs create mode 100644 src/Orleans.Core/Streams/ClientStreamExtensions.cs create mode 100644 src/Orleans.Core/Streams/PersistentStreams/PersistentStreamProviderOptions.cs rename src/Orleans.Core/Streams/Providers/{IStreamProviderImpl.cs => ProviderStartException.cs} (81%) create mode 100644 src/Orleans.Runtime.Abstractions/Hosting/StreamHostingExtensions.cs create mode 100644 src/Orleans.Runtime/Streams/QueueBalancer/LeaseBasedQueueBalancerOptions.cs create mode 100644 src/Orleans.Streaming.GCP/Hosting/ClientBuilderExtensions.cs create mode 100644 src/Orleans.Streaming.GCP/Hosting/SiloBuilderExtensions.cs delete mode 100644 src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubAdapterConstants.cs create mode 100644 src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubStreamOptions.cs delete mode 100644 src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubStreamProvider.cs create mode 100644 src/OrleansProviders/Hosting/ClientBuilderExtensions.cs create mode 100644 src/OrleansProviders/Hosting/SiloBuilderExtensions.cs create mode 100644 src/OrleansProviders/Streams/Common/RecoverableStreamOptions.cs delete mode 100644 src/OrleansProviders/Streams/Common/RecoverableStreamProviderSettings.cs create mode 100644 src/OrleansProviders/Streams/Generator/GeneratedStreamOptions.cs delete mode 100644 src/OrleansProviders/Streams/Generator/GeneratorAdapterConfig.cs delete mode 100644 src/OrleansProviders/Streams/Generator/GeneratorStreamProvider.cs delete mode 100644 src/OrleansProviders/Streams/Memory/MemoryAdapterConfig.cs create mode 100644 src/OrleansProviders/Streams/Memory/MemoryAdapterOptions.cs delete mode 100644 src/OrleansProviders/Streams/Memory/MemoryStreamProvider.cs delete mode 100644 test/ServiceBus.Tests/SlowConsumingTests/EventHubStreamProviderSettingsTests.cs delete mode 100644 test/Tester/TestStreamProviders/FailureInjectionStreamProvider.cs delete mode 100644 test/TesterAzureUtils/Streaming/TestAzureQueueStreamProvider.cs diff --git a/src/AWS/Orleans.Streaming.SQS/Hosting/ClientBuilderExtensions.cs b/src/AWS/Orleans.Streaming.SQS/Hosting/ClientBuilderExtensions.cs new file mode 100644 index 00000000000..f6724eb735b --- /dev/null +++ b/src/AWS/Orleans.Streaming.SQS/Hosting/ClientBuilderExtensions.cs @@ -0,0 +1,46 @@ + +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; +using Orleans.Hosting; +using OrleansAWSUtils.Streams; + +namespace Orleans.Hosting +{ + public static class ClientBuilderExtensions + { + /// + /// Configure cluster client to use SQS persistent streams. + /// + public static IClientBuilder AddSqsStreams(this IClientBuilder builder, string name, Action configureOptions) + { + return builder.ConfigureServices(services => services.AddClusterClientSqsStreams(name, configureOptions)); + } + + /// + /// Configure cluster client to use SQS persistent streams. + /// + public static IClientBuilder AddSqsStreams(this IClientBuilder builder, string name, Action> configureOptions = null) + { + return builder.ConfigureServices(services => services.AddClusterClientSqsStreams(name, configureOptions)); + } + + /// + /// Configure cluster client to use SQS persistent streams. + /// + public static IServiceCollection AddClusterClientSqsStreams(this IServiceCollection services, string name, Action configureOptions) + { + return services.AddClusterClientSqsStreams(name, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure cluster client to use SQS persistent streams. + /// + public static IServiceCollection AddClusterClientSqsStreams(this IServiceCollection services, string name, + Action> configureOptions = null) + { + return services.ConfigureNamedOptionForLogging(name) + .AddClusterClientPersistentStreams(name, SQSAdapterFactory.Create, configureOptions); + } + } +} diff --git a/src/AWS/Orleans.Streaming.SQS/Hosting/SiloBuilderExtensions.cs b/src/AWS/Orleans.Streaming.SQS/Hosting/SiloBuilderExtensions.cs new file mode 100644 index 00000000000..4a89d775072 --- /dev/null +++ b/src/AWS/Orleans.Streaming.SQS/Hosting/SiloBuilderExtensions.cs @@ -0,0 +1,45 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; +using Orleans.Hosting; +using OrleansAWSUtils.Streams; + +namespace Orleans.Hosting +{ + public static class SiloBuilderExtensions + { + /// + /// Configure silo to use SQS persistent streams. + /// + public static ISiloHostBuilder AddSqsStreams(this ISiloHostBuilder builder, string name, Action configureOptions) + { + return builder.ConfigureServices(services => services.AddSiloSqsStreams(name, configureOptions)); + } + + /// + /// Configure silo to use SQS persistent streams. + /// + public static ISiloHostBuilder AddSqsStreams(this ISiloHostBuilder builder, string name, Action> configureOptions = null) + { + return builder.ConfigureServices(services => services.AddSiloSqsStreams(name, configureOptions)); + } + + /// + /// Configure silo to use SQS persistent streams. + /// + public static IServiceCollection AddSiloSqsStreams(this IServiceCollection services, string name, Action configureOptions) + { + return services.AddSiloSqsStreams(name, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure silo to use SQS persistent streams. + /// + public static IServiceCollection AddSiloSqsStreams(this IServiceCollection services, string name, + Action> configureOptions = null) + { + return services.ConfigureNamedOptionForLogging(name) + .AddSiloPersistentStreams(name, SQSAdapterFactory.Create, configureOptions); + } + } +} diff --git a/src/AWS/Orleans.Streaming.SQS/Orleans.Streaming.SQS.csproj b/src/AWS/Orleans.Streaming.SQS/Orleans.Streaming.SQS.csproj index 5ecbfa40234..d0cbae7f06f 100644 --- a/src/AWS/Orleans.Streaming.SQS/Orleans.Streaming.SQS.csproj +++ b/src/AWS/Orleans.Streaming.SQS/Orleans.Streaming.SQS.csproj @@ -22,6 +22,7 @@ + diff --git a/src/AWS/Orleans.Streaming.SQS/Streams/SQSAdapterFactory.cs b/src/AWS/Orleans.Streaming.SQS/Streams/SQSAdapterFactory.cs index 9732ea9d132..254d2da8ab4 100644 --- a/src/AWS/Orleans.Streaming.SQS/Streams/SQSAdapterFactory.cs +++ b/src/AWS/Orleans.Streaming.SQS/Streams/SQSAdapterFactory.cs @@ -1,60 +1,46 @@ -using Orleans.Providers; -using Orleans.Providers.Streams.Common; -using Orleans.Runtime; -using Orleans.Streams; -using System; +using System; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Orleans.Providers.Streams.Common; +using Orleans.Streams; using Orleans.Serialization; +using Orleans.Configuration; namespace OrleansAWSUtils.Streams { /// Factory class for Azure Queue based stream provider. public class SQSAdapterFactory : IQueueAdapterFactory { - internal const int CacheSizeDefaultValue = 4096; - internal const string NumQueuesPropertyName = "NumQueues"; - - /// Default number of Azure Queue used in this stream provider. - public const int NumQueuesDefaultValue = 8; // keep as power of 2. - - private string deploymentId; - private string dataConnectionString; - private string providerName; - private int cacheSize; - private int numQueues; + private readonly string providerName; + private readonly SqsStreamOptions options; + private readonly SiloOptions siloOptions; + private readonly SerializationManager serializationManager; + private readonly ILoggerFactory loggerFactory; private HashRingBasedStreamQueueMapper streamQueueMapper; private IQueueAdapterCache adapterCache; - private SerializationManager serializationManager; - private ILoggerFactory loggerFactory; - /// "DataConnectionString". - public const string DataConnectionStringPropertyName = "DataConnectionString"; - /// "DeploymentId". - public const string DeploymentIdPropertyName = "DeploymentId"; /// /// Application level failure handler override. /// protected Func> StreamFailureHandlerFactory { private get; set; } - /// Init the factory. - public virtual void Init(IProviderConfiguration config, string providerName, IServiceProvider serviceProvider) + public SQSAdapterFactory(string name, SqsStreamOptions options, IServiceProvider serviceProvider, IOptions siloOptions, SerializationManager serializationManager, ILoggerFactory loggerFactory) { - if (config == null) throw new ArgumentNullException("config"); - if (!config.Properties.TryGetValue(DataConnectionStringPropertyName, out dataConnectionString)) - throw new ArgumentException(string.Format("{0} property not set", DataConnectionStringPropertyName)); - if (!config.Properties.TryGetValue(DeploymentIdPropertyName, out deploymentId)) - throw new ArgumentException(string.Format("{0} property not set", DeploymentIdPropertyName)); + this.providerName = name; + this.options = options; + this.siloOptions = siloOptions.Value; + this.serializationManager = serializationManager; + this.loggerFactory = loggerFactory; + } - cacheSize = SimpleQueueAdapterCache.ParseSize(config, CacheSizeDefaultValue); - this.loggerFactory = serviceProvider.GetRequiredService(); - numQueues = config.GetIntProperty(NumQueuesPropertyName, NumQueuesDefaultValue); - this.providerName = providerName; - streamQueueMapper = new HashRingBasedStreamQueueMapper(numQueues, providerName); - adapterCache = new SimpleQueueAdapterCache(cacheSize, providerName, serviceProvider.GetRequiredService()); - this.serializationManager = serviceProvider.GetRequiredService(); + /// Init the factory. + public virtual void Init() + { + streamQueueMapper = new HashRingBasedStreamQueueMapper(this.options.NumQueues, this.providerName); + adapterCache = new SimpleQueueAdapterCache(this.options.CacheSize, this.providerName, this.loggerFactory); if (StreamFailureHandlerFactory == null) { StreamFailureHandlerFactory = @@ -65,7 +51,7 @@ public virtual void Init(IProviderConfiguration config, string providerName, ISe /// Creates the Azure Queue based adapter. public virtual Task CreateAdapter() { - var adapter = new SQSAdapter(this.serializationManager, streamQueueMapper, this.loggerFactory, dataConnectionString, deploymentId, providerName); + var adapter = new SQSAdapter(this.serializationManager, this.streamQueueMapper, this.loggerFactory, this.options.ConnectionString, this.options.ClusterId ?? this.siloOptions.ClusterId, this.providerName); return Task.FromResult(adapter); } @@ -90,5 +76,13 @@ public Task GetDeliveryFailureHandler(QueueId queueId) { return StreamFailureHandlerFactory(queueId); } + + public static SQSAdapterFactory Create(IServiceProvider services, string name) + { + IOptionsSnapshot streamOptionsSnapshot = services.GetRequiredService>(); + var factory = ActivatorUtilities.CreateInstance(services, name, streamOptionsSnapshot.Get(name)); + factory.Init(); + return factory; + } } } diff --git a/src/AWS/Orleans.Streaming.SQS/Streams/SQSStreamProvider.cs b/src/AWS/Orleans.Streaming.SQS/Streams/SQSStreamProvider.cs deleted file mode 100644 index 2d3679a8c14..00000000000 --- a/src/AWS/Orleans.Streaming.SQS/Streams/SQSStreamProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Orleans.Providers.Streams.Common; -using OrleansAWSUtils.Streams; - -namespace Orleans.Providers.Streams -{ - /// - /// Persistent stream provider that uses azure queue for persistence - /// - public class SQSStreamProvider : PersistentStreamProvider - { - } -} diff --git a/src/AWS/Orleans.Streaming.SQS/Streams/SQSStreamProviderUtils.cs b/src/AWS/Orleans.Streaming.SQS/Streams/SQSStreamProviderUtils.cs index ae537a58700..e52402e45b4 100644 --- a/src/AWS/Orleans.Streaming.SQS/Streams/SQSStreamProviderUtils.cs +++ b/src/AWS/Orleans.Streaming.SQS/Streams/SQSStreamProviderUtils.cs @@ -1,9 +1,10 @@ -using Orleans.Streams; -using OrleansAWSUtils.Storage; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Orleans.Streams; +using OrleansAWSUtils.Storage; +using Orleans.Configuration; namespace OrleansAWSUtils.Streams { @@ -20,7 +21,7 @@ public static async Task DeleteAllUsedQueues(string providerName, string cluster { if (clusterId != null) { - var queueMapper = new HashRingBasedStreamQueueMapper(SQSAdapterFactory.NumQueuesDefaultValue, providerName); + var queueMapper = new HashRingBasedStreamQueueMapper(SqsStreamOptions.NumQueuesDefaultValue, providerName); List allQueues = queueMapper.GetAllQueues().ToList(); var deleteTasks = new List(); diff --git a/src/AWS/Orleans.Streaming.SQS/Streams/SqsStreamOptions.cs b/src/AWS/Orleans.Streaming.SQS/Streams/SqsStreamOptions.cs new file mode 100644 index 00000000000..a9649d41384 --- /dev/null +++ b/src/AWS/Orleans.Streaming.SQS/Streams/SqsStreamOptions.cs @@ -0,0 +1,17 @@ + +namespace Orleans.Configuration +{ + public class SqsStreamOptions : PersistentStreamOptions + { + public string ClusterId { get; set; } + + [Redact] + public string ConnectionString { get; set; } + + public int CacheSize { get; set; } = CacheSizeDefaultValue; + public const int CacheSizeDefaultValue = 4096; + + public int NumQueues { get; set; } = NumQueuesDefaultValue; + public const int NumQueuesDefaultValue = 8; // keep as power of 2. + } +} diff --git a/src/AdoNet/Orleans.Persistence.AdoNet/Storage/Provider/SiloBuilderExtensions.cs b/src/AdoNet/Orleans.Persistence.AdoNet/Storage/Provider/SiloBuilderExtensions.cs index dfa1b41fc74..71f41ff06b5 100644 --- a/src/AdoNet/Orleans.Persistence.AdoNet/Storage/Provider/SiloBuilderExtensions.cs +++ b/src/AdoNet/Orleans.Persistence.AdoNet/Storage/Provider/SiloBuilderExtensions.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; diff --git a/src/Azure/Orleans.Persistence.AzureStorage/Providers/Storage/AzureBlobStorage.cs b/src/Azure/Orleans.Persistence.AzureStorage/Providers/Storage/AzureBlobStorage.cs index 716de35f2ba..fea85203fd3 100644 --- a/src/Azure/Orleans.Persistence.AzureStorage/Providers/Storage/AzureBlobStorage.cs +++ b/src/Azure/Orleans.Persistence.AzureStorage/Providers/Storage/AzureBlobStorage.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; @@ -10,8 +9,7 @@ using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Blob; using Newtonsoft.Json; -using Orleans.Hosting; -using Orleans.Providers; +using Orleans.Configuration; using Orleans.Providers.Azure; using Orleans.Runtime; using Orleans.Runtime.Configuration; diff --git a/src/Azure/Orleans.Persistence.AzureStorage/Providers/Storage/AzureBlobStorageOptions.cs b/src/Azure/Orleans.Persistence.AzureStorage/Providers/Storage/AzureBlobStorageOptions.cs index 528b4a7257a..705a6c72367 100644 --- a/src/Azure/Orleans.Persistence.AzureStorage/Providers/Storage/AzureBlobStorageOptions.cs +++ b/src/Azure/Orleans.Persistence.AzureStorage/Providers/Storage/AzureBlobStorageOptions.cs @@ -1,13 +1,13 @@ -using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using Microsoft.Extensions.Options; using Microsoft.WindowsAzure.Storage; using Newtonsoft.Json; using Orleans.Persistence.AzureStorage; using Orleans.Runtime; using Orleans.Runtime.Configuration; -using System; -using System.Collections.Generic; -namespace Orleans.Hosting +namespace Orleans.Configuration { public class AzureBlobStorageOptions { diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Hosting/ClientBuilderExtensions.cs b/src/Azure/Orleans.Streaming.AzureStorage/Hosting/ClientBuilderExtensions.cs new file mode 100644 index 00000000000..d900c88217f --- /dev/null +++ b/src/Azure/Orleans.Streaming.AzureStorage/Hosting/ClientBuilderExtensions.cs @@ -0,0 +1,49 @@ + +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; +using Orleans.Providers.Streams.AzureQueue; + +namespace Orleans.Hosting +{ + public static class ClientBuilderExtensions + { + /// + /// Configure cluster client to use azure queue persistent streams. + /// + public static IClientBuilder AddAzureQueueStreams(this IClientBuilder builder, string name, Action configureOptions) + where TDataAdapter : IAzureQueueDataAdapter + { + return builder.ConfigureServices(services => services.AddClusterClientAzureQueueStreams(name, configureOptions)); + } + + /// + /// Configure cluster client to use azure queue persistent streams. + /// + public static IClientBuilder AddAzureQueueStreams(this IClientBuilder builder, string name, Action> configureOptions = null) + where TDataAdapter : IAzureQueueDataAdapter + { + return builder.ConfigureServices(services => services.AddClusterClientAzureQueueStreams(name, configureOptions)); + } + + /// + /// Configure cluster client to use azure queue persistent streams. + /// + public static IServiceCollection AddClusterClientAzureQueueStreams(this IServiceCollection services, string name, Action configureOptions) + where TDataAdapter : IAzureQueueDataAdapter + { + return services.AddClusterClientAzureQueueStreams(name, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure cluster client to use azure queue persistent streams. + /// + public static IServiceCollection AddClusterClientAzureQueueStreams(this IServiceCollection services, string name, + Action> configureOptions = null) + where TDataAdapter : IAzureQueueDataAdapter + { + return services.ConfigureNamedOptionForLogging(name) + .AddClusterClientPersistentStreams(name, AzureQueueAdapterFactory.Create, configureOptions); + } + } +} diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Hosting/SiloBuilderExtensions.cs b/src/Azure/Orleans.Streaming.AzureStorage/Hosting/SiloBuilderExtensions.cs new file mode 100644 index 00000000000..107c61bf52b --- /dev/null +++ b/src/Azure/Orleans.Streaming.AzureStorage/Hosting/SiloBuilderExtensions.cs @@ -0,0 +1,49 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; +using Orleans.Hosting; +using Orleans.Providers.Streams.AzureQueue; + +namespace Orleans.Hosting +{ + public static class SiloBuilderExtensions + { + /// + /// Configure silo to use azure queue persistent streams. + /// + public static ISiloHostBuilder AddAzureQueueStreams(this ISiloHostBuilder builder, string name, Action configureOptions) + where TDataAdapter : IAzureQueueDataAdapter + { + return builder.ConfigureServices(services => services.AddSiloAzureQueueStreams(name, configureOptions)); + } + + /// + /// Configure silo to use azure queue persistent streams. + /// + public static ISiloHostBuilder AddAzureQueueStreams(this ISiloHostBuilder builder, string name, Action> configureOptions = null) + where TDataAdapter : IAzureQueueDataAdapter + { + return builder.ConfigureServices(services => services.AddSiloAzureQueueStreams(name, configureOptions)); + } + + /// + /// Configure silo to use azure queue persistent streams. + /// + public static IServiceCollection AddSiloAzureQueueStreams(this IServiceCollection services, string name, Action configureOptions) + where TDataAdapter : IAzureQueueDataAdapter + { + return services.AddSiloAzureQueueStreams(name, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure silo to use azure queue persistent streams. + /// + public static IServiceCollection AddSiloAzureQueueStreams(this IServiceCollection services, string name, + Action> configureOptions = null) + where TDataAdapter : IAzureQueueDataAdapter + { + return services.ConfigureNamedOptionForLogging(name) + .AddSiloPersistentStreams(name, AzureQueueAdapterFactory.Create, configureOptions); + } + } +} diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Orleans.Streaming.AzureStorage.csproj b/src/Azure/Orleans.Streaming.AzureStorage/Orleans.Streaming.AzureStorage.csproj index f2d57ea24c4..d57c2332f20 100644 --- a/src/Azure/Orleans.Streaming.AzureStorage/Orleans.Streaming.AzureStorage.csproj +++ b/src/Azure/Orleans.Streaming.AzureStorage/Orleans.Streaming.AzureStorage.csproj @@ -26,7 +26,7 @@ - + diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Providers/AzureConfigurationExtensions.cs b/src/Azure/Orleans.Streaming.AzureStorage/Providers/AzureConfigurationExtensions.cs deleted file mode 100644 index 3a9b15058a8..00000000000 --- a/src/Azure/Orleans.Streaming.AzureStorage/Providers/AzureConfigurationExtensions.cs +++ /dev/null @@ -1,173 +0,0 @@ -using System; -using System.Collections.Generic; -using Orleans.Providers.Streams.AzureQueue; -using Orleans.Providers.Streams.Common; -using Orleans.Streams; - -namespace Orleans.Runtime.Configuration -{ - /// - /// Extension methods for configuration classes specific to Orleans.Streaming.AzureStorage.dll - /// - public static class AzureConfigurationExtensions - { - /// - /// Adds a stream provider of type . - /// - /// The cluster configuration object to add provider to. - /// The provider name - /// The azure storage connection string. If none is provided, it will use the same as in the Globals configuration. - /// The number of queues to use as partitions. - /// The ClusterId used for partitioning. If none is specified, the provider will use the same ClusterId as the Cluster. - /// The cache size. - /// The startup state of the persistent stream provider. - /// Settings related to all persistent stream providers. - public static void AddAzureQueueStreamProvider( - this ClusterConfiguration config, - string providerName, - string connectionString = null, - int numberOfQueues = AzureQueueAdapterConstants.NumQueuesDefaultValue, - string clusterId = null, - int cacheSize = AzureQueueAdapterConstants.CacheSizeDefaultValue, -#pragma warning disable CS0618 // Type or member is obsolete - PersistentStreamProviderState startupState = AzureQueueStreamProvider.StartupStateDefaultValue, -#pragma warning restore CS0618 // Type or member is obsolete - PersistentStreamProviderConfig persistentStreamProviderConfig = null) - { - connectionString = GetConnectionString(connectionString, config); - clusterId = clusterId ?? config.Globals.ClusterId; - var properties = GetAzureQueueStreamProviderProperties(providerName, connectionString, numberOfQueues, clusterId, cacheSize, startupState, persistentStreamProviderConfig); -#pragma warning disable 618 - config.Globals.RegisterStreamProvider(providerName, properties); -#pragma warning restore 618 - } - - /// - /// Adds a stream provider of type . - /// - /// The cluster configuration object to add provider to. - /// The provider name - /// The azure storage connection string. If none is provided, it will use the same as in the Globals configuration. - /// The number of queues to use as partitions. - /// The ClusterId used for partitioning. If none is specified, the provider will use the same ClusterId as the Cluster. - /// The cache size. - /// The startup state of the persistent stream provider. - /// Settings related to all persistent stream providers. - public static void AddAzureQueueStreamProviderV2( - this ClusterConfiguration config, - string providerName, - string connectionString = null, - int numberOfQueues = AzureQueueAdapterConstants.NumQueuesDefaultValue, - string clusterId = null, - int cacheSize = AzureQueueAdapterConstants.CacheSizeDefaultValue, -#pragma warning disable 618 - PersistentStreamProviderState startupState = AzureQueueStreamProvider.StartupStateDefaultValue, -#pragma warning restore 618 - PersistentStreamProviderConfig persistentStreamProviderConfig = null) - { - connectionString = GetConnectionString(connectionString, config); - clusterId = clusterId ?? config.Globals.ClusterId; - var properties = GetAzureQueueStreamProviderProperties(providerName, connectionString, numberOfQueues, clusterId, cacheSize, startupState, persistentStreamProviderConfig); - config.Globals.RegisterStreamProvider(providerName, properties); - } - - /// - /// Adds a stream provider of type . - /// - /// The cluster configuration object to add provider to. - /// The provider name - /// The azure storage connection string. If none is provided, it will use the same as in the Globals configuration. - /// The number of queues to use as partitions. - /// The ClusterId used for partitioning. If none is specified, the provider will use the same ClusterId as the Cluster. - /// The cache size. - /// The startup state of the persistent stream provider. - /// Settings related to all persistent stream providers. - public static void AddAzureQueueStreamProvider( - this ClientConfiguration config, - string providerName, - string connectionString = null, - int numberOfQueues = AzureQueueAdapterConstants.NumQueuesDefaultValue, - string clusterId = null, - int cacheSize = AzureQueueAdapterConstants.CacheSizeDefaultValue, -#pragma warning disable 618 - PersistentStreamProviderState startupState = AzureQueueStreamProvider.StartupStateDefaultValue, -#pragma warning restore 618 - PersistentStreamProviderConfig persistentStreamProviderConfig = null) - { - connectionString = GetConnectionString(connectionString, config); - clusterId = clusterId ?? config.ClusterId; - var properties = GetAzureQueueStreamProviderProperties(providerName, connectionString, numberOfQueues, clusterId, cacheSize, startupState, persistentStreamProviderConfig); -#pragma warning disable 618 - config.RegisterStreamProvider(providerName, properties); -#pragma warning restore 618 - } - - /// - /// Adds a stream provider of type . - /// - /// The cluster configuration object to add provider to. - /// The provider name - /// The azure storage connection string. If none is provided, it will use the same as in the Globals configuration. - /// The number of queues to use as partitions. - /// The ClusterId used for partitioning. If none is specified, the provider will use the same ClusterId as the Cluster. - /// The cache size. - /// The startup state of the persistent stream provider. - /// Settings related to all persistent stream providers. - public static void AddAzureQueueStreamProviderV2( - this ClientConfiguration config, - string providerName, - string connectionString = null, - int numberOfQueues = AzureQueueAdapterConstants.NumQueuesDefaultValue, - string clusterId = null, - int cacheSize = AzureQueueAdapterConstants.CacheSizeDefaultValue, -#pragma warning disable 618 - PersistentStreamProviderState startupState = AzureQueueStreamProvider.StartupStateDefaultValue, -#pragma warning restore 618 - PersistentStreamProviderConfig persistentStreamProviderConfig = null) - { - connectionString = GetConnectionString(connectionString, config); - clusterId = clusterId ?? config.ClusterId; - var properties = GetAzureQueueStreamProviderProperties(providerName, connectionString, numberOfQueues, clusterId, cacheSize, startupState, persistentStreamProviderConfig); - config.RegisterStreamProvider(providerName, properties); - } - - private static Dictionary GetAzureQueueStreamProviderProperties(string providerName, string connectionString, int numberOfQueues, string deploymentId, int cacheSize, PersistentStreamProviderState startupState, PersistentStreamProviderConfig persistentStreamProviderConfig) - { - if (string.IsNullOrWhiteSpace(providerName)) throw new ArgumentNullException(nameof(providerName)); - if (numberOfQueues < 1) throw new ArgumentOutOfRangeException(nameof(numberOfQueues)); - - var properties = new Dictionary - { - { AzureQueueAdapterConstants.DataConnectionStringPropertyName, connectionString }, - { AzureQueueAdapterConstants.NumQueuesPropertyName, numberOfQueues.ToString() }, - { AzureQueueAdapterConstants.DeploymentIdPropertyName, deploymentId }, - { SimpleQueueAdapterCache.CacheSizePropertyName, cacheSize.ToString() }, -#pragma warning disable 618 - { AzureQueueStreamProvider.StartupStatePropertyName, startupState.ToString() }, -#pragma warning restore 618 - }; - - persistentStreamProviderConfig?.WriteProperties(properties); - - return properties; - } - - private static string GetConnectionString(string connectionString, ClusterConfiguration config) - { - if (!string.IsNullOrWhiteSpace(connectionString)) return connectionString; - if (!string.IsNullOrWhiteSpace(config.Globals.DataConnectionString)) return config.Globals.DataConnectionString; - - throw new ArgumentNullException(nameof(connectionString), - "Parameter value and fallback value are both null or empty."); - } - - private static string GetConnectionString(string connectionString, ClientConfiguration config) - { - if (!string.IsNullOrWhiteSpace(connectionString)) return connectionString; - if (!string.IsNullOrWhiteSpace(config.DataConnectionString)) return config.DataConnectionString; - - throw new ArgumentNullException(nameof(connectionString), - "Parameter value and fallback value are both null or empty."); - } - } -} \ No newline at end of file diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueAdapterConstants.cs b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueAdapterConstants.cs deleted file mode 100644 index 786ff099ccb..00000000000 --- a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueAdapterConstants.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Orleans.Providers.Streams.AzureQueue -{ - /// - /// Azure queue stream provider constants. - /// - public static class AzureQueueAdapterConstants - { - internal const int CacheSizeDefaultValue = 4096; - - /// "DataConnectionString". - public const string DataConnectionStringPropertyName = "DataConnectionString"; - /// "DeploymentId". - public const string DeploymentIdPropertyName = "DeploymentId"; - /// "MessageVisibilityTimeout". - public const string MessageVisibilityTimeoutPropertyName = "VisibilityTimeout"; - - /// "NumQueues". - public const string NumQueuesPropertyName = "NumQueues"; - /// Default number of Azure Queue used in this stream provider. - public const int NumQueuesDefaultValue = 8; // keep as power of 2. - } -} diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueAdapterFactory.cs b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueAdapterFactory.cs index a43e920193a..0c89e300047 100644 --- a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueAdapterFactory.cs +++ b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueAdapterFactory.cs @@ -2,9 +2,11 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Orleans.Serialization; using Orleans.Streams; using Orleans.Providers.Streams.Common; +using Orleans.Configuration; namespace Orleans.Providers.Streams.AzureQueue { @@ -12,78 +14,47 @@ namespace Orleans.Providers.Streams.AzureQueue public class AzureQueueAdapterFactory : IQueueAdapterFactory where TDataAdapter : IAzureQueueDataAdapter { - private string deploymentId; - private string dataConnectionString; - private string providerName; - private int cacheSize; - private int numQueues; - private TimeSpan? messageVisibilityTimeout; + private readonly string providerName; + private readonly AzureQueueStreamOptions options; + private readonly SiloOptions siloOptions; + private readonly ILoggerFactory loggerFactory; + private readonly Func dataAadaptorFactory; private HashRingBasedStreamQueueMapper streamQueueMapper; private IQueueAdapterCache adapterCache; - private Func adaptorFactory; - private ILoggerFactory loggerFactory; /// /// Gets the serialization manager. /// - public SerializationManager SerializationManager { get; private set; } + + protected SerializationManager SerializationManager { get; } /// /// Application level failure handler override. /// protected Func> StreamFailureHandlerFactory { private get; set; } - /// Init the factory. - public virtual void Init(IProviderConfiguration config, string providerName, IServiceProvider serviceProvider) + public AzureQueueAdapterFactory(string name, AzureQueueStreamOptions options, IServiceProvider serviceProvider, IOptions siloOptions, SerializationManager serializationManager, ILoggerFactory loggerFactory) { - if (config == null) throw new ArgumentNullException(nameof(config)); - if (!config.Properties.TryGetValue(AzureQueueAdapterConstants.DataConnectionStringPropertyName, out dataConnectionString)) - throw new ArgumentException($"{AzureQueueAdapterConstants.DataConnectionStringPropertyName} property not set"); - if (!config.Properties.TryGetValue(AzureQueueAdapterConstants.DeploymentIdPropertyName, out deploymentId)) - throw new ArgumentException($"{AzureQueueAdapterConstants.DeploymentIdPropertyName} property not set"); - string messageVisibilityTimeoutRaw; - if (config.Properties.TryGetValue(AzureQueueAdapterConstants.MessageVisibilityTimeoutPropertyName, out messageVisibilityTimeoutRaw)) - { - TimeSpan messageVisibilityTimeoutTemp; - if (!TimeSpan.TryParse(messageVisibilityTimeoutRaw, out messageVisibilityTimeoutTemp)) - { - throw new ArgumentException( - $"Failed to parse {AzureQueueAdapterConstants.MessageVisibilityTimeoutPropertyName} value '{messageVisibilityTimeoutRaw}' as a TimeSpan"); - } - - messageVisibilityTimeout = messageVisibilityTimeoutTemp; - } - else - { - messageVisibilityTimeout = null; - } - - cacheSize = SimpleQueueAdapterCache.ParseSize(config, AzureQueueAdapterConstants.CacheSizeDefaultValue); - this.loggerFactory = serviceProvider.GetRequiredService(); - string numQueuesString; - numQueues = AzureQueueAdapterConstants.NumQueuesDefaultValue; - if (config.Properties.TryGetValue(AzureQueueAdapterConstants.NumQueuesPropertyName, out numQueuesString)) - { - if (!int.TryParse(numQueuesString, out numQueues)) - throw new ArgumentException($"{AzureQueueAdapterConstants.NumQueuesPropertyName} invalid. Must be int"); - } - - this.providerName = providerName; - streamQueueMapper = new HashRingBasedStreamQueueMapper(numQueues, providerName); - adapterCache = new SimpleQueueAdapterCache(cacheSize, providerName, loggerFactory); - if (StreamFailureHandlerFactory == null) - { - StreamFailureHandlerFactory = - qid => Task.FromResult(new NoOpStreamDeliveryFailureHandler()); - } + this.providerName = name; + this.options = options ?? throw new ArgumentNullException(nameof(options)); + this.siloOptions = siloOptions.Value; + this.SerializationManager = serializationManager ?? throw new ArgumentNullException(nameof(serializationManager)); + this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); + this.dataAadaptorFactory = () => ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider); + } - this.SerializationManager = serviceProvider.GetRequiredService(); - this.adaptorFactory = () => ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider); + /// Init the factory. + public virtual void Init() + { + this.streamQueueMapper = new HashRingBasedStreamQueueMapper(this.options.NumQueues, providerName); + this.adapterCache = new SimpleQueueAdapterCache(this.options.CacheSize, this.providerName, this.loggerFactory); + this.StreamFailureHandlerFactory = this.StreamFailureHandlerFactory ?? + ((qid) => Task.FromResult(new NoOpStreamDeliveryFailureHandler())); } /// Creates the Azure Queue based adapter. public virtual Task CreateAdapter() { - var adapter = new AzureQueueAdapter(this.adaptorFactory(), this.SerializationManager, streamQueueMapper, this.loggerFactory, dataConnectionString, deploymentId, providerName, messageVisibilityTimeout); + var adapter = new AzureQueueAdapter(this.dataAadaptorFactory(), this.SerializationManager, this.streamQueueMapper, this.loggerFactory, this.options.ConnectionString, this.options.ClusterId ?? this.siloOptions.ClusterId, this.providerName, this.options.MessageVisibilityTimeout); return Task.FromResult(adapter); } @@ -108,5 +79,13 @@ public Task GetDeliveryFailureHandler(QueueId queueId) { return StreamFailureHandlerFactory(queueId); } + + public static AzureQueueAdapterFactory Create(IServiceProvider services, string name) + { + IOptionsSnapshot streamOptionsSnapshot = services.GetRequiredService>(); + var factory = ActivatorUtilities.CreateInstance>(services, name, streamOptionsSnapshot.Get(name)); + factory.Init(); + return factory; + } } } diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamOptions.cs b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamOptions.cs new file mode 100644 index 00000000000..891b256ee06 --- /dev/null +++ b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamOptions.cs @@ -0,0 +1,24 @@ + +using System; + +namespace Orleans.Configuration +{ + /// + /// Azure queue stream provider options. + /// + public class AzureQueueStreamOptions : PersistentStreamOptions + { + [RedactConnectionString] + public string ConnectionString { get; set; } + + public string ClusterId { get; set; } + + public TimeSpan? MessageVisibilityTimeout { get; set; } + + public int CacheSize { get; set; } = DEFAULT_CACHE_SIZE; + public const int DEFAULT_CACHE_SIZE = 4096; + + public int NumQueues { get; set; } = DEFAULT_NUM_QUEUES; + public const int DEFAULT_NUM_QUEUES = 8; // keep as power of 2. + } +} diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamProvider.cs b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamProvider.cs deleted file mode 100644 index 4a9e0b1e33a..00000000000 --- a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamProvider.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using Orleans.Providers.Streams.Common; - -namespace Orleans.Providers.Streams.AzureQueue -{ - /// - /// Persistent stream provider that uses azure queue for persistence - /// WARNING: This version is maintained for compatability purposes. New services should use AzureQueueStreamProviderV2 as it supports external serializers. - /// - [Obsolete("This version is maintained for compatability purposes. New services should use AzureQueueStreamProviderV2 as it supports external serializers.")] - public class AzureQueueStreamProvider : PersistentStreamProvider> - { - } - - /// - /// Persistent stream provider that uses azure queue for persistence - /// - public class AzureQueueStreamProviderV2 : PersistentStreamProvider> - { - } -} diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamProviderUtils.cs b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamProviderUtils.cs index 9a80bdfcb46..cf848a953b9 100644 --- a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamProviderUtils.cs +++ b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/AzureQueueStreamProviderUtils.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Orleans.AzureUtils; +using Orleans.Configuration; using Orleans.Streams; namespace Orleans.Providers.Streams.AzureQueue @@ -23,7 +24,8 @@ public static async Task DeleteAllUsedAzureQueues(ILoggerFactory loggerFactory, { if (deploymentId != null) { - var queueMapper = new HashRingBasedStreamQueueMapper(AzureQueueAdapterConstants.NumQueuesDefaultValue, providerName); + // TODO: Do not assume defaults !? - jbragg + var queueMapper = new HashRingBasedStreamQueueMapper(AzureQueueStreamOptions.DEFAULT_NUM_QUEUES, providerName); List allQueues = queueMapper.GetAllQueues().ToList(); var deleteTasks = new List(); @@ -48,7 +50,8 @@ public static async Task ClearAllUsedAzureQueues(ILoggerFactory loggerFactory, s { if (deploymentId != null) { - var queueMapper = new HashRingBasedStreamQueueMapper(AzureQueueAdapterConstants.NumQueuesDefaultValue, providerName); + // TODO: Do not assume defaults !? - jbragg + var queueMapper = new HashRingBasedStreamQueueMapper(AzureQueueStreamOptions.DEFAULT_NUM_QUEUES, providerName); List allQueues = queueMapper.GetAllQueues().ToList(); var deleteTasks = new List(); diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueAdapterFactory.cs b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueAdapterFactory.cs index 8c939402202..8ffbf7cb299 100644 --- a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueAdapterFactory.cs +++ b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueAdapterFactory.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Orleans.Configuration; using Orleans.Runtime; using Orleans.Streams; @@ -10,30 +10,21 @@ namespace Orleans.Providers.Streams.AzureQueue /// Factory class for Simple Azure Queue based stream provider. public class SimpleAzureQueueAdapterFactory : IQueueAdapterFactory { - private string dataConnectionString; - private string queueName; + private readonly SimpleAzureQueueStreamOptions options; private string providerName; private ILoggerFactory loggerFactory; - /// "QueueName". - public const string QUEUE_NAME_STRING = "QueueName"; - /// Init the factory. - public virtual void Init(IProviderConfiguration config, string providerName, IServiceProvider serviceProvider) + public SimpleAzureQueueAdapterFactory(string name, SimpleAzureQueueStreamOptions options, IServiceProvider serviceProvider, ILoggerFactory loggerFactory) { - if (config == null) throw new ArgumentNullException("config"); - if (!config.Properties.TryGetValue(AzureQueueAdapterConstants.DataConnectionStringPropertyName, out dataConnectionString)) - throw new ArgumentException(String.Format("{0} property not set", AzureQueueAdapterConstants.DataConnectionStringPropertyName)); - if (!config.Properties.TryGetValue(QUEUE_NAME_STRING, out queueName)) - throw new ArgumentException(String.Format("{0} property not set", QUEUE_NAME_STRING)); - this.loggerFactory = serviceProvider.GetRequiredService(); - this.providerName = providerName; + this.providerName = name; + this.options = options ?? throw new ArgumentNullException(nameof(options)); + this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); } - /// Creates the Simple Azure Queue based adapter. public virtual Task CreateAdapter() { - var adapter = new SimpleAzureQueueAdapter(this.loggerFactory, dataConnectionString, providerName, queueName); + var adapter = new SimpleAzureQueueAdapter(this.loggerFactory, this.options.ConnectionString, this.providerName, this.options.QueueName); return Task.FromResult(adapter); } diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueStreamOptions.cs b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueStreamOptions.cs new file mode 100644 index 00000000000..4783a86cc37 --- /dev/null +++ b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueStreamOptions.cs @@ -0,0 +1,14 @@ + +namespace Orleans.Configuration +{ + /// + /// Simple Azure queue stream provider options. + /// + public class SimpleAzureQueueStreamOptions : PersistentStreamOptions + { + [RedactConnectionString] + public string ConnectionString { get; set; } + + public string QueueName { get; set; } + } +} diff --git a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueStreamProvider.cs b/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueStreamProvider.cs deleted file mode 100644 index 52f5ec804dd..00000000000 --- a/src/Azure/Orleans.Streaming.AzureStorage/Providers/Streams/AzureQueue/SimpleAzureQueueStreamProvider.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Orleans.Providers.Streams.Common; - -namespace Orleans.Providers.Streams.AzureQueue -{ - /// - /// Persistent stream provider that uses azure queue for persistence - /// - public class SimpleAzureQueueStreamProvider : PersistentStreamProvider - { - } -} diff --git a/src/Azure/Orleans.Streaming.EventHubs/Hosting/ClientBuilderExtensions.cs b/src/Azure/Orleans.Streaming.EventHubs/Hosting/ClientBuilderExtensions.cs new file mode 100644 index 00000000000..a68973ed031 --- /dev/null +++ b/src/Azure/Orleans.Streaming.EventHubs/Hosting/ClientBuilderExtensions.cs @@ -0,0 +1,46 @@ + +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; +using Orleans.Hosting; +using Orleans.ServiceBus.Providers; + +namespace Orleans.Hosting +{ + public static class ClientBuilderExtensions + { + /// + /// Configure cluster client to use event hub persistent streams. + /// + public static IClientBuilder AddEventHubStreams(this IClientBuilder builder, string name, Action configureOptions) + { + return builder.ConfigureServices(services => services.AddClusterClientEventHubStreams(name, configureOptions)); + } + + /// + /// Configure cluster client to use event hub persistent streams. + /// + public static IClientBuilder AddEventHubStreams(this IClientBuilder builder, string name, Action> configureOptions = null) + { + return builder.ConfigureServices(services => services.AddClusterClientEventHubStreams(name, configureOptions)); + } + + /// + /// Configure cluster client to use event hub persistent streams. + /// + public static IServiceCollection AddClusterClientEventHubStreams(this IServiceCollection services, string name, Action configureOptions) + { + return services.AddClusterClientEventHubStreams(name, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure cluster client to use event hub persistent streams. + /// + public static IServiceCollection AddClusterClientEventHubStreams(this IServiceCollection services, string name, + Action> configureOptions = null) + { + return services.ConfigureNamedOptionForLogging(name) + .AddClusterClientPersistentStreams(name, EventHubAdapterFactory.Create, configureOptions); + } + } +} diff --git a/src/Azure/Orleans.Streaming.EventHubs/Hosting/SiloBuilderExtensions.cs b/src/Azure/Orleans.Streaming.EventHubs/Hosting/SiloBuilderExtensions.cs new file mode 100644 index 00000000000..e88adceae47 --- /dev/null +++ b/src/Azure/Orleans.Streaming.EventHubs/Hosting/SiloBuilderExtensions.cs @@ -0,0 +1,45 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; +using Orleans.Hosting; +using Orleans.ServiceBus.Providers; + +namespace Orleans.Hosting +{ + public static class SiloBuilderExtensions + { + /// + /// Configure silo to use event hub persistent streams. + /// + public static ISiloHostBuilder AddEventHubStreams(this ISiloHostBuilder builder, string name, Action configureOptions) + { + return builder.ConfigureServices(services => services.AddSiloEventHubStreams(name, configureOptions)); + } + + /// + /// Configure silo to use event hub persistent streams. + /// + public static ISiloHostBuilder AddEventHubStreams(this ISiloHostBuilder builder, string name, Action> configureOptions = null) + { + return builder.ConfigureServices(services => services.AddSiloEventHubStreams(name, configureOptions)); + } + + /// + /// Configure silo to use event hub persistent streams. + /// + public static IServiceCollection AddSiloEventHubStreams(this IServiceCollection services, string name, Action configureOptions) + { + return services.AddSiloEventHubStreams(name, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure silo to use event hub persistent streams. + /// + public static IServiceCollection AddSiloEventHubStreams(this IServiceCollection services, string name, + Action> configureOptions = null) + { + return services.ConfigureNamedOptionForLogging(name) + .AddSiloPersistentStreams(name, EventHubAdapterFactory.Create, configureOptions); + } + } +} diff --git a/src/Azure/Orleans.Streaming.EventHubs/Orleans.Streaming.EventHubs.csproj b/src/Azure/Orleans.Streaming.EventHubs/Orleans.Streaming.EventHubs.csproj index 3d1ac81e795..630423cbcb4 100644 --- a/src/Azure/Orleans.Streaming.EventHubs/Orleans.Streaming.EventHubs.csproj +++ b/src/Azure/Orleans.Streaming.EventHubs/Orleans.Streaming.EventHubs.csproj @@ -27,6 +27,7 @@ + diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorAdapterFactory.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorAdapterFactory.cs new file mode 100644 index 00000000000..e5c1c309e6c --- /dev/null +++ b/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorAdapterFactory.cs @@ -0,0 +1,181 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Azure.EventHubs; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Orleans.Configuration; +using Orleans.Providers; +using Orleans.Providers.Streams.Common; +using Orleans.Runtime; +using Orleans.Serialization; +using Orleans.Streams; + +namespace Orleans.ServiceBus.Providers.Testing +{ + /// + /// This is a persistent stream provider adapter that generates it's own events rather than reading them from Eventhub. + /// This is primarily for test purposes. + /// + public class EventDataGeneratorAdapterFactory : EventHubAdapterFactory, IControllable + { + private EventDataGeneratorStreamOptions ehGeneratorOptions; + + public EventDataGeneratorAdapterFactory(string name, EventDataGeneratorStreamOptions options, IServiceProvider serviceProvider, SerializationManager serializationManager, ITelemetryProducer telemetryProducer, ILoggerFactory loggerFactory) + : base(name, options, serviceProvider, serializationManager, telemetryProducer, loggerFactory) + { + this.ehGeneratorOptions = options; + } + + public override void Init() + { + this.CheckpointerFactory = partition => Task.FromResult>(NoOpCheckpointer.Instance); + this.EventHubReceiverFactory = this.EHGeneratorReceiverFactory; + base.Init(); + } + + /// + protected override void InitEventHubClient() + { + //do nothing, EventDataGeneratorStreamProvider doesn't need connection with EventHubClient + } + + /// + /// Generate mocked eventhub partition Ids from EventHubGeneratorStreamProviderSettings + /// + /// + protected override Task GetPartitionIdsAsync() + { + return Task.FromResult(GenerateEventHubPartitions(this.ehGeneratorOptions.EventHubPartitionCount)); + } + + private Task EHGeneratorReceiverFactory(EventHubPartitionSettings settings, string offset, ILogger logger, ITelemetryProducer telemetryProducer) + { + Func> streamGeneratorFactory = this.serviceProvider.GetServiceByName>>(this.Name) + ?? SimpleStreamEventDataGenerator.CreateFactory(this.serviceProvider); + var generator = new EventHubPartitionDataGenerator(this.ehGeneratorOptions, streamGeneratorFactory, logger); + var generatorReceiver = new EventHubPartitionGeneratorReceiver(generator); + return Task.FromResult(generatorReceiver); + } + + private void RandomlyPlaceStreamToQueue(StreamRandomPlacementArg args) + { + if (args == null) + return; + int randomNumber = args.RandomNumber; + IStreamIdentity streamId = args.StreamId; + var allQueueInTheCluster = (this.EventHubQueueMapper as EventHubQueueMapper)?.GetAllQueues().OrderBy(queueId => queueId.ToString()); + + if (allQueueInTheCluster != null) + { + //every agent receive the same random number, do a mod on queue count, get the same random queue to assign stream to. + int randomQueue = randomNumber % allQueueInTheCluster.Count(); + var queueToAssign = allQueueInTheCluster.ToList()[randomQueue]; + EventHubAdapterReceiver receiverToAssign; + if (this.EventHubReceivers.TryGetValue(queueToAssign, out receiverToAssign)) + { + receiverToAssign.ConfigureDataGeneratorForStream(streamId); + logger.Info($"Stream {streamId.Namespace}-{streamId.Guid.ToString()} is assigned to queue {queueToAssign.ToString()}"); + } + } + else + { + logger.Info("Cannot get queues in the cluster, current streamQueueMapper is not EventHubQueueMapper"); + } + } + + private void StopProducingOnStream(IStreamIdentity streamId) + { + foreach (var ehReceiver in this.EventHubReceivers) + { + //if the stream is assigned to this receiver/queue, then it will ask the data generator to stop producing + ehReceiver.Value.StopProducingOnStream(streamId); + } + } + + public static string[] GenerateEventHubPartitions(int partitionCount) + { + var size = partitionCount; + var partitions = new string[size]; + for (int i = 0; i < size; i++) + partitions[i] = $"partition-{(i).ToString()}"; + return partitions; + } + + #region IControllable interface + /// + /// Commands for IControllable + /// + public enum Commands + { + /// + /// Command for Randomly_Place_Stream_To_Queue + /// + Randomly_Place_Stream_To_Queue = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 4, + /// + /// Command for Stop_Producing_On_Stream + /// + Stop_Producing_On_Stream = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 5 + } + + /// + /// Args for RandomlyPlaceStreamToQueue method + /// + [Serializable] + public class StreamRandomPlacementArg + { + /// + /// StreamId + /// + public IStreamIdentity StreamId { get; set; } + + /// + /// A random number + /// + public int RandomNumber { get; set; } + + /// + /// Constructor + /// + /// + /// + public StreamRandomPlacementArg(IStreamIdentity streamId, int randomNumber) + { + this.StreamId = streamId; + this.RandomNumber = randomNumber; + } + } + + /// + /// Execute Command + /// + /// + /// + /// + public virtual Task ExecuteCommand(int command, object arg) + { + switch (command) + { + case (int)Commands.Randomly_Place_Stream_To_Queue: + this.RandomlyPlaceStreamToQueue(arg as StreamRandomPlacementArg); + break; + case (int)Commands.Stop_Producing_On_Stream: + this.StopProducingOnStream(arg as IStreamIdentity); + break; + default: break; + + } + return Task.FromResult((object)true); + } + #endregion + + public new static EventDataGeneratorAdapterFactory Create(IServiceProvider services, string name) + { + IOptionsSnapshot streamOptionsSnapshot = services.GetRequiredService>(); + var factory = ActivatorUtilities.CreateInstance(services, name, streamOptionsSnapshot.Get(name)); + factory.Init(); + return factory; + } + } +} diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorStreamOptions.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorStreamOptions.cs new file mode 100644 index 00000000000..a5e43450fa1 --- /dev/null +++ b/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorStreamOptions.cs @@ -0,0 +1,19 @@ + +namespace Orleans.Configuration +{ + /// + /// Setting class for EHGeneratorStreamProvider + /// + public class EventDataGeneratorStreamOptions : EventHubStreamOptions + { + /// + /// Configure eventhub partition count wanted. EventDataGeneratorStreamProvider would generate the same set of partitions based on the count, when initializing. + /// For example, if parition count set at 5, the generated partitions will be partition-0, partition-1, partition-2, partition-3, partiton-4 + /// + public int EventHubPartitionCount = DefaultEventHubPartitionCount; + /// + /// Default EventHubPartitionRangeStart + /// + public const int DefaultEventHubPartitionCount = 4; + } +} \ No newline at end of file diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorStreamProvider.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorStreamProvider.cs deleted file mode 100644 index 70d3a1854bb..00000000000 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventDataGeneratorStreamProvider.cs +++ /dev/null @@ -1,246 +0,0 @@ -using Microsoft.Azure.EventHubs; -using Orleans.Providers; -using Orleans.Providers.Streams.Common; -using Orleans.Runtime; -using Orleans.Serialization; -using Orleans.ServiceBus.Providers; -using Orleans.Streams; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -namespace Orleans.ServiceBus.Providers.Testing -{ - /// - /// Setting class for EHGeneratorStreamProvider - /// - public class EventHubGeneratorStreamProviderSettings : EventHubStreamProviderSettings - { - /// - /// Constructor - /// - /// - public EventHubGeneratorStreamProviderSettings(string providerName) - :base(providerName) - { - this.EventHubSettingsType = typeof(MockEventHubSettings); - } - - /// - /// StreamDataGeneratorTypeName - /// - public const string StreamDataGeneratorTypeName = nameof(StreamDataGeneratorType); - /// - /// DefaultStreamDataGeneratorType - /// - public static Type DefaultStreamDataGeneratorType = typeof(SimpleStreamEventDataGenerator); - private Type streamDataGeneratorType; - /// - /// type info for stream data generator - /// - public Type StreamDataGeneratorType - { - get { return streamDataGeneratorType ?? DefaultStreamDataGeneratorType; } - set { streamDataGeneratorType = value; } - } - - /// - /// Configure eventhub partition count wanted. EventDataGeneratorStreamProvider would generate the same set of partitions based on the count, when initializing. - /// For example, if parition count set at 5, the generated partitions will be partition-0, partition-1, partition-2, partition-3, partiton-4 - /// - public int EventHubPartitionCount = DefaultEventHubPartitionCount; - /// - /// Default EventHubPartitionRangeStart - /// - public const int DefaultEventHubPartitionCount = 4; - /// - /// EventHubPartitionRangeStartName - /// - public const string EventHubPartitionCountName = nameof(EventHubPartitionCount); - - /// - /// Populate data generating config from provider config - /// - /// - public void PopulateDataGeneratingConfigFromProviderConfig(IProviderConfiguration providerConfiguration) - { - this.streamDataGeneratorType = providerConfiguration.GetTypeProperty(StreamDataGeneratorTypeName, DefaultStreamDataGeneratorType); - this.EventHubPartitionCount = providerConfiguration.GetIntProperty(EventHubPartitionCountName, DefaultEventHubPartitionCount); - } - - /// - /// Write data generating config to a property bag - /// - /// - public void WriteDataGeneratingConfig(Dictionary properties) - { - properties.Add(StreamDataGeneratorTypeName, this.StreamDataGeneratorType.AssemblyQualifiedName); - properties.Add(EventHubPartitionCountName, this.EventHubPartitionCount.ToString()); - } - - public static string[] GenerateEventHubPartitions(int partitionCount) - { - var size = partitionCount; - var partitions = new string[size]; - for (int i = 0; i < size; i++) - partitions[i] = $"partition-{(i).ToString()}"; - return partitions; - } - } - /// - /// This is a persistent stream provider that generates it's own events rather than reading them from Eventhub. - /// This is primarily for test purposes. - /// - public class EventDataGeneratorStreamProvider : PersistentStreamProvider - { - /// - /// EHGeneratorStreamProvider.AdpaterFactory - /// - public class AdapterFactory : EventHubAdapterFactory, IControllable - { - private EventHubGeneratorStreamProviderSettings ehGeneratorSettings; - /// - /// Init method - /// - /// - /// - /// - /// - public override void Init(IProviderConfiguration providerCfg, string providerName, IServiceProvider svcProvider) - { - this.CheckpointerFactory = partition => Task.FromResult>(NoOpCheckpointer.Instance); - this.EventHubReceiverFactory = this.EHGeneratorReceiverFactory; - this.ehGeneratorSettings = new EventHubGeneratorStreamProviderSettings(providerName); - this.ehGeneratorSettings.PopulateDataGeneratingConfigFromProviderConfig(providerCfg); - base.Init(providerCfg, providerName, svcProvider); - } - - /// - protected override void InitEventHubClient() - { - //do nothing, EventDataGeneratorStreamProvider doesn't need connection with EventHubClient - } - - /// - /// Generate mocked eventhub partition Ids from EventHubGeneratorStreamProviderSettings - /// - /// - protected override Task GetPartitionIdsAsync() - { - return Task.FromResult(EventHubGeneratorStreamProviderSettings.GenerateEventHubPartitions(this.ehGeneratorSettings.EventHubPartitionCount)); - } - - private Task EHGeneratorReceiverFactory(EventHubPartitionSettings settings, string offset, ILogger logger, ITelemetryProducer telemetryProducer) - { - var generator = new EventHubPartitionDataGenerator(logger, this.serviceProvider.GetRequiredService(), this.ehGeneratorSettings); - var generatorReceiver = new EventHubPartitionGeneratorReceiver(generator); - return Task.FromResult(generatorReceiver); - } - - private void RandomlyPlaceStreamToQueue(StreamRandomPlacementArg args) - { - if (args == null) - return; - int randomNumber = args.RandomNumber; - IStreamIdentity streamId = args.StreamId; - var allQueueInTheCluster = (this.EventHubQueueMapper as EventHubQueueMapper)?.GetAllQueues().OrderBy(queueId => queueId.ToString()); - - if (allQueueInTheCluster != null) - { - //every agent receive the same random number, do a mod on queue count, get the same random queue to assign stream to. - int randomQueue = randomNumber % allQueueInTheCluster.Count(); - var queueToAssign = allQueueInTheCluster.ToList()[randomQueue]; - EventHubAdapterReceiver receiverToAssign; - if (this.EventHubReceivers.TryGetValue(queueToAssign, out receiverToAssign)) - { - receiverToAssign.ConfigureDataGeneratorForStream(streamId); - logger.Info($"Stream {streamId.Namespace}-{streamId.Guid.ToString()} is assigned to queue {queueToAssign.ToString()}"); - } - } else - { - logger.Info("Cannot get queues in the cluster, current streamQueueMapper is not EventHubQueueMapper"); - } - } - - private void StopProducingOnStream(IStreamIdentity streamId) - { - foreach (var ehReceiver in this.EventHubReceivers) - { - //if the stream is assigned to this receiver/queue, then it will ask the data generator to stop producing - ehReceiver.Value.StopProducingOnStream(streamId); - } - } - - #region IControllable interface - /// - /// Commands for IControllable - /// - public enum Commands - { - /// - /// Command for Randomly_Place_Stream_To_Queue - /// - Randomly_Place_Stream_To_Queue = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 4, - /// - /// Command for Stop_Producing_On_Stream - /// - Stop_Producing_On_Stream = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 5 - } - - /// - /// Args for RandomlyPlaceStreamToQueue method - /// - [Serializable] - public class StreamRandomPlacementArg - { - /// - /// StreamId - /// - public IStreamIdentity StreamId { get; set; } - - /// - /// A random number - /// - public int RandomNumber { get; set; } - - /// - /// Constructor - /// - /// - /// - public StreamRandomPlacementArg(IStreamIdentity streamId, int randomNumber) - { - this.StreamId = streamId; - this.RandomNumber = randomNumber; - } - } - - /// - /// Execute Command - /// - /// - /// - /// - public virtual Task ExecuteCommand(int command, object arg) - { - switch (command) - { - case (int)Commands.Randomly_Place_Stream_To_Queue: - this.RandomlyPlaceStreamToQueue(arg as StreamRandomPlacementArg); - break; - case (int)Commands.Stop_Producing_On_Stream: - this.StopProducingOnStream(arg as IStreamIdentity); - break; - default: break; - - } - return Task.FromResult((object)true); - } -#endregion - } - } -} diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventHubPartitionDataGenerator.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventHubPartitionDataGenerator.cs index faf518dd40d..6eb601537ee 100644 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventHubPartitionDataGenerator.cs +++ b/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/EventHubPartitionDataGenerator.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Linq; using Microsoft.Azure.EventHubs; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Orleans.Configuration; using Orleans.Runtime; using Orleans.Serialization; using Orleans.Streams; @@ -32,8 +34,7 @@ public class SimpleStreamEventDataGenerator : IStreamDataGenerator /// /// /// - public SimpleStreamEventDataGenerator(IStreamIdentity streamId, EventHubGeneratorStreamProviderSettings settings, - ILogger logger, SerializationManager serializationManager) + public SimpleStreamEventDataGenerator(IStreamIdentity streamId, ILogger logger, SerializationManager serializationManager) { this.StreamId = streamId; this.logger = logger; @@ -82,6 +83,11 @@ private IEnumerable GenerateEvent(int sequenceNumber) events.Add(sequenceNumber); return events; } + + public static Func> CreateFactory(IServiceProvider services) + { + return (streamIdentity) => ActivatorUtilities.CreateInstance(services, streamIdentity); + } } /// @@ -90,29 +96,29 @@ private IEnumerable GenerateEvent(int sequenceNumber) public class EventHubPartitionDataGenerator : IDataGenerator, IStreamDataGeneratingController { //differnt stream in the same partition should use the same sequenceNumberCounter - private IntCounter sequenceNumberCounter = new IntCounter(); - private ILogger logger; + private readonly EventDataGeneratorStreamOptions options; + private readonly IntCounter sequenceNumberCounter = new IntCounter(); + private readonly ILogger logger; + private Func> generatorFactory; private List> generators; - private SerializationManager serializationManager; - private EventHubGeneratorStreamProviderSettings settings; + /// /// Constructor /// /// /// /// - public EventHubPartitionDataGenerator(ILogger logger, SerializationManager serializationManager, EventHubGeneratorStreamProviderSettings settings) + public EventHubPartitionDataGenerator(EventDataGeneratorStreamOptions options, Func> generatorFactory, ILogger logger) { - this.logger = logger; + this.options = options; + this.generatorFactory = generatorFactory; this.generators = new List>(); - this.serializationManager = serializationManager; - this.settings = settings; + this.logger = logger; } /// public void AddDataGeneratorForStream(IStreamIdentity streamId) { - var generator = (IStreamDataGenerator)Activator.CreateInstance(settings.StreamDataGeneratorType, - streamId, settings, this.logger, this.serializationManager); + var generator = this.generatorFactory(streamId); generator.SequenceNumberCounter = sequenceNumberCounter; this.logger.Info($"Data generator set up on stream {streamId.Namespace}-{streamId.Guid.ToString()}."); this.generators.Add(generator); diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/MockEventHubSettings.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/MockEventHubSettings.cs deleted file mode 100644 index e4f672597ec..00000000000 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/EventDataGeneratorStreamProvider/MockEventHubSettings.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Orleans.ServiceBus.Providers; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Orleans.ServiceBus.Providers.Testing -{ - /// - /// MockEventHubSettings hard code EventHub related settings to avoid configuring those settings. It is used in EventDataGeneratorStreamProvider to mock its connection to EventHub - /// - public class MockEventHubSettings : IEventHubSettings - { - /// - /// Connection string - /// - public string ConnectionString => "MockConnectionString"; - /// - /// EventHub consumer group. - /// - public string ConsumerGroup => "MockConsumerGroup"; - /// - /// Hub Path. - /// - public string Path => "MockEventHubPath"; - /// - /// Optional parameter which configures the EventHub reciever's prefetch count. - /// - public int? PrefetchCount { get; } - - /// - public bool StartFromNow => true; - } -} diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/CachePressureMonitors/AveragingCachePressureMonitor.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/CachePressureMonitors/AveragingCachePressureMonitor.cs index 6c1fc998a51..e19c4d5f21b 100644 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/CachePressureMonitors/AveragingCachePressureMonitor.cs +++ b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/CachePressureMonitors/AveragingCachePressureMonitor.cs @@ -1,11 +1,8 @@ -using Orleans.Providers.Streams.Common; -using Orleans.Runtime; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; using Microsoft.Extensions.Logging; +using Orleans.Providers.Streams.Common; +using Orleans.Runtime; +using Orleans.Configuration; namespace Orleans.ServiceBus.Providers { @@ -15,10 +12,6 @@ namespace Orleans.ServiceBus.Providers /// public class AveragingCachePressureMonitor : ICachePressureMonitor { - /// - /// Default flow control threshold - /// - public static readonly double DefaultThreshold = 1.0 / 3.0; /// /// Cache monitor which is used to report cache related metrics /// @@ -38,7 +31,7 @@ public class AveragingCachePressureMonitor : ICachePressureMonitor /// /// public AveragingCachePressureMonitor(ILogger logger, ICacheMonitor monitor=null) - :this(DefaultThreshold, logger, monitor) + :this(EventHubStreamOptions.DEFAULT_AVERAGING_CACHE_PRESSURE_MONITORING_THRESHOLD, logger, monitor) { } /// diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubAdapterFactory.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubAdapterFactory.cs index 59b0df6de98..3969fe6d92a 100644 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubAdapterFactory.cs +++ b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubAdapterFactory.cs @@ -5,12 +5,10 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Azure.EventHubs; -using Orleans.Providers; using Orleans.Providers.Streams.Common; using Orleans.Runtime; using Orleans.Serialization; using Orleans.Streams; -using Orleans.Runtime.Configuration; using Microsoft.Extensions.Options; using Orleans.Configuration; using Orleans.Hosting; @@ -22,6 +20,8 @@ namespace Orleans.ServiceBus.Providers /// public class EventHubAdapterFactory : IQueueAdapterFactory, IQueueAdapter, IQueueAdapterCache { + private readonly ILoggerFactory loggerFactory; + /// /// Orleans logging /// @@ -32,32 +32,16 @@ public class EventHubAdapterFactory : IQueueAdapterFactory, IQueueAdapter, IQueu /// protected IServiceProvider serviceProvider; - /// - /// Provider configuration - /// - protected IProviderConfiguration providerConfig; - /// /// Stream provider settings /// - protected EventHubStreamProviderSettings adapterSettings; - - /// - /// Event Hub settings - /// - protected IEventHubSettings hubSettings; - - /// - /// Checkpointer settings - /// - protected ICheckpointerSettings checkpointerSettings; + protected EventHubStreamOptions options; private IEventHubQueueMapper streamQueueMapper; private string[] partitionIds; private ConcurrentDictionary receivers; private EventHubClient client; private ITelemetryProducer telemetryProducer; - private ILoggerFactory loggerFactory; /// /// Gets the serialization manager. /// @@ -66,7 +50,7 @@ public class EventHubAdapterFactory : IQueueAdapterFactory, IQueueAdapter, IQueu /// /// Name of the adapter. Primarily for logging purposes /// - public string Name => this.adapterSettings.StreamProviderName; + public string Name { get; } /// /// Determines whether this is a rewindable stream adapter - supports subscribing from previous point in time. @@ -113,40 +97,32 @@ public class EventHubAdapterFactory : IQueueAdapterFactory, IQueueAdapter, IQueu protected Func> EventHubReceiverFactory; internal ConcurrentDictionary EventHubReceivers { get { return this.receivers; } } internal IEventHubQueueMapper EventHubQueueMapper { get { return this.streamQueueMapper; } } - /// - /// Factory initialization. - /// Provider config must contain the event hub settings type or the settings themselves. - /// EventHubSettingsType is recommended for consumers that do not want to include secure information in the cluster configuration. - /// - /// - /// - /// - /// - public virtual void Init(IProviderConfiguration providerCfg, string providerName, IServiceProvider svcProvider) + + public EventHubAdapterFactory(string name, EventHubStreamOptions options, IServiceProvider serviceProvider, SerializationManager serializationManager, ITelemetryProducer telemetryProducer, ILoggerFactory loggerFactory) { - if (providerCfg == null) throw new ArgumentNullException(nameof(providerCfg)); - if (string.IsNullOrWhiteSpace(providerName)) throw new ArgumentNullException(nameof(providerName)); + this.Name = name; + this.options = options ?? throw new ArgumentNullException(nameof(options)); + this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + this.SerializationManager = serializationManager ?? throw new ArgumentNullException(nameof(serializationManager)); + this.telemetryProducer = telemetryProducer ?? throw new ArgumentNullException(nameof(telemetryProducer)); + this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); + } - this.providerConfig = providerCfg; - this.serviceProvider = svcProvider; - this.loggerFactory = this.serviceProvider.GetRequiredService(); + public virtual void Init() + { this.receivers = new ConcurrentDictionary(); - this.SerializationManager = this.serviceProvider.GetRequiredService(); - this.adapterSettings = new EventHubStreamProviderSettings(providerName); - this.adapterSettings.PopulateFromProviderConfig(this.providerConfig); - this.hubSettings = this.adapterSettings.GetEventHubSettings(this.providerConfig, this.serviceProvider); this.telemetryProducer = this.serviceProvider.GetService(); InitEventHubClient(); if (this.CheckpointerFactory == null) { - this.checkpointerSettings = this.adapterSettings.GetCheckpointerSettings(this.providerConfig, this.serviceProvider); - this.CheckpointerFactory = partition => EventHubCheckpointer.Create(this.checkpointerSettings, this.adapterSettings.StreamProviderName, partition, this.loggerFactory); + // TODO: make checkpointer entirely injectable, make all this stuff injectable!? + this.CheckpointerFactory = partition => EventHubCheckpointer.Create(this.options, this.Name, partition, this.loggerFactory); } if (this.CacheFactory == null) { - this.CacheFactory = CreateCacheFactory(this.adapterSettings).CreateCache; + this.CacheFactory = CreateCacheFactory(this.options).CreateCache; } if (this.StreamFailureHandlerFactory == null) @@ -157,7 +133,7 @@ public virtual void Init(IProviderConfiguration providerCfg, string providerName if (this.QueueMapperFactory == null) { - this.QueueMapperFactory = partitions => new EventHubQueueMapper(partitions, this.adapterSettings.StreamProviderName); + this.QueueMapperFactory = partitions => new EventHubQueueMapper(partitions, this.Name); } if (this.ReceiverMonitorFactory == null) @@ -165,7 +141,7 @@ public virtual void Init(IProviderConfiguration providerCfg, string providerName this.ReceiverMonitorFactory = (dimensions, logger, telemetryProducer) => new DefaultEventHubReceiverMonitor(dimensions, telemetryProducer); } - this.logger = this.loggerFactory.CreateLogger($"{this.GetType().FullName}.{this.hubSettings.Path}"); + this.logger = this.loggerFactory.CreateLogger($"{this.GetType().FullName}.{this.options.Path}"); } /// @@ -259,9 +235,9 @@ private EventHubAdapterReceiver GetOrCreateReceiver(QueueId queueId) protected virtual void InitEventHubClient() { - var connectionStringBuilder = new EventHubsConnectionStringBuilder(this.hubSettings.ConnectionString) + var connectionStringBuilder = new EventHubsConnectionStringBuilder(this.options.ConnectionString) { - EntityPath = this.hubSettings.Path + EntityPath = this.options.Path }; this.client = EventHubClient.CreateFromConnectionString(connectionStringBuilder.ToString()); } @@ -273,18 +249,18 @@ protected virtual void InitEventHubClient() /// /// /// - protected virtual IEventHubQueueCacheFactory CreateCacheFactory(EventHubStreamProviderSettings providerSettings) + protected virtual IEventHubQueueCacheFactory CreateCacheFactory(EventHubStreamOptions eventHubStreamOptions) { - var eventHubPath = this.hubSettings.Path; + var eventHubPath = this.options.Path; var sharedDimensions = new EventHubMonitorAggregationDimensions(eventHubPath); - return new EventHubQueueCacheFactory(providerSettings, this.SerializationManager, sharedDimensions, this.loggerFactory); + return new EventHubQueueCacheFactory(eventHubStreamOptions, this.SerializationManager, sharedDimensions, this.loggerFactory); } private EventHubAdapterReceiver MakeReceiver(QueueId queueId) { var config = new EventHubPartitionSettings { - Hub = hubSettings, + Hub = options, Partition = this.streamQueueMapper.QueueToPartition(queueId), }; @@ -309,5 +285,13 @@ protected virtual async Task GetPartitionIdsAsync() EventHubRuntimeInformation runtimeInfo = await client.GetRuntimeInformationAsync(); return runtimeInfo.PartitionIds; } + + public static EventHubAdapterFactory Create(IServiceProvider services, string name) + { + IOptionsSnapshot streamOptionsSnapshot = services.GetRequiredService>(); + var factory = ActivatorUtilities.CreateInstance(services, name, streamOptionsSnapshot.Get(name)); + factory.Init(); + return factory; + } } } \ No newline at end of file diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubAdapterReceiver.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubAdapterReceiver.cs index 467554518a8..398c2e75dc5 100644 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubAdapterReceiver.cs +++ b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubAdapterReceiver.cs @@ -11,6 +11,7 @@ using Orleans.Runtime; using Orleans.Streams; using Orleans.ServiceBus.Providers.Testing; +using Orleans.Hosting; namespace Orleans.ServiceBus.Providers { @@ -22,7 +23,7 @@ public class EventHubPartitionSettings /// /// Eventhub settings /// - public IEventHubSettings Hub { get; set; } + public EventHubStreamOptions Hub { get; set; } /// /// Partition name /// diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubCheckpointer.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubCheckpointer.cs index afb22217513..d46e3c4f1a8 100644 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubCheckpointer.cs +++ b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubCheckpointer.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; using Orleans.Streams; using Orleans.Streaming.EventHubs; +using Orleans.Configuration; namespace Orleans.ServiceBus.Providers { @@ -31,18 +32,18 @@ public class EventHubCheckpointer : IStreamQueueCheckpointer /// /// /// - public static async Task> Create(ICheckpointerSettings settings, string streamProviderName, string partition, ILoggerFactory loggerFactory) + public static async Task> Create(EventHubStreamOptions options, string streamProviderName, string partition, ILoggerFactory loggerFactory) { - var checkpointer = new EventHubCheckpointer(settings, streamProviderName, partition, loggerFactory); + var checkpointer = new EventHubCheckpointer(options, streamProviderName, partition, loggerFactory); await checkpointer.Initialize(); return checkpointer; } - private EventHubCheckpointer(ICheckpointerSettings settings, string streamProviderName, string partition, ILoggerFactory loggerFactory) + private EventHubCheckpointer(EventHubStreamOptions options, string streamProviderName, string partition, ILoggerFactory loggerFactory) { - if (settings == null) + if (options == null) { - throw new ArgumentNullException(nameof(settings)); + throw new ArgumentNullException(nameof(options)); } if (string.IsNullOrWhiteSpace(streamProviderName)) { @@ -52,9 +53,9 @@ private EventHubCheckpointer(ICheckpointerSettings settings, string streamProvid { throw new ArgumentNullException(nameof(partition)); } - persistInterval = settings.PersistInterval; - dataManager = new AzureTableDataManager(settings.TableName, settings.DataConnectionString, loggerFactory); - entity = EventHubPartitionCheckpointEntity.Create(streamProviderName, settings.CheckpointNamespace, partition); + persistInterval = options.CheckpointPersistInterval; + dataManager = new AzureTableDataManager(options.CheckpointTableName, options.CheckpointConnectionString, loggerFactory); + entity = EventHubPartitionCheckpointEntity.Create(streamProviderName, options.CheckpointNamespace, partition); } private Task Initialize() diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubQueueCacheFactory.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubQueueCacheFactory.cs index 1601ee513d5..a7acb322aab 100644 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubQueueCacheFactory.cs +++ b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubQueueCacheFactory.cs @@ -1,8 +1,8 @@ using System; using Microsoft.Extensions.Logging; +using Orleans.Configuration; using Orleans.Providers.Streams.Common; using Orleans.Runtime; -using Orleans.Runtime.Configuration; using Orleans.Serialization; using Orleans.Streams; using OrleansServiceBus.Providers.Streams.EventHub.StatisticMonitors; @@ -14,7 +14,7 @@ namespace Orleans.ServiceBus.Providers /// public class EventHubQueueCacheFactory : IEventHubQueueCacheFactory { - private readonly EventHubStreamProviderSettings providerSettings; + private readonly EventHubStreamOptions options; private readonly SerializationManager serializationManager; private IObjectPool bufferPool; private string bufferPoolId; @@ -35,20 +35,20 @@ public class EventHubQueueCacheFactory : IEventHubQueueCacheFactory /// /// Constructor for EventHubQueueCacheFactory /// - /// + /// /// /// shared dimensions between cache monitor and block pool monitor /// /// - public EventHubQueueCacheFactory(EventHubStreamProviderSettings providerSettings, + public EventHubQueueCacheFactory(EventHubStreamOptions options, SerializationManager serializationManager, EventHubMonitorAggregationDimensions sharedDimensions, ILoggerFactory loggerFactory, Func cacheMonitorFactory = null, Func blockPoolMonitorFactory = null) { - this.providerSettings = providerSettings; + this.options = options; this.serializationManager = serializationManager; - this.timePurge = new TimePurgePredicate(this.providerSettings.DataMinTimeInCache, this.providerSettings.DataMaxAgeInCache); + this.timePurge = new TimePurgePredicate(this.options.DataMinTimeInCache, this.options.DataMaxAgeInCache); this.sharedDimensions = sharedDimensions; this.CacheMonitorFactory = cacheMonitorFactory == null?(dimensions, logger, telemetryProducer) => new DefaultEventHubCacheMonitor(dimensions, telemetryProducer) : cacheMonitorFactory; this.BlockPoolMonitorFactory = blockPoolMonitorFactory == null? (dimensions, logger, telemetryProducer) => new DefaultEventHubBlockPoolMonitor(dimensions, telemetryProducer) : blockPoolMonitorFactory; @@ -62,16 +62,16 @@ public EventHubQueueCacheFactory(EventHubStreamProviderSettings providerSettings public IEventHubQueueCache CreateCache(string partition, IStreamQueueCheckpointer checkpointer, ILoggerFactory loggerFactory, ITelemetryProducer telemetryProducer) { string blockPoolId; - var blockPool = CreateBufferPool(this.providerSettings, loggerFactory, this.sharedDimensions, telemetryProducer, out blockPoolId); - var cache = CreateCache(partition, this.providerSettings, checkpointer, loggerFactory, blockPool, blockPoolId, this.timePurge, this.serializationManager, this.sharedDimensions, telemetryProducer); - AddCachePressureMonitors(cache, this.providerSettings, loggerFactory.CreateLogger($"{typeof(EventHubQueueCache).FullName}.{this.sharedDimensions.EventHubPath}.{partition}")); + var blockPool = CreateBufferPool(this.options, loggerFactory, this.sharedDimensions, telemetryProducer, out blockPoolId); + var cache = CreateCache(partition, this.options, checkpointer, loggerFactory, blockPool, blockPoolId, this.timePurge, this.serializationManager, this.sharedDimensions, telemetryProducer); + AddCachePressureMonitors(cache, this.options, loggerFactory.CreateLogger($"{typeof(EventHubQueueCache).FullName}.{this.sharedDimensions.EventHubPath}.{partition}")); return cache; } /// /// Function used to configure BufferPool for EventHubQueueCache. User can override this function to provide more customization on BufferPool creation /// - protected virtual IObjectPool CreateBufferPool(EventHubStreamProviderSettings providerSettings, ILoggerFactory loggerFactory, EventHubMonitorAggregationDimensions sharedDimensions, ITelemetryProducer telemetryProducer, out string blockPoolId) + protected virtual IObjectPool CreateBufferPool(EventHubStreamOptions providerOptions, ILoggerFactory loggerFactory, EventHubMonitorAggregationDimensions sharedDimensions, ITelemetryProducer telemetryProducer, out string blockPoolId) { if (this.bufferPool == null) { @@ -80,7 +80,7 @@ protected virtual IObjectPool CreateBufferPool(EventHubStreamPr var monitorDimensions = new EventHubBlockPoolMonitorDimensions(sharedDimensions, this.bufferPoolId); var objectPoolMonitor = new ObjectPoolMonitorBridge(this.BlockPoolMonitorFactory(monitorDimensions, loggerFactory, telemetryProducer), bufferSize); this.bufferPool = new ObjectPool(() => new FixedSizeBuffer(bufferSize), - objectPoolMonitor, providerSettings.StatisticMonitorWriteInterval); + objectPoolMonitor, providerOptions.StatisticMonitorWriteInterval); } blockPoolId = this.bufferPoolId; return this.bufferPool; @@ -93,27 +93,27 @@ protected virtual IObjectPool CreateBufferPool(EventHubStreamPr /// /// /// - protected virtual void AddCachePressureMonitors(IEventHubQueueCache cache, EventHubStreamProviderSettings providerSettings, + protected virtual void AddCachePressureMonitors(IEventHubQueueCache cache, EventHubStreamOptions providerOptions, ILogger cacheLogger) { - if (providerSettings.AveragingCachePressureMonitorFlowControlThreshold.HasValue) + if (providerOptions.AveragingCachePressureMonitorFlowControlThreshold.HasValue) { var avgMonitor = new AveragingCachePressureMonitor( - providerSettings.AveragingCachePressureMonitorFlowControlThreshold.Value, cacheLogger); + providerOptions.AveragingCachePressureMonitorFlowControlThreshold.Value, cacheLogger); cache.AddCachePressureMonitor(avgMonitor); } - if (providerSettings.SlowConsumingMonitorPressureWindowSize.HasValue - || providerSettings.SlowConsumingMonitorFlowControlThreshold.HasValue) + if (providerOptions.SlowConsumingMonitorPressureWindowSize.HasValue + || providerOptions.SlowConsumingMonitorFlowControlThreshold.HasValue) { var slowConsumeMonitor = new SlowConsumingPressureMonitor(cacheLogger); - if (providerSettings.SlowConsumingMonitorFlowControlThreshold.HasValue) + if (providerOptions.SlowConsumingMonitorFlowControlThreshold.HasValue) { - slowConsumeMonitor.FlowControlThreshold = providerSettings.SlowConsumingMonitorFlowControlThreshold.Value; + slowConsumeMonitor.FlowControlThreshold = providerOptions.SlowConsumingMonitorFlowControlThreshold.Value; } - if (providerSettings.SlowConsumingMonitorPressureWindowSize.HasValue) + if (providerOptions.SlowConsumingMonitorPressureWindowSize.HasValue) { - slowConsumeMonitor.PressureWindowSize = providerSettings.SlowConsumingMonitorPressureWindowSize.Value; + slowConsumeMonitor.PressureWindowSize = providerOptions.SlowConsumingMonitorPressureWindowSize.Value; } cache.AddCachePressureMonitor(slowConsumeMonitor); @@ -124,13 +124,13 @@ protected virtual void AddCachePressureMonitors(IEventHubQueueCache cache, Event /// Default function to be called to create an EventhubQueueCache in IEventHubQueueCacheFactory.CreateCache method. User can /// override this method to add more customization. /// - protected virtual IEventHubQueueCache CreateCache(string partition, EventHubStreamProviderSettings providerSettings, IStreamQueueCheckpointer checkpointer, + protected virtual IEventHubQueueCache CreateCache(string partition, EventHubStreamOptions providerOptions, IStreamQueueCheckpointer checkpointer, ILoggerFactory loggerFactory, IObjectPool bufferPool, string blockPoolId, TimePurgePredicate timePurge, SerializationManager serializationManager, EventHubMonitorAggregationDimensions sharedDimensions, ITelemetryProducer telemetryProducer) { var cacheMonitorDimensions = new EventHubCacheMonitorDimensions(sharedDimensions, partition, blockPoolId); var cacheMonitor = this.CacheMonitorFactory(cacheMonitorDimensions, loggerFactory, telemetryProducer); - return new EventHubQueueCache(checkpointer, bufferPool, timePurge, loggerFactory.CreateLogger($"{typeof(EventHubQueueCache).FullName}.{sharedDimensions.EventHubPath}.{partition}"), serializationManager, cacheMonitor, providerSettings.StatisticMonitorWriteInterval); + return new EventHubQueueCache(checkpointer, bufferPool, timePurge, loggerFactory.CreateLogger($"{typeof(EventHubQueueCache).FullName}.{sharedDimensions.EventHubPath}.{partition}"), serializationManager, cacheMonitor, providerOptions.StatisticMonitorWriteInterval); } } } \ No newline at end of file diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubSettings.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubSettings.cs deleted file mode 100644 index 3b227ed1822..00000000000 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubSettings.cs +++ /dev/null @@ -1,123 +0,0 @@ - -using System; -using System.Collections.Generic; -using System.Globalization; -using Orleans.Providers; - -namespace Orleans.ServiceBus.Providers -{ - /// - /// EventHub settings for a specific hub - /// - [Serializable] - public class EventHubSettings : IEventHubSettings - { - private const string ConnectionStringName = "EventHubConnectionString"; - private const string ConsumerGroupName = "EventHubConsumerGroup"; - private const string PathName = "EventHubPath"; - private const string PrefetchCountName = "EventHubPrefetchCount"; - private const int InvalidPrefetchCount = -1; - private const string StartFromNowName = "StartFromNow"; - private const bool StartFromNowDefault = true; - - /// - /// Default constructor - /// - public EventHubSettings(){} - - /// - /// Constructor - /// - /// EventHub connection string. - /// EventHub consumer group. - /// Hub path. - /// In cases where no checkpoint is found, this indicates if service should read from the most recent data, or from the begining of a partition. - /// optional parameter that configures the receiver prefetch count. - public EventHubSettings(string connectionString, string consumerGroup, string path, bool startFromNow = StartFromNowDefault, int? prefetchCount = null) - { - if (string.IsNullOrWhiteSpace(connectionString)) - { - throw new ArgumentNullException(nameof(connectionString)); - } - if (string.IsNullOrWhiteSpace(consumerGroup)) - { - throw new ArgumentNullException(nameof(consumerGroup)); - } - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException(nameof(path)); - } - ConnectionString = connectionString; - ConsumerGroup = consumerGroup; - Path = path; - PrefetchCount = prefetchCount; - StartFromNow = startFromNow; - } - - /// - /// EventHub connection string. - /// - public string ConnectionString { get; private set; } - /// - /// EventHub consumer group. - /// - public string ConsumerGroup { get; private set; } - /// - /// Hub path. - /// - public string Path { get; private set; } - /// - /// Optional parameter that configures the receiver prefetch count. - /// - public int? PrefetchCount { get; private set; } - /// - /// In cases where no checkpoint is found, this indicates if service should read from the most recent data, or from the begining of a partition. - /// - public bool StartFromNow { get; private set; } - - /// - /// Utility function to convert config to property bag for use in stream provider configuration - /// - /// - public void WriteProperties(Dictionary properties) - { - properties.Add(ConnectionStringName, ConnectionString); - properties.Add(ConsumerGroupName, ConsumerGroup); - properties.Add(PathName, Path); - if (PrefetchCount != null) - { - properties.Add(PrefetchCountName, PrefetchCount.Value.ToString(CultureInfo.InvariantCulture)); - } - properties.Add(StartFromNowName, StartFromNow.ToString()); - } - - /// - /// Utility function to populate config from provider config - /// - /// - public virtual void PopulateFromProviderConfig(IProviderConfiguration providerConfiguration) - { - ConnectionString = providerConfiguration.GetProperty(ConnectionStringName, null); - if (string.IsNullOrWhiteSpace(ConnectionString)) - { - throw new ArgumentOutOfRangeException(nameof(providerConfiguration), ConnectionStringName + " not set."); - } - ConsumerGroup = providerConfiguration.GetProperty(ConsumerGroupName, null); - if (string.IsNullOrWhiteSpace(ConsumerGroup)) - { - throw new ArgumentOutOfRangeException(nameof(providerConfiguration), ConsumerGroupName + " not set."); - } - Path = providerConfiguration.GetProperty(PathName, null); - if (string.IsNullOrWhiteSpace(Path)) - { - throw new ArgumentOutOfRangeException(nameof(providerConfiguration), PathName + " not set."); - } - PrefetchCount = providerConfiguration.GetIntProperty(PrefetchCountName, InvalidPrefetchCount); - if (PrefetchCount == InvalidPrefetchCount) - { - PrefetchCount = null; - } - StartFromNow = providerConfiguration.GetBoolProperty(StartFromNowName, StartFromNowDefault); - } - } -} diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamOptions.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamOptions.cs new file mode 100644 index 00000000000..931b9174190 --- /dev/null +++ b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamOptions.cs @@ -0,0 +1,75 @@ + +using System; +using System.Collections.Generic; +using Microsoft.Extensions.Options; +using Orleans.Runtime.Configuration; + +namespace Orleans.Configuration +{ + /// + /// EventHub settings for a specific hub + /// + public class EventHubStreamOptions : RecoverableStreamOptions + { + /// + /// EventHub connection string. + /// + [Redact] + public string ConnectionString { get; set; } + /// + /// EventHub consumer group. + /// + public string ConsumerGroup { get; set; } + /// + /// Hub path. + /// + public string Path { get; set; } + /// + /// Optional parameter that configures the receiver prefetch count. + /// + public int? PrefetchCount { get; set; } + /// + /// In cases where no checkpoint is found, this indicates if service should read from the most recent data, or from the begining of a partition. + /// + public bool StartFromNow { get; set; } = DEFAULT_START_FROM_NOW; + public const bool DEFAULT_START_FROM_NOW = true; + + /// + /// SlowConsumingPressureMonitorConfig + /// + public double? SlowConsumingMonitorFlowControlThreshold { get; set; } + + /// + /// SlowConsumingMonitorPressureWindowSize + /// + public TimeSpan? SlowConsumingMonitorPressureWindowSize { get; set; } + + /// + /// AveragingCachePressureMonitorFlowControlThreshold, AveragingCachePressureMonitor is turn on by default. + /// User can turn it off by setting this value to null + /// + public double? AveragingCachePressureMonitorFlowControlThreshold { get; set; } = DEFAULT_AVERAGING_CACHE_PRESSURE_MONITORING_THRESHOLD; + public const double AVERAGING_CACHE_PRESSURE_MONITORING_OFF = 1.0; + public const double DEFAULT_AVERAGING_CACHE_PRESSURE_MONITORING_THRESHOLD = 1.0 / 3.0; + + /// + /// Azure table storage connections string. + /// + [RedactConnectionString] + public string CheckpointConnectionString { get; set; } + /// + /// Azure table name. + /// + public string CheckpointTableName { get; set; } + /// + /// Interval to write checkpoints. Prevents spamming storage. + /// + public TimeSpan CheckpointPersistInterval { get; set; } = DEFAULT_CHECKPOINT_PERSIST_INTERVAL; + public static readonly TimeSpan DEFAULT_CHECKPOINT_PERSIST_INTERVAL = TimeSpan.FromMinutes(1); + + /// + /// Unique namespace for checkpoint data. Is similar to consumer group. + /// + public string CheckpointNamespace { get; set; } + } +} \ No newline at end of file diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamProvider.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamProvider.cs deleted file mode 100644 index cf11edf0406..00000000000 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ - -using Orleans.Providers.Streams.Common; - -namespace Orleans.ServiceBus.Providers -{ - /// - /// Persistent stream provider that uses EventHub for persistence - /// - public class EventHubStreamProvider : PersistentStreamProvider - { - } -} diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamProviderSettings.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamProviderSettings.cs deleted file mode 100644 index d8d1ceb4e8a..00000000000 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/EventHubStreamProviderSettings.cs +++ /dev/null @@ -1,193 +0,0 @@ - -using System; -using System.Collections.Generic; -using System.Globalization; -using Orleans.Providers; -using Orleans.Providers.Streams.Common; - -namespace Orleans.ServiceBus.Providers -{ - /// - /// Settings class for EventHubStreamProvider. - /// - public class EventHubStreamProviderSettings : RecoverableStreamProviderSettings - { - /// - /// Stream provider name. This setting is required. - /// - public string StreamProviderName { get; } - - /// - /// SlowConsumingMonitorFlowControlThresholdName - /// - public const string SlowConsumingMonitorFlowControlThresholdName = nameof(SlowConsumingMonitorFlowControlThreshold); - - /// - /// SlowConsumingPressureMonitorConfig - /// - public double? SlowConsumingMonitorFlowControlThreshold { get; set; } - - /// - /// SlowConsumingMonitorPressureWindowSizeName - /// - public const string SlowConsumingMonitorPressureWindowSizeName = nameof(SlowConsumingMonitorPressureWindowSize); - - /// - /// SlowConsumingMonitorPressureWindowSize - /// - public TimeSpan? SlowConsumingMonitorPressureWindowSize { get; set; } - - /// - /// AveragingCachePressureMonitorFlowControlThresholdName - /// - public const string AveragingCachePressureMonitorFlowControlThresholdName = nameof(AveragingCachePressureMonitorFlowControlThreshold); - - /// - /// AveragingCachePressureMonitorFlowControlThreshold, AveragingCachePressureMonitor is turn on by default. - /// User can turn it off by setting this value to null - /// - public double? AveragingCachePressureMonitorFlowControlThreshold = AveragingCachePressureMonitor.DefaultThreshold; - private const double CachePressureMonitorOffThreshold = 1.0; - /// - /// EventHubSettingsType setting name. - /// - public const string EventHubConfigTypeName = "EventHubSettingsType"; - /// - /// EventHub configuration type. Type must conform to IEventHubSettings interface. - /// - public Type EventHubSettingsType { get; set; } - - /// - /// CheckpointerSettingsType setting name. - /// - public const string CheckpointerSettingsTypeName = "CheckpointerSettingsType"; - /// - /// Checkpoint settings type. Type must conform to ICheckpointerSettings interface. - /// - public Type CheckpointerSettingsType { get; set; } - - /// - /// Constructor. Requires provider name. - /// - /// - public EventHubStreamProviderSettings(string streamProviderName) - { - StreamProviderName = streamProviderName; - } - - /// - /// Writes settings into a property bag. - /// - /// - public override void WriteProperties(Dictionary properties) - { - base.WriteProperties(properties); - if (EventHubSettingsType != null) - properties.Add(EventHubConfigTypeName, EventHubSettingsType.AssemblyQualifiedName); - if (CheckpointerSettingsType != null) - properties.Add(CheckpointerSettingsTypeName, CheckpointerSettingsType.AssemblyQualifiedName); - if (AveragingCachePressureMonitorFlowControlThreshold.HasValue) - { - properties.Add(AveragingCachePressureMonitorFlowControlThresholdName, AveragingCachePressureMonitorFlowControlThreshold.ToString()); - } - else - { - properties.Add(AveragingCachePressureMonitorFlowControlThresholdName, CachePressureMonitorOffThreshold.ToString()); - } - if (SlowConsumingMonitorPressureWindowSize.HasValue) - { - properties.Add(SlowConsumingMonitorPressureWindowSizeName, SlowConsumingMonitorPressureWindowSize.ToString()); - } - if (SlowConsumingMonitorFlowControlThreshold.HasValue) - { - properties.Add(SlowConsumingMonitorFlowControlThresholdName, SlowConsumingMonitorFlowControlThreshold.ToString()); - } - } - - /// - /// Read settings from provider configuration. - /// - /// - public override void PopulateFromProviderConfig(IProviderConfiguration providerConfiguration) - { - EventHubSettingsType = providerConfiguration.GetTypeProperty(EventHubConfigTypeName, null); - CheckpointerSettingsType = providerConfiguration.GetTypeProperty(CheckpointerSettingsTypeName, null); - if (string.IsNullOrWhiteSpace(StreamProviderName)) - { - throw new ArgumentOutOfRangeException(nameof(providerConfiguration), "StreamProviderName not set."); - } - base.PopulateFromProviderConfig(providerConfiguration); - double flowControlThreshold = 0; - if (providerConfiguration.TryGetDoubleProperty(SlowConsumingMonitorFlowControlThresholdName, out flowControlThreshold)) - { - this.SlowConsumingMonitorFlowControlThreshold = flowControlThreshold; - } - TimeSpan pressureWindowSize = TimeSpan.Zero; - if (providerConfiguration.TryGetTimeSpanProperty(SlowConsumingMonitorPressureWindowSizeName, out pressureWindowSize)) - { - this.SlowConsumingMonitorPressureWindowSize = pressureWindowSize; - } - if (providerConfiguration.TryGetDoubleProperty(AveragingCachePressureMonitorFlowControlThresholdName, out flowControlThreshold)) - { - if (flowControlThreshold >= CachePressureMonitorOffThreshold) - this.AveragingCachePressureMonitorFlowControlThreshold = null; - else - this.AveragingCachePressureMonitorFlowControlThreshold = flowControlThreshold; - } - } - - /// - /// Aquire configured IEventHubSettings class - /// - /// - /// - /// - public IEventHubSettings GetEventHubSettings(IProviderConfiguration providerConfig, IServiceProvider serviceProvider) - { - // if no event hub settings type is provided, use EventHubSettings and get populate settings from providerConfig - if (EventHubSettingsType == null) - { - EventHubSettingsType = typeof(EventHubSettings); - } - - var hubSettings = (IEventHubSettings)(serviceProvider?.GetService(EventHubSettingsType) ?? Activator.CreateInstance(EventHubSettingsType)); - if (hubSettings == null) - { - throw new ArgumentOutOfRangeException(nameof(providerConfig), "EventHubSettingsType not valid."); - } - - // if settings is an EventHubSettings class, populate settings from providerConfig - var settings = hubSettings as EventHubSettings; - settings?.PopulateFromProviderConfig(providerConfig); - - return hubSettings; - } - - /// - /// Aquire configured ICheckpointerSettings class - /// - /// - /// - /// - public ICheckpointerSettings GetCheckpointerSettings(IProviderConfiguration providerConfig, IServiceProvider serviceProvider) - { - // if no checkpointer settings type is provided, use EventHubCheckpointerSettings and get populate settings from providerConfig - if (CheckpointerSettingsType == null) - { - CheckpointerSettingsType = typeof(EventHubCheckpointerSettings); - } - - var checkpointerSettings = (ICheckpointerSettings)(serviceProvider?.GetService(CheckpointerSettingsType) ?? Activator.CreateInstance(CheckpointerSettingsType)); - if (checkpointerSettings == null) - { - throw new ArgumentOutOfRangeException(nameof(providerConfig), "CheckpointerSettingsType not valid."); - } - - // if settings is an EventHubCheckpointerSettings class, populate settings from providerConfig - var settings = checkpointerSettings as EventHubCheckpointerSettings; - settings?.PopulateFromProviderConfig(providerConfig); - - return checkpointerSettings; - } - } -} diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/ICheckpointerSettings.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/ICheckpointerSettings.cs deleted file mode 100644 index 11a2f699747..00000000000 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/ICheckpointerSettings.cs +++ /dev/null @@ -1,130 +0,0 @@ - -using System; -using System.Collections.Generic; -using Orleans.Providers; - -namespace Orleans.ServiceBus.Providers -{ - /// - /// Setting interface for checkpointer - /// - public interface ICheckpointerSettings - { - /// - /// Azure table storage data connections string - /// - string DataConnectionString { get; } - - /// - /// Azure storage table name where the checkpoints will be stored - /// - string TableName { get; } - - /// - /// How often to persist the checkpoints, if they've changed. - /// - TimeSpan PersistInterval { get; } - - /// - /// This name partitions a service's checkpoint information from other services. - /// - string CheckpointNamespace { get; } - } - - /// - /// EventHub checkpointer. - /// - public class EventHubCheckpointerSettings : ICheckpointerSettings - { - private const string DataConnectionStringName = "CheckpointerDataConnectionString"; - private const string TableNameName = "CheckpointTableName"; - private const string PersistIntervalName = "CheckpointPersistInterval"; - private const string CheckpointNamespaceName = "CheckpointNamespace"; - private static readonly TimeSpan DefaultPersistInterval = TimeSpan.FromMinutes(1); - - /// - /// Default constructor/ - /// - public EventHubCheckpointerSettings(){} - - /// - /// Constructor - /// - /// Azure table storage connections string. - /// table name. - /// checkpointer namespace. - /// checkpoint interval. - public EventHubCheckpointerSettings(string dataConnectionString, string table, string checkpointNamespace, TimeSpan? persistInterval = null) - { - if (string.IsNullOrWhiteSpace(dataConnectionString)) - { - throw new ArgumentNullException(nameof(dataConnectionString)); - } - if (string.IsNullOrWhiteSpace(table)) - { - throw new ArgumentNullException(nameof(table)); - } - if (string.IsNullOrWhiteSpace(checkpointNamespace)) - { - throw new ArgumentNullException(nameof(checkpointNamespace)); - } - DataConnectionString = dataConnectionString; - TableName = table; - CheckpointNamespace = checkpointNamespace; - PersistInterval = persistInterval ?? DefaultPersistInterval; - } - - /// - /// Azure table storage connections string. - /// - public string DataConnectionString { get; private set; } - /// - /// Azure table name. - /// - public string TableName { get; private set; } - /// - /// Intervale to write checkpoints. Prevents spamming storage. - /// - public TimeSpan PersistInterval { get; private set; } - /// - /// Unique namespace for checkpoint data. Is similar to consumer group. - /// - public string CheckpointNamespace { get; private set; } - - /// - /// Utility function to convert config to property bag for use in stream provider configuration - /// - /// - public void WriteProperties(Dictionary properties) - { - properties.Add(DataConnectionStringName, DataConnectionString); - properties.Add(TableNameName, TableName); - properties.Add(PersistIntervalName, PersistInterval.ToString()); - properties.Add(CheckpointNamespaceName, CheckpointNamespace); - } - - /// - /// Utility function to populate config from provider config - /// - /// - public virtual void PopulateFromProviderConfig(IProviderConfiguration providerConfiguration) - { - DataConnectionString = providerConfiguration.GetProperty(DataConnectionStringName, null); - if (string.IsNullOrWhiteSpace(DataConnectionString)) - { - throw new ArgumentOutOfRangeException(nameof(providerConfiguration), DataConnectionStringName + " not set."); - } - TableName = providerConfiguration.GetProperty(TableNameName, null); - if (string.IsNullOrWhiteSpace(TableName)) - { - throw new ArgumentOutOfRangeException(nameof(providerConfiguration), TableNameName + " not set."); - } - PersistInterval = providerConfiguration.GetTimeSpanProperty(PersistIntervalName, DefaultPersistInterval); - CheckpointNamespace = providerConfiguration.GetProperty(CheckpointNamespaceName, null); - if (string.IsNullOrWhiteSpace(CheckpointNamespace)) - { - throw new ArgumentOutOfRangeException(nameof(providerConfiguration), CheckpointNamespaceName + " not set."); - } - } - } -} diff --git a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/IEventHubSettings.cs b/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/IEventHubSettings.cs deleted file mode 100644 index 3678c9185e5..00000000000 --- a/src/Azure/Orleans.Streaming.EventHubs/Providers/Streams/EventHub/IEventHubSettings.cs +++ /dev/null @@ -1,34 +0,0 @@ - -namespace Orleans.ServiceBus.Providers -{ - /// - /// EventHub settings inteface for a specific hub. - /// - public interface IEventHubSettings - { - /// - /// EventHub connection string. - /// - string ConnectionString { get; } - /// - /// EventHub consumer group. - /// - string ConsumerGroup { get; } - /// - /// Hub Path. - /// - string Path { get; } - /// - /// Optional parameter which configures the EventHub reciever's prefetch count. - /// - int? PrefetchCount { get; } - - /// - /// Indicates if stream provider should read all new data in partition, or from start of partition. - /// True - read all new data added to partition. - /// False - start reading from beginning of partition. - /// Note: If checkpoints are used, stream provider will always begin reading from most recent checkpoint. - /// - bool StartFromNow { get; } - } -} diff --git a/src/Orleans.Core.Legacy/Configuration/LegacyConfigurationExtensions.cs b/src/Orleans.Core.Legacy/Configuration/LegacyConfigurationExtensions.cs index 7f03f0a422c..d957942743a 100644 --- a/src/Orleans.Core.Legacy/Configuration/LegacyConfigurationExtensions.cs +++ b/src/Orleans.Core.Legacy/Configuration/LegacyConfigurationExtensions.cs @@ -6,15 +6,11 @@ using Orleans.Messaging; using Orleans.Runtime.Configuration; using Orleans.Providers; -using Orleans.Runtime; namespace Orleans.Configuration { public static class LegacyConfigurationExtensions { - private const int ClusterClientDefaultProviderInitStage = ServiceLifecycleStage.RuntimeStorageServices; - private const int ClusterClientDefaultProviderStartStage = ServiceLifecycleStage.ApplicationServices; - public static IServiceCollection AddLegacyClientConfigurationSupport(this IServiceCollection services, ClientConfiguration configuration = null) { if (TryGetClientConfiguration(services) != null) @@ -84,7 +80,7 @@ public static IServiceCollection AddLegacyClientConfigurationSupport(this IServi LegacyGatewayListProviderConfigurator.ConfigureServices(configuration, services); // Register providers - LegacyProviderConfigurator.ConfigureServices(configuration.ProviderConfigurations, services, ClusterClientDefaultProviderInitStage, ClusterClientDefaultProviderStartStage); + LegacyProviderConfigurator.ConfigureServices(configuration.ProviderConfigurations, services); return services; } diff --git a/src/Orleans.Core/Configuration/OptionLogger/IOptionsLogger.cs b/src/Orleans.Core/Configuration/OptionLogger/IOptionsLogger.cs index d0f8c0df297..33ed30f3939 100644 --- a/src/Orleans.Core/Configuration/OptionLogger/IOptionsLogger.cs +++ b/src/Orleans.Core/Configuration/OptionLogger/IOptionsLogger.cs @@ -68,13 +68,20 @@ public void LogOptions(IEnumerable formatters) /// public void LogOption(IOptionFormatter formatter) { - var stringBuiler = new StringBuilder(); - stringBuiler.AppendLine($"Configuration {formatter.Name}: "); - foreach (var setting in formatter.Format()) + try { - stringBuiler.AppendLine($"{setting}"); + var stringBuiler = new StringBuilder(); + stringBuiler.AppendLine($"Configuration {formatter.Name}: "); + foreach (var setting in formatter.Format()) + { + stringBuiler.AppendLine($"{setting}"); + } + this.logger.LogInformation(stringBuiler.ToString()); + } catch(Exception ex) + { + this.logger.LogError(ex, $"An error occured while logging options {formatter.Name}", formatter.Name); + throw; } - this.logger.LogInformation(stringBuiler.ToString()); } } } diff --git a/src/Orleans.Core/Configuration/Options/MessagingOptions.cs b/src/Orleans.Core/Configuration/Options/MessagingOptions.cs index b799c5b6ce4..2b72463e5e5 100644 --- a/src/Orleans.Core/Configuration/Options/MessagingOptions.cs +++ b/src/Orleans.Core/Configuration/Options/MessagingOptions.cs @@ -78,5 +78,4 @@ protected List FormatSharedOptions() }; } } - } diff --git a/src/Orleans.Core/Core/IClientBuilder.cs b/src/Orleans.Core/Core/IClientBuilder.cs index 7af4ea386a1..02d59fe5c55 100644 --- a/src/Orleans.Core/Core/IClientBuilder.cs +++ b/src/Orleans.Core/Core/IClientBuilder.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; -using Orleans.Hosting; -using Orleans.Runtime.Configuration; namespace Orleans { diff --git a/src/Orleans.Core/Lifecycle/ClusterClientLifecycleExtensions.cs b/src/Orleans.Core/Lifecycle/ClusterClientLifecycleExtensions.cs new file mode 100644 index 00000000000..f7f549ef37d --- /dev/null +++ b/src/Orleans.Core/Lifecycle/ClusterClientLifecycleExtensions.cs @@ -0,0 +1,33 @@ + +namespace Orleans.Runtime +{ + public static class LifecycleParticipantExtensions + { + /// + /// Conforms components written to participate with any ILifecycleObservable to take part in specific lifecycles + /// + /// + /// + /// + public static ILifecycleParticipant ParticipateIn(this ILifecycleParticipant participant) + where TLifecycle : ILifecycleObservable + { + return new Bridge(participant); + } + + private class Bridge : ILifecycleParticipant + where TLifecycle : ILifecycleObservable + { + private readonly ILifecycleParticipant participant; + public Bridge(ILifecycleParticipant participant) + { + this.participant = participant; + } + + public void Participate(TLifecycle lifecycle) + { + this.participant?.Participate(lifecycle); + } + } + } +} diff --git a/src/Orleans.Core/Logging/ErrorCodes.cs b/src/Orleans.Core/Logging/ErrorCodes.cs index 0ca958b72ed..394ca1429fb 100644 --- a/src/Orleans.Core/Logging/ErrorCodes.cs +++ b/src/Orleans.Core/Logging/ErrorCodes.cs @@ -392,7 +392,7 @@ internal enum ErrorCode LifecycleStopFailure = SiloBase + 51, SiloStartPerfMeasure = SiloBase + 52, - CatalogBase = Runtime + 500, + CatalogBase = Runtime + 500, CatalogNonExistingActivation1 = CatalogBase + 1, Catalog_UnregisterManyAsync = CatalogBase + 2, Catalog_DestroyActivations = CatalogBase + 3, @@ -918,8 +918,6 @@ internal enum ErrorCode Provider_CatalogNoLogConsistencyProvider = ProviderManagerBase + 17, Provider_CatalogLogConsistencyProviderAllocated = ProviderManagerBase + 18, Provider_ErrorFromClose = ProviderManagerBase + 19, - Provider_ErrorFromStart = ProviderManagerBase + 20, - Provider_ErrorFromStop = ProviderManagerBase + 21, PersistentStreamPullingAgentBase = Runtime + 3300, PersistentStreamPullingAgent_01 = PersistentStreamPullingAgentBase + 1, diff --git a/src/Orleans.Core/Providers/LegacyProviderConfigurator.cs b/src/Orleans.Core/Providers/LegacyProviderConfigurator.cs index e96d12eaac5..c7322ec08c1 100644 --- a/src/Orleans.Core/Providers/LegacyProviderConfigurator.cs +++ b/src/Orleans.Core/Providers/LegacyProviderConfigurator.cs @@ -18,17 +18,18 @@ namespace Orleans.Providers public class LegacyProviderConfigurator { public const string InitStageName = "ProviderInitStage"; - public const string StartStageName = "ProviderStartStage"; } internal static class LegacyProviderConfigurator where TLifecycle : ILifecycleObservable { + public const int DefaultStage = ServiceLifecycleStage.RuntimeStorageServices; + /// /// Legacy way to configure providers. Will need to move to a legacy package in the future /// /// - internal static void ConfigureServices(IDictionary providerConfigurations, IServiceCollection services, int defaultInitStage, int defaultStartStage) + internal static void ConfigureServices(IDictionary providerConfigurations, IServiceCollection services) { // if already added providers or nothing to add, skipp if (services.Any(s => s.ServiceType == typeof(ProviderTypeLookup)) @@ -43,7 +44,7 @@ internal static void ConfigureServices(IDictionary kvp.Value.Providers.Values)) { - RegisterProvider(providerConfig, services, defaultInitStage, defaultStartStage); + RegisterProvider(providerConfig, services, DefaultStage); } } else if (providerGroup.Key == ProviderCategoryConfiguration.STORAGE_PROVIDER_CATEGORY_NAME) @@ -51,7 +52,7 @@ internal static void ConfigureServices(IDictionary(sp => sp.GetServiceByName(ProviderConstants.DEFAULT_STORAGE_PROVIDER_NAME)); foreach (IProviderConfiguration providerConfig in providerGroup.SelectMany(kvp => kvp.Value.Providers.Values)) { - RegisterProvider(providerConfig, services, defaultInitStage, defaultStartStage); + RegisterProvider(providerConfig, services, DefaultStage); } } else if (providerGroup.Key == ProviderCategoryConfiguration.LOG_CONSISTENCY_PROVIDER_CATEGORY_NAME) @@ -59,14 +60,14 @@ internal static void ConfigureServices(IDictionary(sp => sp.GetServiceByName(ProviderConstants.DEFAULT_LOG_CONSISTENCY_PROVIDER_NAME)); foreach (IProviderConfiguration providerConfig in providerGroup.SelectMany(kvp => kvp.Value.Providers.Values)) { - RegisterProvider(providerConfig, services, defaultInitStage, defaultStartStage); + RegisterProvider(providerConfig, services, DefaultStage); } } else { foreach (IProviderConfiguration providerConfig in providerGroup.SelectMany(kvp => kvp.Value.Providers.Values)) { - RegisterProvider(providerConfig, services, defaultInitStage, defaultStartStage); + RegisterProvider(providerConfig, services, DefaultStage); } } } @@ -80,17 +81,14 @@ private class ProviderLifecycleParticipant : ILifecycleParticipant provider; - public ProviderLifecycleParticipant(IProviderConfiguration config, IServiceProvider services, ILoggerFactory loggerFactory, int defaultInitStage, int defaultStartStage) + public ProviderLifecycleParticipant(IProviderConfiguration config, IServiceProvider services, ILoggerFactory loggerFactory, int defaultInitStage) { this.logger = loggerFactory.CreateLogger(config.Type); this.services = services; this.config = config; this.defaultInitStage = defaultInitStage; - this.defaultStartStage = defaultStartStage; this.provider = new Lazy(() => services.GetServiceByName(this.config.Name) as IProvider); } @@ -98,8 +96,6 @@ public virtual void Participate(TLifecycle lifecycle) { this.initStage = this.config.GetIntProperty(LegacyProviderConfigurator.InitStageName, this.defaultInitStage); lifecycle.Subscribe(this.initStage, this.Init, this.ProviderClose); - this.startStage = this.config.GetIntProperty(LegacyProviderConfigurator.StartStageName, this.defaultStartStage); - lifecycle.Subscribe(this.startStage, this.Start, this.StreamProviderClose); } @@ -127,7 +123,6 @@ private async Task ProviderClose(CancellationToken ct) try { IProvider provider = this.provider.Value; - if (provider is IStreamProvider) return; // stream providers are closed in StreamProviderClose await provider.Close(); stopWatch.Stop(); this.logger.Info(ErrorCode.SiloStartPerfMeasure, $"Closing provider {this.config.Name} of type {this.config.Type} in stage {this.initStage} took {stopWatch.ElapsedMilliseconds} Milliseconds."); @@ -139,54 +134,16 @@ private async Task ProviderClose(CancellationToken ct) throw; } } - - private async Task StreamProviderClose(CancellationToken ct) - { - var stopWatch = Stopwatch.StartNew(); - try - { - IProvider provider = this.provider.Value; - if (!(provider is IStreamProvider)) return; // only stream providers are closed here - await provider.Close(); - stopWatch.Stop(); - this.logger.Info(ErrorCode.SiloStartPerfMeasure, $"Closing stream provider {this.config.Name} of type {this.config.Type} in stage {this.startStage} took {stopWatch.ElapsedMilliseconds} Milliseconds."); - } - catch (Exception ex) - { - stopWatch.Stop(); - this.logger.Error(ErrorCode.Provider_ErrorFromStop, $"Close failed for stream provider {this.config.Name} of type {this.config.Type} in stage {this.startStage} in {stopWatch.ElapsedMilliseconds} Milliseconds.", ex); - throw; - } - } - - private async Task Start(CancellationToken ct) - { - var stopWatch = Stopwatch.StartNew(); - try - { - IStreamProviderImpl provider = this.provider.Value as IStreamProviderImpl; - if (provider == null) return; - await provider.Start(); - stopWatch.Stop(); - this.logger.Info(ErrorCode.SiloStartPerfMeasure, $"Starting stream provider {this.config.Name} of type {this.config.Type} in stage {this.startStage} took {stopWatch.ElapsedMilliseconds} Milliseconds."); - } - catch (Exception ex) - { - stopWatch.Stop(); - this.logger.Error(ErrorCode.Provider_ErrorFromStart, $"Start failed for stream provider {this.config.Name} of type {this.config.Type} in stage {this.startStage} in {stopWatch.ElapsedMilliseconds} Milliseconds.", ex); - throw; - } - } } - private static void RegisterProvider(IProviderConfiguration config, IServiceCollection services, int defaultInitStage, int defaultStartStage) + private static void RegisterProvider(IProviderConfiguration config, IServiceCollection services, int defaultInitStage) where TService : class { services.AddSingletonNamedService(config.Name, (s, n) => { Type providerType = s.GetRequiredService().GetType(config.Type); return Activator.CreateInstance(providerType) as TService; }); - services.AddSingletonNamedService>(config.Name, (s, n) => new ProviderLifecycleParticipant(config, s, s.GetRequiredService(), defaultInitStage, defaultStartStage)); + services.AddSingletonNamedService>(config.Name, (s, n) => new ProviderLifecycleParticipant(config, s, s.GetRequiredService(), defaultInitStage)); services.AddSingletonNamedService(config.Name, (s, n) => s.GetServiceByName(n) as IControllable); } } diff --git a/src/Orleans.Core/Streams/ClientStreamExtensions.cs b/src/Orleans.Core/Streams/ClientStreamExtensions.cs new file mode 100644 index 00000000000..89793b9c112 --- /dev/null +++ b/src/Orleans.Core/Streams/ClientStreamExtensions.cs @@ -0,0 +1,53 @@ + +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; +using Orleans.Providers.Streams.Common; +using Orleans.Runtime; +using Orleans.Streams; + +namespace Orleans.Hosting +{ + public static class ClientStreamExtensions + { + /// + /// Configure silo to use persistent streams. + /// + public static IClientBuilder AddPersistentStreams(this IClientBuilder builder, string name, Func adapterFactory, Action configureOptions) + where TOptions : PersistentStreamOptions, new() + { + return builder.ConfigureServices(services => services.AddClusterClientPersistentStreams(name, adapterFactory, configureOptions)); + } + + /// + /// Configure silo to use persistent streams. + /// + public static IClientBuilder AddPersistentStreams(this IClientBuilder builder, string name, Func adapterFactory, Action> configureOptions = null) + where TOptions : PersistentStreamOptions, new() + { + return builder.ConfigureServices(services => services.AddClusterClientPersistentStreams(name, adapterFactory, configureOptions)); + } + + /// + /// Configure silo to use persistent streams. + /// + public static IServiceCollection AddClusterClientPersistentStreams(this IServiceCollection services, string name, Func adapterFactory, Action configureOptions) + where TOptions : PersistentStreamOptions, new() + { + return services.AddClusterClientPersistentStreams(name, adapterFactory, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure silo to use persistent streams. + /// + public static IServiceCollection AddClusterClientPersistentStreams(this IServiceCollection services, string name, Func adapterFactory, + Action> configureOptions = null) + where TOptions : PersistentStreamOptions, new() + { + configureOptions?.Invoke(services.AddOptions(name)); + return services.AddSingletonNamedService(name, PersistentStreamProvider.Create) + .AddSingletonNamedService>(name, (s, n) => ((PersistentStreamProvider)s.GetRequiredServiceByName(n)).ParticipateIn()) + .AddSingletonNamedService(name, adapterFactory); + } + } +} diff --git a/src/Orleans.Core/Streams/Internal/IInternalStreamProvider.cs b/src/Orleans.Core/Streams/Internal/IInternalStreamProvider.cs index dfc1fcf0936..d1ffe986385 100644 --- a/src/Orleans.Core/Streams/Internal/IInternalStreamProvider.cs +++ b/src/Orleans.Core/Streams/Internal/IInternalStreamProvider.cs @@ -1,6 +1,6 @@ namespace Orleans.Streams { - internal interface IInternalStreamProvider : IStreamProviderImpl + internal interface IInternalStreamProvider { IInternalAsyncBatchObserver GetProducerInterface(IAsyncStream streamId); IInternalAsyncObservable GetConsumerInterface(IAsyncStream streamId); diff --git a/src/Orleans.Core/Streams/Internal/StreamConsumer.cs b/src/Orleans.Core/Streams/Internal/StreamConsumer.cs index 09ec3841f4e..db79faa5f31 100644 --- a/src/Orleans.Core/Streams/Internal/StreamConsumer.cs +++ b/src/Orleans.Core/Streams/Internal/StreamConsumer.cs @@ -25,21 +25,22 @@ internal class StreamConsumer : IInternalAsyncObservable [NonSerialized] private readonly ILogger logger; - public StreamConsumer(StreamImpl stream, string streamProviderName, IStreamProviderRuntime providerUtilities, IStreamPubSub pubSub, ILoggerFactory loggerFactory, bool isRewindable) + public StreamConsumer(StreamImpl stream, string streamProviderName, IStreamProviderRuntime runtime, IStreamPubSub pubSub, ILogger logger, bool isRewindable) { - if (stream == null) throw new ArgumentNullException("stream"); - if (providerUtilities == null) throw new ArgumentNullException("providerUtilities"); - if (pubSub == null) throw new ArgumentNullException("pubSub"); + if (stream == null) throw new ArgumentNullException(nameof(stream)); + if (runtime == null) throw new ArgumentNullException(nameof(runtime)); + if (pubSub == null) throw new ArgumentNullException(nameof(pubSub)); + if (logger == null) throw new ArgumentNullException(nameof(logger)); - logger = loggerFactory.CreateLogger(string.Format("<{0}>-{1}", typeof(StreamConsumer).FullName, stream)); + this.logger = logger; this.stream = stream; this.streamProviderName = streamProviderName; - providerRuntime = providerUtilities; + this.providerRuntime = runtime; this.pubSub = pubSub; - IsRewindable = isRewindable; - myExtension = null; - myGrainReference = null; - bindExtLock = new AsyncLock(); + this.IsRewindable = isRewindable; + this.myExtension = null; + this.myGrainReference = null; + this.bindExtLock = new AsyncLock(); } public Task> SubscribeAsync(IAsyncObserver observer) diff --git a/src/Orleans.Core/Streams/PersistentStreams/IStreamQueueBalancer.cs b/src/Orleans.Core/Streams/PersistentStreams/IStreamQueueBalancer.cs index c497c12c4a7..1afd95938f3 100644 --- a/src/Orleans.Core/Streams/PersistentStreams/IStreamQueueBalancer.cs +++ b/src/Orleans.Core/Streams/PersistentStreams/IStreamQueueBalancer.cs @@ -1,8 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Orleans.Runtime; using System; -using Orleans.Providers; namespace Orleans.Streams { @@ -20,12 +18,10 @@ public interface IStreamQueueBalancer /// /// /// - /// Provider configuration for current stream provider /// Task Initialize(string strProviderName, IStreamQueueMapper queueMapper, - TimeSpan siloMaturityPeriod, - IProviderConfiguration providerConfig); + TimeSpan siloMaturityPeriod); /// /// Retrieves the latest queue distribution for this balancer. diff --git a/src/Orleans.Core/Streams/PersistentStreams/PersistentStreamProvider.cs b/src/Orleans.Core/Streams/PersistentStreams/PersistentStreamProvider.cs index 24e512fc80c..9c3807157b7 100644 --- a/src/Orleans.Core/Streams/PersistentStreams/PersistentStreamProvider.cs +++ b/src/Orleans.Core/Streams/PersistentStreams/PersistentStreamProvider.cs @@ -1,7 +1,10 @@ using System; +using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Orleans.Configuration; using Orleans.Runtime; using Orleans.Serialization; using Orleans.Streams; @@ -9,15 +12,6 @@ namespace Orleans.Providers.Streams.Common { - [Serializable] - public enum PersistentStreamProviderState - { - None, - Initialized, - AgentsStarted, - AgentsStopped, - } - [Serializable] public enum PersistentStreamProviderCommand { @@ -36,82 +30,66 @@ public enum PersistentStreamProviderCommand /// Persistent stream provider that uses an adapter for persistence /// /// - public class PersistentStreamProvider : IInternalStreamProvider, IControllable, IStreamSubscriptionManagerRetriever - where TAdapterFactory : IQueueAdapterFactory, new() + public class PersistentStreamProvider : IStreamProvider, IInternalStreamProvider, IControllable, IStreamSubscriptionManagerRetriever, ILifecycleParticipant { - private ILogger logger; + private readonly PersistentStreamOptions options; + private readonly ILogger logger; + private readonly IStreamProviderRuntime runtime; + private readonly SerializationManager serializationManager; + private readonly IRuntimeClient runtimeClient; + private readonly ProviderStateManager stateManager = new ProviderStateManager(); private IQueueAdapterFactory adapterFactory; - private IStreamProviderRuntime providerRuntime; private IQueueAdapter queueAdapter; private IPersistentStreamPullingManager pullingAgentManager; - private PersistentStreamProviderConfig myConfig; - internal const string StartupStatePropertyName = "StartupState"; - internal const PersistentStreamProviderState StartupStateDefaultValue = PersistentStreamProviderState.AgentsStarted; - private PersistentStreamProviderState startupState; - private readonly ProviderStateManager stateManager = new ProviderStateManager(); - private SerializationManager serializationManager; - private IRuntimeClient runtimeClient; private IStreamSubscriptionManager streamSubscriptionManager; - private IProviderConfiguration providerConfig; + public string Name { get; private set; } - private ILoggerFactory loggerFactory; public bool IsRewindable { get { return queueAdapter.IsRewindable; } } - public async Task Init(string name, IProviderRuntime providerUtilitiesManager, IProviderConfiguration config) + public PersistentStreamProvider(string name, PersistentStreamOptions options, IProviderRuntime runtime, SerializationManager serializationManager, ILogger logger) { - if(!stateManager.PresetState(ProviderState.Initialized)) return; - if (String.IsNullOrEmpty(name)) throw new ArgumentNullException("name"); - if (providerUtilitiesManager == null) throw new ArgumentNullException("providerUtilitiesManager"); - if (config == null) throw new ArgumentNullException("config"); - - Name = name; - providerRuntime = (IStreamProviderRuntime)providerUtilitiesManager; - adapterFactory = new TAdapterFactory(); - adapterFactory.Init(config, Name, providerRuntime.ServiceProvider); - queueAdapter = await adapterFactory.CreateAdapter(); - this.loggerFactory = providerUtilitiesManager.ServiceProvider.GetRequiredService(); - this.logger = loggerFactory.CreateLogger(this.GetType().FullName); - myConfig = new PersistentStreamProviderConfig(config); - this.providerConfig = config; - this.serializationManager = this.providerRuntime.ServiceProvider.GetRequiredService(); - this.runtimeClient = this.providerRuntime.ServiceProvider.GetRequiredService(); - if (this.myConfig.PubSubType == StreamPubSubType.ExplicitGrainBasedAndImplicit - || this.myConfig.PubSubType == StreamPubSubType.ExplicitGrainBasedOnly) + if (String.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name)); + if (options == null) throw new ArgumentNullException(nameof(options)); + if (runtime == null) throw new ArgumentNullException(nameof(runtime)); + if (serializationManager == null) throw new ArgumentNullException(nameof(serializationManager)); + if (logger == null) throw new ArgumentNullException(nameof(logger)); + + this.Name = name; + this.options = options; + this.runtime = runtime.ServiceProvider.GetRequiredService(); + this.runtimeClient = runtime.ServiceProvider.GetRequiredService(); + this.serializationManager = serializationManager; + this.logger = logger; + } + + private async Task Init(CancellationToken token) + { + if(!this.stateManager.PresetState(ProviderState.Initialized)) return; + this.adapterFactory = this.runtime.ServiceProvider.GetRequiredServiceByName(this.Name); + this.queueAdapter = await adapterFactory.CreateAdapter(); + + if (this.options.PubSubType == StreamPubSubType.ExplicitGrainBasedAndImplicit + || this.options.PubSubType == StreamPubSubType.ExplicitGrainBasedOnly) { - this.streamSubscriptionManager = this.providerRuntime.ServiceProvider + this.streamSubscriptionManager = this.runtime.ServiceProvider .GetService().GetStreamSubscriptionManager(StreamSubscriptionManagerType.ExplicitSubscribeOnly); } - string startup; - if (config.Properties.TryGetValue(StartupStatePropertyName, out startup)) - { - if(!Enum.TryParse(startup, true, out startupState)) - throw new ArgumentException( - String.Format("Unsupported value '{0}' for configuration parameter {1} of stream provider {2}.", startup, StartupStatePropertyName, config.Name)); - } - else - startupState = StartupStateDefaultValue; - logger.Info("Initialized PersistentStreamProvider<{0}> with name {1}, Adapter {2} and config {3}, {4} = {5}.", - typeof(TAdapterFactory).Name, - Name, - queueAdapter.Name, - myConfig, - StartupStatePropertyName, startupState); - stateManager.CommitState(); + this.stateManager.CommitState(); } - public async Task Start() + private async Task Start(CancellationToken token) { - if (!stateManager.PresetState(ProviderState.Started)) return; - if (queueAdapter.Direction.Equals(StreamProviderDirection.ReadOnly) || - queueAdapter.Direction.Equals(StreamProviderDirection.ReadWrite)) + if (!this.stateManager.PresetState(ProviderState.Started)) return; + if (this.queueAdapter.Direction.Equals(StreamProviderDirection.ReadOnly) || + this.queueAdapter.Direction.Equals(StreamProviderDirection.ReadWrite)) { - var siloRuntime = providerRuntime as ISiloSideStreamProviderRuntime; + var siloRuntime = this.runtime as ISiloSideStreamProviderRuntime; if (siloRuntime != null) { - pullingAgentManager = await siloRuntime.InitializePullingAgents(Name, adapterFactory, queueAdapter, myConfig, this.providerConfig); + this.pullingAgentManager = await siloRuntime.InitializePullingAgents(this.Name, this.adapterFactory, this.queueAdapter, this.options); // TODO: No support yet for DeliveryDisabled, only Stopped and Started - if (startupState == PersistentStreamProviderState.AgentsStarted) + if (this.options.StartupState == PersistentStreamOptions.RunState.AgentsStarted) await pullingAgentManager.StartAgents(); } } @@ -123,10 +101,10 @@ public IStreamSubscriptionManager GetStreamSubscriptionManager() return this.streamSubscriptionManager; } - public async Task Close() + private async Task Close(CancellationToken token) { if (!stateManager.PresetState(ProviderState.Closed)) return; - var siloRuntime = providerRuntime as ISiloSideStreamProviderRuntime; + var siloRuntime = this.runtime as ISiloSideStreamProviderRuntime; if (siloRuntime != null) { await pullingAgentManager.Stop(); @@ -137,7 +115,7 @@ public async Task Close() public IAsyncStream GetStream(Guid id, string streamNamespace) { var streamId = StreamId.GetStreamId(id, Name, streamNamespace); - return providerRuntime.GetStreamDirectory().GetOrAddStream( + return this.runtime.GetStreamDirectory().GetOrAddStream( streamId, () => new StreamImpl(streamId, this, IsRewindable, this.runtimeClient)); } @@ -147,7 +125,7 @@ IInternalAsyncBatchObserver IInternalStreamProvider.GetProducerInterface(I { throw new InvalidOperationException($"Stream provider {queueAdapter.Name} is ReadOnly."); } - return new PersistentStreamProducer((StreamImpl)stream, providerRuntime, queueAdapter, IsRewindable, this.serializationManager); + return new PersistentStreamProducer((StreamImpl)stream, this.runtime, queueAdapter, IsRewindable, this.serializationManager); } IInternalAsyncObservable IInternalStreamProvider.GetConsumerInterface(IAsyncStream streamId) @@ -157,7 +135,7 @@ IInternalAsyncObservable IInternalStreamProvider.GetConsumerInterface(IAsy private IInternalAsyncObservable GetConsumerInterfaceImpl(IAsyncStream stream) { - return new StreamConsumer((StreamImpl)stream, Name, providerRuntime, providerRuntime.PubSub(myConfig.PubSubType), this.loggerFactory, IsRewindable); + return new StreamConsumer((StreamImpl)stream, Name, this.runtime, this.runtime.PubSub(this.options.PubSubType), this.logger, IsRewindable); } public Task ExecuteCommand(int command, object arg) @@ -184,5 +162,18 @@ public Task ExecuteCommand(int command, object arg) logger.Warn(0, $"Got command {(PersistentStreamProviderCommand)command} with arg {arg}, but PullingAgentManager is not initialized yet. Ignoring the command."); throw new ArgumentException("PullingAgentManager is not initialized yet."); } + + public void Participate(ILifecycleObservable lifecycle) + { + lifecycle.Subscribe(this.options.InitStage, Init); + lifecycle.Subscribe(this.options.StartStage, Start, Close); + } + + public static IStreamProvider Create(IServiceProvider services, string name) + where TOptions : PersistentStreamOptions, new() + { + IOptionsSnapshot optionsSnapshot = services.GetRequiredService>(); + return ActivatorUtilities.CreateInstance(services, name, optionsSnapshot.Get(name)); + } } } diff --git a/src/Orleans.Core/Streams/PersistentStreams/PersistentStreamProviderOptions.cs b/src/Orleans.Core/Streams/PersistentStreams/PersistentStreamProviderOptions.cs new file mode 100644 index 00000000000..63c487fb654 --- /dev/null +++ b/src/Orleans.Core/Streams/PersistentStreams/PersistentStreamProviderOptions.cs @@ -0,0 +1,52 @@ + +using System; +using Orleans.Streams; + +namespace Orleans.Configuration +{ + public class PersistentStreamOptions + { + [Serializable] + public enum RunState + { + None, + Initialized, + AgentsStarted, + AgentsStopped, + } + + public TimeSpan GetQueueMsgsTimerPeriod { get; set; } = DEFAULT_GET_QUEUE_MESSAGES_TIMER_PERIOD; + public static readonly TimeSpan DEFAULT_GET_QUEUE_MESSAGES_TIMER_PERIOD = TimeSpan.FromMilliseconds(100); + + public TimeSpan InitQueueTimeout { get; set; } = DEFAULT_INIT_QUEUE_TIMEOUT; + public static readonly TimeSpan DEFAULT_INIT_QUEUE_TIMEOUT = TimeSpan.FromSeconds(5); + + public TimeSpan MaxEventDeliveryTime { get; set; } = DEFAULT_MAX_EVENT_DELIVERY_TIME; + public static readonly TimeSpan DEFAULT_MAX_EVENT_DELIVERY_TIME = TimeSpan.FromMinutes(1); + + public TimeSpan StreamInactivityPeriod { get; set; } = DEFAULT_STREAM_INACTIVITY_PERIOD; + public static readonly TimeSpan DEFAULT_STREAM_INACTIVITY_PERIOD = TimeSpan.FromMinutes(30); + + /// + /// The queue balancer type for your stream provider. If you are using a custom queue balancer by injecting IStreamQueueBalancer as a transient service into DI, + /// you should use your custom balancer's type + /// + public Type BalancerType { get; set; } = DEFAULT_STREAM_QUEUE_BALANCER_TYPE; + public static Type DEFAULT_STREAM_QUEUE_BALANCER_TYPE = null; + + public StreamPubSubType PubSubType { get; set; } = DEFAULT_STREAM_PUBSUB_TYPE; + public const StreamPubSubType DEFAULT_STREAM_PUBSUB_TYPE = StreamPubSubType.ExplicitGrainBasedAndImplicit; + + public TimeSpan SiloMaturityPeriod { get; set; } = DEFAULT_SILO_MATURITY_PERIOD; + public static readonly TimeSpan DEFAULT_SILO_MATURITY_PERIOD = TimeSpan.FromMinutes(2); + + public RunState StartupState = DEFAULT_STARTUP_STATE; + public const RunState DEFAULT_STARTUP_STATE = RunState.AgentsStarted; + + public int InitStage { get; set; } = DEFAULT_INIT_STAGE; + public const int DEFAULT_INIT_STAGE = ServiceLifecycleStage.ApplicationServices; + + public int StartStage { get; set; } = DEFAULT_START_STAGE; + public const int DEFAULT_START_STAGE = ServiceLifecycleStage.Active; + } +} diff --git a/src/Orleans.Core/Streams/Providers/IStreamProviderRuntime.cs b/src/Orleans.Core/Streams/Providers/IStreamProviderRuntime.cs index b032f717792..b8f6b7272a7 100644 --- a/src/Orleans.Core/Streams/Providers/IStreamProviderRuntime.cs +++ b/src/Orleans.Core/Streams/Providers/IStreamProviderRuntime.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Orleans.Configuration; using Orleans.Providers; using Orleans.Runtime; -using Orleans.Runtime.Configuration; using Orleans.Streams.Core; namespace Orleans.Streams @@ -54,8 +54,7 @@ Task InitializePullingAgents( string streamProviderName, IQueueAdapterFactory adapterFactory, IQueueAdapter queueAdapter, - PersistentStreamProviderConfig config, - IProviderConfiguration providerConfig); + PersistentStreamOptions config); } public enum StreamPubSubType @@ -65,108 +64,6 @@ public enum StreamPubSubType ImplicitOnly, } - [Serializable] - public class PersistentStreamProviderConfig - { - public const string GET_QUEUE_MESSAGES_TIMER_PERIOD = "GetQueueMessagesTimerPeriod"; - public static readonly TimeSpan DEFAULT_GET_QUEUE_MESSAGES_TIMER_PERIOD = TimeSpan.FromMilliseconds(100); - - public const string INIT_QUEUE_TIMEOUT = "InitQueueTimeout"; - public static readonly TimeSpan DEFAULT_INIT_QUEUE_TIMEOUT = TimeSpan.FromSeconds(5); - - public const string MAX_EVENT_DELIVERY_TIME = "MaxEventDeliveryTime"; - public static readonly TimeSpan DEFAULT_MAX_EVENT_DELIVERY_TIME = TimeSpan.FromMinutes(1); - - public const string STREAM_INACTIVITY_PERIOD = "StreamInactivityPeriod"; - public static readonly TimeSpan DEFAULT_STREAM_INACTIVITY_PERIOD = TimeSpan.FromMinutes(30); - - public const string QUEUE_BALANCER_TYPE = "QueueBalancerType"; - //default balancer type if ConsistentRingBalancer - public static Type DEFAULT_STREAM_QUEUE_BALANCER_TYPE = null; - - public const string STREAM_PUBSUB_TYPE = "PubSubType"; - public const StreamPubSubType DEFAULT_STREAM_PUBSUB_TYPE = StreamPubSubType.ExplicitGrainBasedAndImplicit; - - public const string SILO_MATURITY_PERIOD = "SiloMaturityPeriod"; - public static readonly TimeSpan DEFAULT_SILO_MATURITY_PERIOD = TimeSpan.FromMinutes(2); - - public TimeSpan GetQueueMsgsTimerPeriod { get; set; } = DEFAULT_GET_QUEUE_MESSAGES_TIMER_PERIOD; - public TimeSpan InitQueueTimeout { get; set; } = DEFAULT_INIT_QUEUE_TIMEOUT; - public TimeSpan MaxEventDeliveryTime { get; set; } = DEFAULT_MAX_EVENT_DELIVERY_TIME; - public TimeSpan StreamInactivityPeriod { get; set; } = DEFAULT_STREAM_INACTIVITY_PERIOD; - - /// - /// The queue balancer type for your stream provider. If you are using a custom queue balancer by injecting IStreamQueueBalancer as a transient service into DI, - /// you should use your custom balancer's type - /// - public Type BalancerType { get; set; } = DEFAULT_STREAM_QUEUE_BALANCER_TYPE; - public StreamPubSubType PubSubType { get; set; } = DEFAULT_STREAM_PUBSUB_TYPE; - public TimeSpan SiloMaturityPeriod { get; set; } = DEFAULT_SILO_MATURITY_PERIOD; - - public PersistentStreamProviderConfig() - { - } - - public PersistentStreamProviderConfig(IProviderConfiguration config) - { - string timePeriod; - if (config.Properties.TryGetValue(GET_QUEUE_MESSAGES_TIMER_PERIOD, out timePeriod)) - GetQueueMsgsTimerPeriod = ConfigUtilities.ParseTimeSpan(timePeriod, - "Invalid time value for the " + GET_QUEUE_MESSAGES_TIMER_PERIOD + " property in the provider config values."); - - string timeout; - if (config.Properties.TryGetValue(INIT_QUEUE_TIMEOUT, out timeout)) - InitQueueTimeout = ConfigUtilities.ParseTimeSpan(timeout, - "Invalid time value for the " + INIT_QUEUE_TIMEOUT + " property in the provider config values."); - - BalancerType = config.GetTypeProperty(QUEUE_BALANCER_TYPE, DEFAULT_STREAM_QUEUE_BALANCER_TYPE); - - if (config.Properties.TryGetValue(MAX_EVENT_DELIVERY_TIME, out timeout)) - MaxEventDeliveryTime = ConfigUtilities.ParseTimeSpan(timeout, - "Invalid time value for the " + MAX_EVENT_DELIVERY_TIME + " property in the provider config values."); - - if (config.Properties.TryGetValue(STREAM_INACTIVITY_PERIOD, out timeout)) - StreamInactivityPeriod = ConfigUtilities.ParseTimeSpan(timeout, - "Invalid time value for the " + STREAM_INACTIVITY_PERIOD + " property in the provider config values."); - - string pubSubTypeString; - if (config.Properties.TryGetValue(STREAM_PUBSUB_TYPE, out pubSubTypeString)) - PubSubType = (StreamPubSubType)Enum.Parse(typeof(StreamPubSubType), pubSubTypeString); - - string immaturityPeriod; - if (config.Properties.TryGetValue(SILO_MATURITY_PERIOD, out immaturityPeriod)) - SiloMaturityPeriod = ConfigUtilities.ParseTimeSpan(immaturityPeriod, - "Invalid time value for the " + SILO_MATURITY_PERIOD + " property in the provider config values."); - } - - /// - /// Utility function to convert config to property bag for use in stream provider configuration - /// - /// - public void WriteProperties(Dictionary properties) - { - properties[GET_QUEUE_MESSAGES_TIMER_PERIOD] = ConfigUtilities.ToParseableTimeSpan(GetQueueMsgsTimerPeriod); - properties[INIT_QUEUE_TIMEOUT] = ConfigUtilities.ToParseableTimeSpan(InitQueueTimeout); - properties[QUEUE_BALANCER_TYPE] = BalancerType.AssemblyQualifiedName; - properties[MAX_EVENT_DELIVERY_TIME] = ConfigUtilities.ToParseableTimeSpan(MaxEventDeliveryTime); - properties[STREAM_INACTIVITY_PERIOD] = ConfigUtilities.ToParseableTimeSpan(StreamInactivityPeriod); - properties[STREAM_PUBSUB_TYPE] = PubSubType.ToString(); - properties[SILO_MATURITY_PERIOD] = ConfigUtilities.ToParseableTimeSpan(SiloMaturityPeriod); - } - - public override string ToString() - { - return String.Format("{0}={1}, {2}={3}, {4}={5}, {6}={7}, {8}={9}, {10}={11}, {12}={13}", - GET_QUEUE_MESSAGES_TIMER_PERIOD, GetQueueMsgsTimerPeriod, - INIT_QUEUE_TIMEOUT, InitQueueTimeout, - MAX_EVENT_DELIVERY_TIME, MaxEventDeliveryTime, - STREAM_INACTIVITY_PERIOD, StreamInactivityPeriod, - QUEUE_BALANCER_TYPE, BalancerType, - STREAM_PUBSUB_TYPE, PubSubType, - SILO_MATURITY_PERIOD, SiloMaturityPeriod); - } - } - internal interface IStreamPubSub // Compare with: IPubSubRendezvousGrain { Task> RegisterProducer(StreamId streamId, string streamProvider, IStreamProducerExtension streamProducer); diff --git a/src/Orleans.Core/Streams/Providers/IStreamProviderImpl.cs b/src/Orleans.Core/Streams/Providers/ProviderStartException.cs similarity index 81% rename from src/Orleans.Core/Streams/Providers/IStreamProviderImpl.cs rename to src/Orleans.Core/Streams/Providers/ProviderStartException.cs index 62dcce7b318..9c473c06983 100644 --- a/src/Orleans.Core/Streams/Providers/IStreamProviderImpl.cs +++ b/src/Orleans.Core/Streams/Providers/ProviderStartException.cs @@ -1,16 +1,9 @@ using System; -using System.Threading.Tasks; using System.Runtime.Serialization; -using Orleans.Providers; using Orleans.Runtime; namespace Orleans.Streams { - public interface IStreamProviderImpl : IStreamProvider, IProvider - { - Task Start(); - } - /// /// Exception thrown whenever a provider has failed to be started. /// diff --git a/src/Orleans.Core/Streams/QueueAdapters/IQueueAdapterFactory.cs b/src/Orleans.Core/Streams/QueueAdapters/IQueueAdapterFactory.cs index 8788a327ff9..072d2c0509f 100644 --- a/src/Orleans.Core/Streams/QueueAdapters/IQueueAdapterFactory.cs +++ b/src/Orleans.Core/Streams/QueueAdapters/IQueueAdapterFactory.cs @@ -9,8 +9,6 @@ namespace Orleans.Streams /// public interface IQueueAdapterFactory { - void Init(IProviderConfiguration config, string providerName, IServiceProvider serviceProvider); - /// /// Create queue adapter. /// diff --git a/src/Orleans.Core/Streams/SimpleMessageStream/SimpleMessageStreamProvider.cs b/src/Orleans.Core/Streams/SimpleMessageStream/SimpleMessageStreamProvider.cs index ac22676fbaa..ec4b055f9ee 100644 --- a/src/Orleans.Core/Streams/SimpleMessageStream/SimpleMessageStreamProvider.cs +++ b/src/Orleans.Core/Streams/SimpleMessageStream/SimpleMessageStreamProvider.cs @@ -10,7 +10,7 @@ namespace Orleans.Providers.Streams.SimpleMessageStream { using Orleans.Serialization; - public class SimpleMessageStreamProvider : IInternalStreamProvider, IStreamSubscriptionManagerRetriever + public class SimpleMessageStreamProvider : IStreamProvider, IProvider, IInternalStreamProvider, IStreamSubscriptionManagerRetriever { public string Name { get; private set; } @@ -101,7 +101,7 @@ IInternalAsyncObservable IInternalStreamProvider.GetConsumerInterface(IAsy private IInternalAsyncObservable GetConsumerInterfaceImpl(IAsyncStream stream) { return new StreamConsumer((StreamImpl)stream, Name, providerRuntime, - providerRuntime.PubSub(pubSubType), this.loggerFactory, IsRewindable); + providerRuntime.PubSub(pubSubType), this.logger, IsRewindable); } } } diff --git a/src/Orleans.Core/Utils/KeyedService.cs b/src/Orleans.Core/Utils/KeyedService.cs index 997c016babc..7aa5f73d185 100644 --- a/src/Orleans.Core/Utils/KeyedService.cs +++ b/src/Orleans.Core/Utils/KeyedService.cs @@ -6,17 +6,20 @@ namespace Orleans.Runtime { - public class KeyedService : IKeyedService - where TInstance : TService + public class KeyedService : IKeyedService + where TService : class { + private readonly Func factory; + public TKey Key { get; } - public KeyedService(TKey key) + public KeyedService(TKey key, IServiceProvider services, Func factory) { this.Key = key; + this.factory = factory; } - public TService GetService(IServiceProvider services) => services.GetService(); + public TService GetService(IServiceProvider services) => factory(services,Key); public bool Equals(TKey other) { @@ -24,10 +27,20 @@ public bool Equals(TKey other) } } + public class KeyedService : KeyedService + where TInstance : TService + where TService : class + { + public KeyedService(TKey key, IServiceProvider services) + : base(key, services, (sp, k) => sp.GetService()) + { + } + } + public class KeyedSingletonService : IKeyedService where TService : class { - private Lazy instance; + private readonly Lazy instance; public TKey Key { get; } @@ -71,6 +84,15 @@ public IEnumerable> GetServices(IServiceProvider s public static class KeyedServiceExtensions { + /// + /// Register a transient keyed service + /// + public static IServiceCollection AddTransientKeyedService(this IServiceCollection collection, TKey key, Func factory) + where TService : class + { + return collection.AddSingleton>(sp => new KeyedService(key, sp, factory)); + } + /// /// Register a transient keyed service /// @@ -79,7 +101,7 @@ public static IServiceCollection AddTransientKeyedService(); - return collection.AddSingleton>(sp => new KeyedService(key)); + return collection.AddSingleton>(sp => new KeyedService(key,sp)); } /// @@ -102,6 +124,15 @@ public static IServiceCollection AddSingletonKeyedService>(sp => new KeyedSingletonService(key, sp)); } + /// + /// Register a transient named service + /// + public static IServiceCollection AddTransientNamedService(this IServiceCollection collection, string name, Func factory) + where TService : class + { + return collection.AddTransientKeyedService(name, factory); + } + /// /// Register a transient named service /// diff --git a/src/Orleans.Runtime.Abstractions/Hosting/StreamHostingExtensions.cs b/src/Orleans.Runtime.Abstractions/Hosting/StreamHostingExtensions.cs new file mode 100644 index 00000000000..194a033eb55 --- /dev/null +++ b/src/Orleans.Runtime.Abstractions/Hosting/StreamHostingExtensions.cs @@ -0,0 +1,55 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Runtime; +using Orleans.Hosting; +using Orleans.Streams; +using Orleans.Providers.Streams.Common; +using Orleans.Providers; +using Orleans.Configuration; + +namespace Orleans.Hosting +{ + public static class StreamHostingExtensions + { + /// + /// Configure silo to use persistent streams. + /// + public static ISiloHostBuilder AddPersistentStreams(this ISiloHostBuilder builder, string name, Func adapterFactory, Action configureOptions) + where TOptions : PersistentStreamOptions, new() + { + return builder.ConfigureServices(services => services.AddSiloPersistentStreams(name, adapterFactory, configureOptions)); + } + + /// + /// Configure silo to use persistent streams. + /// + public static ISiloHostBuilder AddPersistentStreams(this ISiloHostBuilder builder, string name, Func adapterFactory, Action> configureOptions = null) + where TOptions : PersistentStreamOptions, new() + { + return builder.ConfigureServices(services => services.AddSiloPersistentStreams(name, adapterFactory, configureOptions)); + } + + /// + /// Configure silo to use persistent streams. + /// + public static IServiceCollection AddSiloPersistentStreams(this IServiceCollection services, string name, Func adapterFactory, Action configureOptions) + where TOptions : PersistentStreamOptions, new() + { + return services.AddSiloPersistentStreams(name, adapterFactory, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure silo to use persistent streams. + /// + public static IServiceCollection AddSiloPersistentStreams(this IServiceCollection services, string name, Func adapterFactory, + Action> configureOptions = null) + where TOptions : PersistentStreamOptions, new() + { + configureOptions?.Invoke(services.AddOptions(name)); + return services.AddSingletonNamedService(name, PersistentStreamProvider.Create) + .AddSingletonNamedService>(name, (s, n) => ((PersistentStreamProvider)s.GetRequiredServiceByName(n)).ParticipateIn()) + .AddSingletonNamedService(name, adapterFactory) + .AddSingletonNamedService(name, (s, n) => s.GetServiceByName(n) as IControllable); + } + } +} diff --git a/src/Orleans.Runtime.Abstractions/Orleans.Runtime.Abstractions.csproj b/src/Orleans.Runtime.Abstractions/Orleans.Runtime.Abstractions.csproj index dc6b3fe580f..c7f54eaf7e6 100644 --- a/src/Orleans.Runtime.Abstractions/Orleans.Runtime.Abstractions.csproj +++ b/src/Orleans.Runtime.Abstractions/Orleans.Runtime.Abstractions.csproj @@ -18,4 +18,8 @@ + + + + diff --git a/src/Orleans.Runtime.Legacy/Configuration/LegacyClusterConfigurationExtensions.cs b/src/Orleans.Runtime.Legacy/Configuration/LegacyClusterConfigurationExtensions.cs index 5039334f78a..d10105c0a30 100644 --- a/src/Orleans.Runtime.Legacy/Configuration/LegacyClusterConfigurationExtensions.cs +++ b/src/Orleans.Runtime.Legacy/Configuration/LegacyClusterConfigurationExtensions.cs @@ -3,7 +3,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; -using Microsoft.Extensions.Logging; using Orleans.Configuration; using Orleans.Runtime; using Orleans.Runtime.Configuration; @@ -16,9 +15,6 @@ namespace Orleans.Hosting { public static class LegacyClusterConfigurationExtensions { - private const int SiloDefaultProviderInitStage = ServiceLifecycleStage.RuntimeStorageServices; - private const int SiloDefaultProviderStartStage = ServiceLifecycleStage.ApplicationServices; - /// /// Specifies the configuration to use for this silo. /// @@ -216,7 +212,7 @@ public static IServiceCollection AddLegacyClusterConfigurationSupport(this IServ }; }); - LegacyProviderConfigurator.ConfigureServices(configuration.Globals.ProviderConfigurations, services, SiloDefaultProviderInitStage, SiloDefaultProviderStartStage); + LegacyProviderConfigurator.ConfigureServices(configuration.Globals.ProviderConfigurations, services); services.AddOptions().Configure((options, config) => { diff --git a/src/Orleans.Runtime/Silo/Silo.cs b/src/Orleans.Runtime/Silo/Silo.cs index 0c5b15c0e9e..4d251a17a36 100644 --- a/src/Orleans.Runtime/Silo/Silo.cs +++ b/src/Orleans.Runtime/Silo/Silo.cs @@ -80,7 +80,7 @@ public enum SiloType private readonly object lockable = new object(); private readonly GrainFactory grainFactory; private readonly IGrainRuntime grainRuntime; - private readonly ILifecycleObserver siloLifecycle; + private readonly SiloLifecycle siloLifecycle; private readonly ILoggerFactory loggerFactory; /// diff --git a/src/Orleans.Runtime/Silo/SiloProviderRuntime.cs b/src/Orleans.Runtime/Silo/SiloProviderRuntime.cs index 3f8d9511d43..84611a9e196 100644 --- a/src/Orleans.Runtime/Silo/SiloProviderRuntime.cs +++ b/src/Orleans.Runtime/Silo/SiloProviderRuntime.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using Orleans.Concurrency; -using Orleans.Providers; using Orleans.Runtime.ConsistentRing; using Orleans.Runtime.Scheduler; using Orleans.Streams; @@ -10,6 +9,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Orleans.Configuration; +using Orleans.Hosting; namespace Orleans.Runtime.Providers { @@ -100,12 +100,11 @@ public async Task InitializePullingAgents( string streamProviderName, IQueueAdapterFactory adapterFactory, IQueueAdapter queueAdapter, - PersistentStreamProviderConfig config, - IProviderConfiguration providerConfig) + PersistentStreamOptions options) { - IStreamQueueBalancer queueBalancer = CreateQueueBalancer(config, streamProviderName); + IStreamQueueBalancer queueBalancer = CreateQueueBalancer(options, streamProviderName); var managerId = GrainId.NewSystemTargetGrainIdByTypeCode(Constants.PULLING_AGENTS_MANAGER_SYSTEM_TARGET_TYPE_CODE); - var manager = new PersistentStreamPullingManager(managerId, streamProviderName, this, this.PubSub(config.PubSubType), adapterFactory, queueBalancer, config, providerConfig, this.loggerFactory); + var manager = new PersistentStreamPullingManager(managerId, streamProviderName, this, this.PubSub(options.PubSubType), adapterFactory, queueBalancer, options, this.loggerFactory); this.RegisterSystemTarget(manager); // Init the manager only after it was registered locally. var pullingAgentManager = manager.AsReference(); @@ -114,21 +113,21 @@ public async Task InitializePullingAgents( return pullingAgentManager; } - private IStreamQueueBalancer CreateQueueBalancer(PersistentStreamProviderConfig config, string streamProviderName) + private IStreamQueueBalancer CreateQueueBalancer(PersistentStreamOptions options, string streamProviderName) { //default type is ConsistentRingBalancer - if (config.BalancerType == null) - config.BalancerType = StreamQueueBalancerType.ConsistentRingBalancer; + if (options.BalancerType == null) + options.BalancerType = StreamQueueBalancerType.ConsistentRingBalancer; try { - var balancer = this.ServiceProvider.GetRequiredService(config.BalancerType) as IStreamQueueBalancer; + var balancer = this.ServiceProvider.GetRequiredService(options.BalancerType) as IStreamQueueBalancer; if (balancer == null) - throw new ArgumentOutOfRangeException("balancerType", $"Configured BalancerType isn't a type which implements IStreamQueueBalancer. BalancerType: {config.BalancerType}, StreamProvider: {streamProviderName}"); + throw new ArgumentOutOfRangeException("balancerType", $"Configured BalancerType isn't a type which implements IStreamQueueBalancer. BalancerType: {options.BalancerType}, StreamProvider: {streamProviderName}"); return balancer; } catch (Exception e) { - string error = $"Unsupported balancerType for stream provider. BalancerType: {config.BalancerType}, StreamProvider: {streamProviderName}, Exception: {e}"; + string error = $"Unsupported balancerType for stream provider. BalancerType: {options.BalancerType}, StreamProvider: {streamProviderName}, Exception: {e}"; throw new ArgumentOutOfRangeException("balancerType", error); } } diff --git a/src/Orleans.Runtime/Streams/PersistentStream/PersistentStreamPullingAgent.cs b/src/Orleans.Runtime/Streams/PersistentStream/PersistentStreamPullingAgent.cs index 22a87ea9c30..c9633261b6c 100644 --- a/src/Orleans.Runtime/Streams/PersistentStream/PersistentStreamPullingAgent.cs +++ b/src/Orleans.Runtime/Streams/PersistentStream/PersistentStreamPullingAgent.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Orleans.Concurrency; +using Orleans.Configuration; using Orleans.Runtime; namespace Orleans.Streams @@ -20,7 +21,7 @@ internal class PersistentStreamPullingAgent : SystemTarget, IPersistentStreamPul private readonly IStreamPubSub pubSub; private readonly Dictionary pubSubCache; private readonly SafeRandom safeRandom; - private readonly PersistentStreamProviderConfig config; + private readonly PersistentStreamOptions options; private readonly ILogger logger; private readonly CounterStatistic numReadMessagesCounter; private readonly CounterStatistic numSentMessagesCounter; @@ -45,7 +46,7 @@ internal PersistentStreamPullingAgent( ILoggerFactory loggerFactory, IStreamPubSub streamPubSub, QueueId queueId, - PersistentStreamProviderConfig config) + PersistentStreamOptions options) : base(id, runtime.ExecutingSiloAddress, true, loggerFactory) { if (runtime == null) throw new ArgumentNullException("runtime", "PersistentStreamPullingAgent: runtime reference should not be null"); @@ -56,7 +57,7 @@ internal PersistentStreamPullingAgent( pubSub = streamPubSub; pubSubCache = new Dictionary(); safeRandom = new SafeRandom(); - this.config = config; + this.options = options; numMessages = 0; logger = runtime.ServiceProvider.GetRequiredService().CreateLogger($"{this.GetType().Namespace}.{((ISystemTargetBase)this).GrainId}.{streamProviderName}"); @@ -125,7 +126,7 @@ private void InitializeInternal(IQueueAdapter qAdapter, IQueueAdapterCache queue try { - receiverInitTask = OrleansTaskExtentions.SafeExecute(() => receiver.Initialize(config.InitQueueTimeout)) + receiverInitTask = OrleansTaskExtentions.SafeExecute(() => receiver.Initialize(this.options.InitQueueTimeout)) .LogException(logger, ErrorCode.PersistentStreamPullingAgent_03, $"QueueAdapterReceiver {QueueId.ToStringWithHashCode()} failed to Initialize."); receiverInitTask.Ignore(); } @@ -136,8 +137,8 @@ private void InitializeInternal(IQueueAdapter qAdapter, IQueueAdapterCache queue } // Setup a reader for a new receiver. // Even if the receiver failed to initialise, treat it as OK and start pumping it. It's receiver responsibility to retry initialization. - var randomTimerOffset = safeRandom.NextTimeSpan(config.GetQueueMsgsTimerPeriod); - timer = RegisterTimer(AsyncTimerCallback, QueueId, randomTimerOffset, config.GetQueueMsgsTimerPeriod); + var randomTimerOffset = safeRandom.NextTimeSpan(this.options.GetQueueMsgsTimerPeriod); + timer = RegisterTimer(AsyncTimerCallback, QueueId, randomTimerOffset, this.options.GetQueueMsgsTimerPeriod); IntValueStatistic.FindOrCreate(new StatisticName(StatisticNames.STREAMS_PERSISTENT_STREAM_PUBSUB_CACHE_SIZE, StatisticUniquePostfix), () => pubSubCache.Count); @@ -179,7 +180,7 @@ public async Task Shutdown() this.receiver = null; if (localReceiver != null) { - var task = OrleansTaskExtentions.SafeExecute(() => localReceiver.Shutdown(config.InitQueueTimeout)); + var task = OrleansTaskExtentions.SafeExecute(() => localReceiver.Shutdown(this.options.InitQueueTimeout)); task = task.LogException(logger, ErrorCode.PersistentStreamPullingAgent_07, $"QueueAdapterReceiver {QueueId} failed to Shutdown."); await task; @@ -273,7 +274,7 @@ private async Task DoHandshakeWithConsumer( i => consumerData.StreamConsumer.GetSequenceToken(consumerData.SubscriptionId), AsyncExecutorWithRetries.INFINITE_RETRIES, (exception, i) => !(exception is ClientNotAvailableException), - config.MaxEventDeliveryTime, + this.options.MaxEventDeliveryTime, DeliveryBackoffProvider); if (requestedHandshakeToken != null) @@ -399,7 +400,7 @@ private async Task ReadFromQueue(QueueId myQueueId, IQueueAdapterReceiver var now = DateTime.UtcNow; // Try to cleanup the pubsub cache at the cadence of 10 times in the configurable StreamInactivityPeriod. - if ((now - lastTimeCleanedPubSubCache) >= config.StreamInactivityPeriod.Divide(StreamInactivityCheckFrequency)) + if ((now - lastTimeCleanedPubSubCache) >= this.options.StreamInactivityPeriod.Divide(StreamInactivityCheckFrequency)) { lastTimeCleanedPubSubCache = now; CleanupPubSubCache(now); @@ -464,7 +465,7 @@ private async Task ReadFromQueue(QueueId myQueueId, IQueueAdapterReceiver private void CleanupPubSubCache(DateTime now) { if (pubSubCache.Count == 0) return; - var toRemove = pubSubCache.Where(pair => pair.Value.IsInactive(now, config.StreamInactivityPeriod)) + var toRemove = pubSubCache.Where(pair => pair.Value.IsInactive(now, this.options.StreamInactivityPeriod)) .ToList(); toRemove.ForEach(tuple => { @@ -563,7 +564,7 @@ private async Task RunConsumerCursor(StreamConsumerData consumerData, IStreamFil i => DeliverBatchToConsumer(consumerData, batch), AsyncExecutorWithRetries.INFINITE_RETRIES, (exception, i) => !(exception is ClientNotAvailableException), - config.MaxEventDeliveryTime, + this.options.MaxEventDeliveryTime, DeliveryBackoffProvider); if (newToken != null) { diff --git a/src/Orleans.Runtime/Streams/PersistentStream/PersistentStreamPullingManager.cs b/src/Orleans.Runtime/Streams/PersistentStream/PersistentStreamPullingManager.cs index 14a92e91987..3b8f298ac22 100644 --- a/src/Orleans.Runtime/Streams/PersistentStream/PersistentStreamPullingManager.cs +++ b/src/Orleans.Runtime/Streams/PersistentStream/PersistentStreamPullingManager.cs @@ -6,7 +6,8 @@ using Orleans.Concurrency; using Orleans.Providers.Streams.Common; using Orleans.Runtime; -using Orleans.Providers; +using Orleans.Configuration; +using RunState = Orleans.Configuration.PersistentStreamOptions.RunState; namespace Orleans.Streams { @@ -19,8 +20,7 @@ internal class PersistentStreamPullingManager : SystemTarget, IPersistentStreamP private readonly IStreamProviderRuntime providerRuntime; private readonly IStreamPubSub pubSub; - private readonly PersistentStreamProviderConfig config; - private readonly IProviderConfiguration providerConfig; + private readonly PersistentStreamOptions options; private readonly AsyncSerialExecutor nonReentrancyGuarantor; // for non-reentrant execution of queue change notifications. private readonly ILogger logger; private readonly ILoggerFactory loggerFactory; @@ -30,7 +30,7 @@ internal class PersistentStreamPullingManager : SystemTarget, IPersistentStreamP private readonly IQueueAdapterCache queueAdapterCache; private IStreamQueueBalancer queueBalancer; private readonly IQueueAdapterFactory adapterFactory; - private PersistentStreamProviderState managerState; + private RunState managerState; private IDisposable queuePrintTimer; private int NumberRunningAgents { get { return queuesToAgentsMap.Count; } } @@ -41,8 +41,7 @@ internal PersistentStreamPullingManager( IStreamPubSub streamPubSub, IQueueAdapterFactory adapterFactory, IStreamQueueBalancer streamQueueBalancer, - PersistentStreamProviderConfig config, - IProviderConfiguration providerConfig, + PersistentStreamOptions options, ILoggerFactory loggerFactory) : base(id, runtime.ExecutingSiloAddress, loggerFactory) { @@ -67,8 +66,7 @@ internal PersistentStreamPullingManager( streamProviderName = strProviderName; providerRuntime = runtime; pubSub = streamPubSub; - this.config = config; - this.providerConfig = providerConfig; + this.options = options; nonReentrancyGuarantor = new AsyncSerialExecutor(); latestRingNotificationSequenceNumber = 0; latestCommandNumber = 0; @@ -90,14 +88,14 @@ public async Task Initialize(Immutable qAdapter) // Remove cast once we cleanup queueAdapter = qAdapter.Value; - await this.queueBalancer.Initialize(this.streamProviderName, this.adapterFactory.GetStreamQueueMapper(), config.SiloMaturityPeriod, this.providerConfig); + await this.queueBalancer.Initialize(this.streamProviderName, this.adapterFactory.GetStreamQueueMapper(), this.options.SiloMaturityPeriod); queueBalancer.SubscribeToQueueDistributionChangeEvents(this); List myQueues = queueBalancer.GetMyQueues().ToList(); Log(ErrorCode.PersistentStreamPullingManager_03, String.Format("Initialize: I am now responsible for {0} queues: {1}.", myQueues.Count, PrintQueues(myQueues))); queuePrintTimer = this.RegisterTimer(AsyncTimerCallback, null, QUEUES_PRINT_PERIOD, QUEUES_PRINT_PERIOD); - managerState = PersistentStreamProviderState.Initialized; + managerState = RunState.Initialized; } public async Task Stop() @@ -114,7 +112,7 @@ public async Task Stop() public async Task StartAgents() { - managerState = PersistentStreamProviderState.AgentsStarted; + managerState = RunState.AgentsStarted; List myQueues = queueBalancer.GetMyQueues().ToList(); Log(ErrorCode.PersistentStreamPullingManager_Starting, "Starting agents for {0} queues: {1}", myQueues.Count, PrintQueues(myQueues)); @@ -124,7 +122,7 @@ public async Task StartAgents() public async Task StopAgents() { - managerState = PersistentStreamProviderState.AgentsStopped; + managerState = RunState.AgentsStopped; List queuesToRemove = queuesToAgentsMap.Keys.ToList(); Log(ErrorCode.PersistentStreamPullingManager_Stopping, "Stopping agents for {0} queues: {1}", queuesToRemove.Count, PrintQueues(queuesToRemove)); await RemoveQueues(queuesToRemove); @@ -152,7 +150,7 @@ public Task HandleQueueDistributionChangeNotification() Log(ErrorCode.PersistentStreamPullingManager_04, "Got QueueChangeNotification number {0} from the queue balancer. managerState = {1}", notificationSeqNumber, managerState); - if (managerState == PersistentStreamProviderState.AgentsStopped) + if (managerState == RunState.AgentsStopped) { return Task.CompletedTask; // if agents not running, no need to rebalance the queues among them. } @@ -168,7 +166,7 @@ public Task HandleQueueDistributionChangeNotification() notificationSeqNumber, latestRingNotificationSequenceNumber); return Task.CompletedTask; } - if (managerState == PersistentStreamProviderState.AgentsStopped) + if (managerState == RunState.AgentsStopped) { return Task.CompletedTask; // if agents not running, no need to rebalance the queues among them. } @@ -220,7 +218,7 @@ private async Task AddNewQueues(IEnumerable myQueues, bool failOnInit) try { var agentId = GrainId.NewSystemTargetGrainIdByTypeCode(Constants.PULLING_AGENT_SYSTEM_TARGET_TYPE_CODE); - var agent = new PersistentStreamPullingAgent(agentId, streamProviderName, providerRuntime, this.loggerFactory, pubSub, queueId, config); + var agent = new PersistentStreamPullingAgent(agentId, streamProviderName, providerRuntime, this.loggerFactory, pubSub, queueId, this.options); providerRuntime.RegisterSystemTarget(agent); queuesToAgentsMap.Add(queueId, agent); agents.Add(agent); diff --git a/src/Orleans.Runtime/Streams/QueueBalancer/ConsistentRingQueueBalancer.cs b/src/Orleans.Runtime/Streams/QueueBalancer/ConsistentRingQueueBalancer.cs index 7a0e7f6b177..61a1a7408b4 100644 --- a/src/Orleans.Runtime/Streams/QueueBalancer/ConsistentRingQueueBalancer.cs +++ b/src/Orleans.Runtime/Streams/QueueBalancer/ConsistentRingQueueBalancer.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Threading.Tasks; using Orleans.Runtime; -using Orleans.Providers; namespace Orleans.Streams { @@ -25,8 +24,7 @@ public ConsistentRingQueueBalancer(IStreamProviderRuntime streamProviderRuntime) public override Task Initialize(string strProviderName, IStreamQueueMapper queueMapper, - TimeSpan siloMaturityPeriod, - IProviderConfiguration providerConfig) + TimeSpan siloMaturityPeriod) { if (queueMapper == null) { diff --git a/src/Orleans.Runtime/Streams/QueueBalancer/DeploymentBasedQueueBalancer.cs b/src/Orleans.Runtime/Streams/QueueBalancer/DeploymentBasedQueueBalancer.cs index e7527340696..0cd8afc804d 100644 --- a/src/Orleans.Runtime/Streams/QueueBalancer/DeploymentBasedQueueBalancer.cs +++ b/src/Orleans.Runtime/Streams/QueueBalancer/DeploymentBasedQueueBalancer.cs @@ -80,8 +80,7 @@ public DeploymentBasedQueueBalancer( public override Task Initialize(string strProviderName, IStreamQueueMapper queueMapper, - TimeSpan siloMaturityPeriod, - IProviderConfiguration providerConfig) + TimeSpan siloMaturityPeriod) { if (queueMapper == null) { diff --git a/src/Orleans.Runtime/Streams/QueueBalancer/LeaseBasedQueueBalancer.cs b/src/Orleans.Runtime/Streams/QueueBalancer/LeaseBasedQueueBalancer.cs index d6f40d49ec0..b1e061e4657 100644 --- a/src/Orleans.Runtime/Streams/QueueBalancer/LeaseBasedQueueBalancer.cs +++ b/src/Orleans.Runtime/Streams/QueueBalancer/LeaseBasedQueueBalancer.cs @@ -1,20 +1,15 @@ -using Orleans.LeaseProviders; -using Orleans.Runtime; -using Orleans.Runtime.Configuration; -using Orleans.Streams; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Text; -using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Orleans.Providers; -using Orleans.Hosting; using Microsoft.Extensions.Options; +using Orleans.LeaseProviders; +using Orleans.Runtime; +using Orleans.Hosting; +using Orleans.Configuration; namespace Orleans.Streams { @@ -78,63 +73,6 @@ public ClusterConfigDeploymentLeaseBasedBalancer(IServiceProvider serviceProvide { } } - /// - /// Config for LeaseBasedQueueBalancer. User need to add this config to its stream provder's IProviderConfiguration in order to use LeaseBasedQueueBalancer in the stream provider - /// - public class LeaseBasedQueueBalancerConfig - { - /// - /// LeaseProviderType - /// - public Type LeaseProviderType { get; set; } - /// - /// LeaseProviderTypeName - /// - public const string LeaseProviderTypeName = nameof(LeaseProviderType); - /// - /// LeaseLength - /// - public TimeSpan LeaseLength { get; set; } = TimeSpan.FromSeconds(60); - /// - /// LeaseLengthName - /// - public const string LeaseLengthName = nameof(LeaseLengthName); - /// - /// Constructor - /// - public LeaseBasedQueueBalancerConfig() - { } - /// - /// Constructor - /// - /// - public LeaseBasedQueueBalancerConfig(IProviderConfiguration providerConfig) - { - string leaseLength; - if (providerConfig.Properties.TryGetValue(LeaseLengthName, out leaseLength)) - { - this.LeaseLength = ConfigUtilities.ParseTimeSpan(leaseLength, - "Invalid time value for the " + LeaseLengthName + " property in the provider config values."); - } - - this.LeaseProviderType = providerConfig.GetTypeProperty(LeaseProviderTypeName, null); - if (this.LeaseProviderType == null) - throw new ArgumentOutOfRangeException(LeaseProviderTypeName, "LeaseProviderType not set"); - } - - /// - /// Write properties to IProviderConfiguration's property bag - /// - /// - public void WriterProperties(Dictionary properties) - { - properties[LeaseLengthName] = ConfigUtilities.ToParseableTimeSpan(this.LeaseLength); - if (this.LeaseProviderType != null) - properties[LeaseProviderTypeName] = this.LeaseProviderType.AssemblyQualifiedName; - else - throw new ArgumentOutOfRangeException(LeaseProviderTypeName, "LeaseProviderType not set"); - } - } /// /// LeaseBasedQueueBalancer. This balancer supports queue balancing in cluster auto-scale scenario, unexpected server failure scenario, and try to support ideal distribution /// as much as possible. @@ -190,15 +128,18 @@ public LeaseBasedQueueBalancer(IServiceProvider serviceProvider, ISiloStatusOrac } /// - public override Task Initialize(string strProviderName, IStreamQueueMapper queueMapper, TimeSpan siloMaturityPeriod, IProviderConfiguration providerConfig) + public override Task Initialize(string strProviderName, IStreamQueueMapper queueMapper, TimeSpan siloMaturityPeriod) { if (queueMapper == null) { throw new ArgumentNullException("queueMapper"); } - var balancerConfig = new LeaseBasedQueueBalancerConfig(providerConfig); - this.leaseProvider = this.serviceProvider.GetRequiredService(balancerConfig.LeaseProviderType) as ILeaseProvider; - this.leaseLength = balancerConfig.LeaseLength; + var options = this.serviceProvider.GetServiceByName(strProviderName) + ?? this.serviceProvider.GetService(); + if (options == null) + throw new KeyNotFoundException($"No lease base queue balancer options was configured for provider {strProviderName}, nor was a default configured."); + this.leaseProvider = this.serviceProvider.GetRequiredService(options.LeaseProviderType) as ILeaseProvider; + this.leaseLength = options.LeaseLength; this.allQueues = new ReadOnlyCollection(queueMapper.GetAllQueues().ToList()); this.siloMaturityPeriod = siloMaturityPeriod; NotifyAfterStart().Ignore(); diff --git a/src/Orleans.Runtime/Streams/QueueBalancer/LeaseBasedQueueBalancerOptions.cs b/src/Orleans.Runtime/Streams/QueueBalancer/LeaseBasedQueueBalancerOptions.cs new file mode 100644 index 00000000000..e8e06e6a664 --- /dev/null +++ b/src/Orleans.Runtime/Streams/QueueBalancer/LeaseBasedQueueBalancerOptions.cs @@ -0,0 +1,28 @@ +using System; + +namespace Orleans.Configuration +{ + /// + /// Config for LeaseBasedQueueBalancer. User need to configure this option in order to use LeaseBasedQueueBalancer in the + /// stream provider. Per stream provider options can be configured as named options using the same name as the provider. + /// + public class LeaseBasedQueueBalancerOptions + { + /// + /// LeaseProviderType + /// + public Type LeaseProviderType { get; set; } + /// + /// LeaseProviderTypeName + /// + public const string LeaseProviderTypeName = nameof(LeaseProviderType); + /// + /// LeaseLength + /// + public TimeSpan LeaseLength { get; set; } = TimeSpan.FromSeconds(60); + /// + /// LeaseLengthName + /// + public const string LeaseLengthName = nameof(LeaseLengthName); + } +} diff --git a/src/Orleans.Runtime/Streams/QueueBalancer/QueueBalancerBaseClass.cs b/src/Orleans.Runtime/Streams/QueueBalancer/QueueBalancerBaseClass.cs index b14a37af52b..bdfd7bc72b5 100644 --- a/src/Orleans.Runtime/Streams/QueueBalancer/QueueBalancerBaseClass.cs +++ b/src/Orleans.Runtime/Streams/QueueBalancer/QueueBalancerBaseClass.cs @@ -1,11 +1,5 @@ -using Orleans.Providers; -using Orleans.Runtime; -using Orleans.Streams; -using System; -using System.Collections.Concurrent; +using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; namespace Orleans.Streams @@ -26,7 +20,7 @@ public QueueBalancerBase() /// public abstract IEnumerable GetMyQueues(); /// - public abstract Task Initialize(string strProviderName, IStreamQueueMapper queueMapper, TimeSpan siloMaturityPeriod, IProviderConfiguration providerConfig); + public abstract Task Initialize(string strProviderName, IStreamQueueMapper queueMapper, TimeSpan siloMaturityPeriod); /// public virtual bool SubscribeToQueueDistributionChangeEvents(IStreamQueueBalanceListener observer) { diff --git a/src/Orleans.Streaming.GCP/Hosting/ClientBuilderExtensions.cs b/src/Orleans.Streaming.GCP/Hosting/ClientBuilderExtensions.cs new file mode 100644 index 00000000000..e212266861f --- /dev/null +++ b/src/Orleans.Streaming.GCP/Hosting/ClientBuilderExtensions.cs @@ -0,0 +1,49 @@ + +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; +using Orleans.Providers.GCP.Streams.PubSub; + +namespace Orleans.Hosting +{ + public static class ClientBuilderExtensions + { + /// + /// Configure cluster client to use PubSub persistent streams. + /// + public static IClientBuilder AddPubSubStreams(this IClientBuilder builder, string name, Action configureOptions) + where TDataAdapter : IPubSubDataAdapter + { + return builder.ConfigureServices(services => services.AddClusterClientPubSubStreams(name, configureOptions)); + } + + /// + /// Configure cluster client to use PubSub persistent streams. + /// + public static IClientBuilder AddPubSubStreams(this IClientBuilder builder, string name, Action> configureOptions = null) + where TDataAdapter : IPubSubDataAdapter + { + return builder.ConfigureServices(services => services.AddClusterClientPubSubStreams(name, configureOptions)); + } + + /// + /// Configure cluster client to use PubSub persistent streams. + /// + public static IServiceCollection AddClusterClientPubSubStreams(this IServiceCollection services, string name, Action configureOptions) + where TDataAdapter : IPubSubDataAdapter + { + return services.AddClusterClientPubSubStreams(name, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure cluster client to use PubSub persistent streams. + /// + public static IServiceCollection AddClusterClientPubSubStreams(this IServiceCollection services, string name, + Action> configureOptions = null) + where TDataAdapter : IPubSubDataAdapter + { + return services.ConfigureNamedOptionForLogging(name) + .AddClusterClientPersistentStreams(name, PubSubAdapterFactory.Create, configureOptions); + } + } +} diff --git a/src/Orleans.Streaming.GCP/Hosting/SiloBuilderExtensions.cs b/src/Orleans.Streaming.GCP/Hosting/SiloBuilderExtensions.cs new file mode 100644 index 00000000000..62b617fe6d6 --- /dev/null +++ b/src/Orleans.Streaming.GCP/Hosting/SiloBuilderExtensions.cs @@ -0,0 +1,49 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; +using Orleans.Hosting; +using Orleans.Providers.GCP.Streams.PubSub; + +namespace Orleans.Hosting +{ + public static class SiloBuilderExtensions + { + /// + /// Configure silo to use PubSub persistent streams. + /// + public static ISiloHostBuilder AddPubSubStreams(this ISiloHostBuilder builder, string name, Action configureOptions) + where TDataAdapter : IPubSubDataAdapter + { + return builder.ConfigureServices(services => services.AddSiloPubSubStreams(name, configureOptions)); + } + + /// + /// Configure silo to use PubSub persistent streams. + /// + public static ISiloHostBuilder AddPubSubStreams(this ISiloHostBuilder builder, string name, Action> configureOptions = null) + where TDataAdapter : IPubSubDataAdapter + { + return builder.ConfigureServices(services => services.AddSiloPubSubStreams(name, configureOptions)); + } + + /// + /// Configure silo to use PubSub persistent streams. + /// + public static IServiceCollection AddSiloPubSubStreams(this IServiceCollection services, string name, Action configureOptions) + where TDataAdapter : IPubSubDataAdapter + { + return services.AddSiloPubSubStreams(name, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure silo to use PubSub persistent streams. + /// + public static IServiceCollection AddSiloPubSubStreams(this IServiceCollection services, string name, + Action> configureOptions = null) + where TDataAdapter : IPubSubDataAdapter + { + return services.ConfigureNamedOptionForLogging(name) + .AddSiloPersistentStreams(name, PubSubAdapterFactory< TDataAdapter>.Create, configureOptions); + } + } +} diff --git a/src/Orleans.Streaming.GCP/Orleans.Streaming.GCP.csproj b/src/Orleans.Streaming.GCP/Orleans.Streaming.GCP.csproj index ea39a504b20..2ce6ddf66b2 100644 --- a/src/Orleans.Streaming.GCP/Orleans.Streaming.GCP.csproj +++ b/src/Orleans.Streaming.GCP/Orleans.Streaming.GCP.csproj @@ -17,6 +17,7 @@ + diff --git a/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubAdapterConstants.cs b/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubAdapterConstants.cs deleted file mode 100644 index ee55af1fc67..00000000000 --- a/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubAdapterConstants.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; - -namespace Orleans.Providers.GCP.Streams.PubSub -{ - public static class PubSubAdapterConstants - { - internal static readonly TimeSpan MAX_DEADLINE = TimeSpan.FromSeconds(600); - internal const string NUMBER_SUBSCRIPTIONS = "NumSubscriptions"; - internal const int NUMBER_SUBSCRIPTIONS_DEFAULT = 8; - internal const int CACHE_SIZE_DEFAULT = 4096; - internal const string PROJECT_ID = "ProjectId"; - internal const string TOPIC_ID = "TopicId"; - internal const string DEADLINE = "Deadline"; - internal const string DEPLOYMENT_ID = "DeploymentId"; - internal const string CUSTOM_ENDPOINT = "CustomEndpoint"; - } -} diff --git a/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubAdapterFactory.cs b/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubAdapterFactory.cs index d0dce2550b5..acb5cb68a3f 100644 --- a/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubAdapterFactory.cs +++ b/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubAdapterFactory.cs @@ -1,28 +1,25 @@ -using Microsoft.Extensions.DependencyInjection; +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Logging; using Orleans.Providers.Streams.Common; -using Orleans.Runtime; using Orleans.Serialization; using Orleans.Streams; -using System; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; +using Orleans.Configuration; + namespace Orleans.Providers.GCP.Streams.PubSub { public class PubSubAdapterFactory : IQueueAdapterFactory where TDataAdapter : IPubSubDataAdapter { - private string _projectId; - private string _topicId; - private string _deploymentId; - private string _providerName; - private string _customEndpoint; - private int _cacheSize; - private int _numSubscriptions; - private TimeSpan? _deadline; + private readonly string _providerName; + private readonly PubSubStreamOptions options; + private readonly SiloOptions siloOptions; + private readonly ILoggerFactory loggerFactory; + private readonly Func _adaptorFactory; private HashRingBasedStreamQueueMapper _streamQueueMapper; private IQueueAdapterCache _adapterCache; - private Func _adaptorFactory; - private ILoggerFactory loggerFactory; /// /// Gets the serialization manager. @@ -34,67 +31,32 @@ public class PubSubAdapterFactory : IQueueAdapterFactory /// protected Func> StreamFailureHandlerFactory { private get; set; } - public virtual void Init(IProviderConfiguration config, string providerName, IServiceProvider serviceProvider) + public PubSubAdapterFactory(string name, PubSubStreamOptions options, IServiceProvider serviceProvider, IOptions siloOptions, SerializationManager serializationManager, ILoggerFactory loggerFactory) { - if (config == null) throw new ArgumentNullException(nameof(config)); - if (!config.Properties.TryGetValue(PubSubAdapterConstants.PROJECT_ID, out _projectId)) - throw new ArgumentException($"{PubSubAdapterConstants.PROJECT_ID} property not set"); - if (!config.Properties.TryGetValue(PubSubAdapterConstants.TOPIC_ID, out _topicId)) - throw new ArgumentException($"{PubSubAdapterConstants.TOPIC_ID} property not set"); - if (!config.Properties.TryGetValue(PubSubAdapterConstants.DEPLOYMENT_ID, out _deploymentId)) - throw new ArgumentException($"{PubSubAdapterConstants.DEPLOYMENT_ID} property not set"); - - loggerFactory = serviceProvider.GetRequiredService(); - - config.Properties.TryGetValue(PubSubAdapterConstants.CUSTOM_ENDPOINT, out _customEndpoint); - - string deadlineStr; - if (config.Properties.TryGetValue(PubSubAdapterConstants.DEADLINE, out deadlineStr)) - { - int seconds; - if (!int.TryParse(deadlineStr, out seconds)) - { - throw new ArgumentException( - $"Failed to parse {PubSubAdapterConstants.DEADLINE} value '{deadlineStr}' as a TimeSpan"); - } - - _deadline = TimeSpan.FromSeconds(seconds); - - if (_deadline == TimeSpan.MinValue || _deadline > PubSubAdapterConstants.MAX_DEADLINE) - _deadline = PubSubAdapterConstants.MAX_DEADLINE; - } - else - { - _deadline = null; - } - - _cacheSize = SimpleQueueAdapterCache.ParseSize(config, PubSubAdapterConstants.CACHE_SIZE_DEFAULT); - - string numSubscriptionsString; - _numSubscriptions = PubSubAdapterConstants.NUMBER_SUBSCRIPTIONS_DEFAULT; - if (config.Properties.TryGetValue(PubSubAdapterConstants.NUMBER_SUBSCRIPTIONS, out numSubscriptionsString)) - { - if (!int.TryParse(numSubscriptionsString, out _numSubscriptions)) - throw new ArgumentException($"{PubSubAdapterConstants.NUMBER_SUBSCRIPTIONS} invalid. Must be int"); - } + this._providerName = name; + this.options = options; + this.siloOptions = siloOptions.Value; + this.SerializationManager = serializationManager; + this.loggerFactory = loggerFactory; + this._adaptorFactory = () => ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider); + } - _providerName = providerName; - _streamQueueMapper = new HashRingBasedStreamQueueMapper(_numSubscriptions, providerName); - _adapterCache = new SimpleQueueAdapterCache(_cacheSize, providerName, loggerFactory); + public virtual void Init() + { + this._streamQueueMapper = new HashRingBasedStreamQueueMapper(this.options.NumSubscriptions, this._providerName); + this._adapterCache = new SimpleQueueAdapterCache(this.options.CacheSize, this._providerName, loggerFactory); if (StreamFailureHandlerFactory == null) { StreamFailureHandlerFactory = qid => Task.FromResult(new NoOpStreamDeliveryFailureHandler()); } - SerializationManager = serviceProvider.GetRequiredService(); - _adaptorFactory = () => ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider); } public virtual Task CreateAdapter() { - var adapter = new PubSubAdapter(_adaptorFactory(), SerializationManager, this.loggerFactory, _streamQueueMapper, - _projectId, _topicId, _deploymentId, _providerName, _deadline, _customEndpoint); + var adapter = new PubSubAdapter(_adaptorFactory(), SerializationManager, this.loggerFactory, _streamQueueMapper, + this.options.ProjectId, this.options.TopicId, this.options.ClusterId ?? this.siloOptions.ClusterId, this._providerName, this.options.Deadline, this.options.CustomEndpoint); return Task.FromResult(adapter); } @@ -103,5 +65,13 @@ public virtual Task CreateAdapter() public IQueueAdapterCache GetQueueAdapterCache() => _adapterCache; public IStreamQueueMapper GetStreamQueueMapper() => _streamQueueMapper; + + public static PubSubAdapterFactory Create(IServiceProvider services, string name) + { + IOptionsSnapshot streamOptionsSnapshot = services.GetRequiredService>(); + var factory = ActivatorUtilities.CreateInstance>(services, name, streamOptionsSnapshot.Get(name)); + factory.Init(); + return factory; + } } } diff --git a/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubStreamOptions.cs b/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubStreamOptions.cs new file mode 100644 index 00000000000..8b603e215e0 --- /dev/null +++ b/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubStreamOptions.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.Options; + +namespace Orleans.Configuration +{ + public class PubSubStreamOptions : PersistentStreamOptions + { + public string ProjectId { get; set; } + + public string TopicId { get; set; } + + public string ClusterId { get; set; } + + public string CustomEndpoint { get; set; } + + public int CacheSize { get; set; } = CACHE_SIZE_DEFAULT; + public const int CACHE_SIZE_DEFAULT = 4096; + + public int NumSubscriptions { get; set; } = NUMBER_SUBSCRIPTIONS_DEFAULT; + public const int NUMBER_SUBSCRIPTIONS_DEFAULT = 8; + + private TimeSpan? deadline; + public TimeSpan? Deadline + { + get { return this.deadline; } + set { this.deadline = (value.HasValue) ? TimeSpan.FromTicks(Math.Min(value.Value.Ticks, MAX_DEADLINE.Ticks)) : value; } + } + public static readonly TimeSpan MAX_DEADLINE = TimeSpan.FromSeconds(600); + } +} diff --git a/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubStreamProvider.cs b/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubStreamProvider.cs deleted file mode 100644 index 4c06936c258..00000000000 --- a/src/Orleans.Streaming.GCP/Providers/Streams/PubSub/PubSubStreamProvider.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Orleans.Providers.Streams.Common; - -namespace Orleans.Providers.GCP.Streams.PubSub -{ - /// - /// Persistent stream provider that uses Google PubSub as backend - /// - public class PubSubStreamProvider : PersistentStreamProvider> - { - } -} diff --git a/src/OrleansProviders/Hosting/ClientBuilderExtensions.cs b/src/OrleansProviders/Hosting/ClientBuilderExtensions.cs new file mode 100644 index 00000000000..3dd8e03ae77 --- /dev/null +++ b/src/OrleansProviders/Hosting/ClientBuilderExtensions.cs @@ -0,0 +1,49 @@ + +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; +using Orleans.Providers; + +namespace Orleans.Hosting +{ + public static class ClientBuilderExtensions + { + /// + /// Configure cluster client to use memory streams. + /// + public static IClientBuilder AddMemoryStreams(this IClientBuilder builder, string name, Action configureOptions) + where TSerializer : class, IMemoryMessageBodySerializer + { + return builder.ConfigureServices(services => services.AddClusterClientMemoryStreams(name, configureOptions)); + } + + /// + /// Configure cluster client to use memory streams. + /// + public static IClientBuilder AddMemoryStreams(this IClientBuilder builder, string name, Action> configureOptions = null) + where TSerializer : class, IMemoryMessageBodySerializer + { + return builder.ConfigureServices(services => services.AddClusterClientMemoryStreams(name, configureOptions)); + } + + /// + /// Configure cluster client to use memory streams. + /// + public static IServiceCollection AddClusterClientMemoryStreams(this IServiceCollection services, string name, Action configureOptions) + where TSerializer : class, IMemoryMessageBodySerializer + { + return services.AddClusterClientMemoryStreams(name, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure cluster client to use memory streams. + /// + public static IServiceCollection AddClusterClientMemoryStreams(this IServiceCollection services, string name, + Action> configureOptions = null) + where TSerializer : class, IMemoryMessageBodySerializer + { + return services.ConfigureNamedOptionForLogging(name) + .AddClusterClientPersistentStreams(name, MemoryAdapterFactory.Create, configureOptions); + } + } +} diff --git a/src/OrleansProviders/Hosting/SiloBuilderExtensions.cs b/src/OrleansProviders/Hosting/SiloBuilderExtensions.cs new file mode 100644 index 00000000000..c8ec9d7456e --- /dev/null +++ b/src/OrleansProviders/Hosting/SiloBuilderExtensions.cs @@ -0,0 +1,49 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; +using Orleans.Hosting; +using Orleans.Providers; + +namespace Orleans.Hosting +{ + public static class SiloBuilderExtensions + { + /// + /// Configure silo to use memory streams. + /// + public static ISiloHostBuilder AddMemoryStreams(this ISiloHostBuilder builder, string name, Action configureOptions) + where TSerializer : class, IMemoryMessageBodySerializer + { + return builder.ConfigureServices(services => services.AddSiloMemoryStreams(name, configureOptions)); + } + + /// + /// Configure silo to use memory streams. + /// + public static ISiloHostBuilder AddMemoryStreams(this ISiloHostBuilder builder, string name, Action> configureOptions = null) + where TSerializer : class, IMemoryMessageBodySerializer + { + return builder.ConfigureServices(services => services.AddSiloMemoryStreams(name, configureOptions)); + } + + /// + /// Configure silo to use memory streams. + /// + public static IServiceCollection AddSiloMemoryStreams(this IServiceCollection services, string name, Action configureOptions) + where TSerializer : class, IMemoryMessageBodySerializer + { + return services.AddSiloMemoryStreams(name, ob => ob.Configure(configureOptions)); + } + + /// + /// Configure silo to use memory streams. + /// + public static IServiceCollection AddSiloMemoryStreams(this IServiceCollection services, string name, + Action> configureOptions = null) + where TSerializer : class, IMemoryMessageBodySerializer + { + return services.ConfigureNamedOptionForLogging(name) + .AddSiloPersistentStreams(name, MemoryAdapterFactory.Create, configureOptions); + } + } +} diff --git a/src/OrleansProviders/OrleansProviders.csproj b/src/OrleansProviders/OrleansProviders.csproj index 3007acdd617..6b639d85da6 100644 --- a/src/OrleansProviders/OrleansProviders.csproj +++ b/src/OrleansProviders/OrleansProviders.csproj @@ -14,5 +14,6 @@ + \ No newline at end of file diff --git a/src/OrleansProviders/Streams/Common/RecoverableStreamOptions.cs b/src/OrleansProviders/Streams/Common/RecoverableStreamOptions.cs new file mode 100644 index 00000000000..731a2641c67 --- /dev/null +++ b/src/OrleansProviders/Streams/Common/RecoverableStreamOptions.cs @@ -0,0 +1,39 @@ +using System; + +namespace Orleans.Configuration +{ + /// + /// Common stream provider settings shared by EventHubStreamProvider, MemoryStreamProvider and GeneratorStreamProvider + /// + public class RecoverableStreamOptions : PersistentStreamOptions + { + /// + /// Minimum time message will stay in cache before it is available for time based purge. + /// + public TimeSpan DataMinTimeInCache { get; set; } = DefaultDataMinTimeInCache; + /// + /// Drfault DataMinTimeInCache + /// + public static readonly TimeSpan DefaultDataMinTimeInCache = TimeSpan.FromMinutes(5); + + /// + /// Difference in time between the newest and oldest messages in the cache. Any messages older than this will be purged from the cache. + /// + public TimeSpan DataMaxAgeInCache { get; set; } = DefaultDataMaxAgeInCache; + /// + /// Default DataMaxAgeInCache + /// + public static readonly TimeSpan DefaultDataMaxAgeInCache = TimeSpan.FromMinutes(30); + + + /// + /// Statistic monitor write interval + /// Statistics generation is triggered by activity. Interval will be ignored when streams are inactive. + /// + public TimeSpan StatisticMonitorWriteInterval { get; set; } = DefaultStatisticMonitorWriteInterval; + /// + /// Default statistic monitor write interval + /// + public static TimeSpan DefaultStatisticMonitorWriteInterval = TimeSpan.FromMinutes(5); + } +} diff --git a/src/OrleansProviders/Streams/Common/RecoverableStreamProviderSettings.cs b/src/OrleansProviders/Streams/Common/RecoverableStreamProviderSettings.cs deleted file mode 100644 index 43ec560e594..00000000000 --- a/src/OrleansProviders/Streams/Common/RecoverableStreamProviderSettings.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Orleans.Providers.Streams.Common -{ - /// - /// Common stream provider settings shared by EventHubStreamProvider, MemoryStreamProvider and GeneratorStreamProvider - /// - public class RecoverableStreamProviderSettings - { - /// - /// DataMinTimeInCache setting name. - /// - public const string DataMinTimeInCacheName = "DataMinTimeInCache"; - /// - /// Drfault DataMinTimeInCache - /// - public static readonly TimeSpan DefaultDataMinTimeInCache = TimeSpan.FromMinutes(5); - /// - /// Minimum time message will stay in cache before it is available for time based purge. - /// - public TimeSpan DataMinTimeInCache { get; set; } = DefaultDataMinTimeInCache; - - /// - /// DataMaxAgeInCache setting name. - /// - public const string DataMaxAgeInCacheName = "DataMaxAgeInCache"; - /// - /// Default DataMaxAgeInCache - /// - public static readonly TimeSpan DefaultDataMaxAgeInCache = TimeSpan.FromMinutes(30); - /// - /// Difference in time between the newest and oldest messages in the cache. Any messages older than this will be purged from the cache. - /// - public TimeSpan DataMaxAgeInCache { get; set; } = DefaultDataMaxAgeInCache; - - /// - /// Name of StatisticMonitorWriteInterval - /// - public const string StatisticMonitorWriteIntervalName = nameof(StatisticMonitorWriteInterval); - - /// - /// Default statistic monitor write interval - /// - public static TimeSpan DefaultStatisticMonitorWriteInterval = TimeSpan.FromMinutes(5); - - /// - /// Statistic monitor write interval - /// Statistics generation is triggered by activity. Interval will be ignored when streams are inactive. - /// - public TimeSpan StatisticMonitorWriteInterval { get; set; } = DefaultStatisticMonitorWriteInterval; - - public virtual void WriteProperties(Dictionary properties) - { - properties.Add(StatisticMonitorWriteIntervalName, StatisticMonitorWriteInterval.ToString()); - properties.Add(DataMinTimeInCacheName, DataMinTimeInCache.ToString()); - properties.Add(DataMaxAgeInCacheName, DataMaxAgeInCache.ToString()); - } - - /// - /// Read settings from provider configuration. - /// - /// - public virtual void PopulateFromProviderConfig(IProviderConfiguration providerConfiguration) - { - DataMinTimeInCache = providerConfiguration.GetTimeSpanProperty(DataMinTimeInCacheName, DefaultDataMinTimeInCache); - DataMaxAgeInCache = providerConfiguration.GetTimeSpanProperty(DataMaxAgeInCacheName, DefaultDataMaxAgeInCache); - StatisticMonitorWriteInterval = providerConfiguration.GetTimeSpanProperty(StatisticMonitorWriteIntervalName, - DefaultStatisticMonitorWriteInterval); - } - } -} diff --git a/src/OrleansProviders/Streams/Generator/GeneratedStreamOptions.cs b/src/OrleansProviders/Streams/Generator/GeneratedStreamOptions.cs new file mode 100644 index 00000000000..b587d8be8d2 --- /dev/null +++ b/src/OrleansProviders/Streams/Generator/GeneratedStreamOptions.cs @@ -0,0 +1,16 @@ + +namespace Orleans.Configuration +{ + /// + /// This configuration class is used to configure the GeneratorStreamProvider. + /// It tells the stream provider how many queues to create, and which generator to use to generate event streams. + /// + public class GeneratedStreamOptions : RecoverableStreamOptions + { + /// + /// Total number of queues + /// + public int TotalQueueCount { get; set; } = DEFAULT_TOTAL_QUEUE_COUNT; + public const int DEFAULT_TOTAL_QUEUE_COUNT = 4; + } +} diff --git a/src/OrleansProviders/Streams/Generator/GeneratorAdapterConfig.cs b/src/OrleansProviders/Streams/Generator/GeneratorAdapterConfig.cs deleted file mode 100644 index 53a789809dd..00000000000 --- a/src/OrleansProviders/Streams/Generator/GeneratorAdapterConfig.cs +++ /dev/null @@ -1,77 +0,0 @@ - -using Orleans.Providers.Streams.Common; -using System; -using System.Collections.Generic; -using System.Globalization; - -namespace Orleans.Providers.Streams.Generator -{ - /// - /// This configuration class is used to configure the GeneratorStreamProvider. - /// It tells the stream provider how many queues to create, and which generator to use to generate event streams. - /// - public class GeneratorAdapterConfig : RecoverableStreamProviderSettings - { - /// - /// Configuration property name for generator configuration type - /// - public const string GeneratorConfigTypeName = "GeneratorConfigType"; - - /// - /// Generator configuration type - /// - public Type GeneratorConfigType { get; set; } - - /// - /// Stream provider name - /// - public string StreamProviderName { get; } - - private const string TotalQueueCountName = "TotalQueueCount"; - private const int TotalQueueCountDefault = 4; - - /// - /// Total number of queues - /// - public int TotalQueueCount { get; set; } - - /// - /// Constructor - /// - /// - public GeneratorAdapterConfig(string streamProviderName) - { - StreamProviderName = streamProviderName; - TotalQueueCount = TotalQueueCountDefault; - } - - /// - /// Utility function to convert config to property bag for use in stream provider configuration - /// - /// - public override void WriteProperties(Dictionary properties) - { - base.WriteProperties(properties); - if (GeneratorConfigType != null) - { - properties.Add(GeneratorConfigTypeName, GeneratorConfigType.AssemblyQualifiedName); - } - properties.Add(TotalQueueCountName, TotalQueueCount.ToString(CultureInfo.InvariantCulture)); - } - - /// - /// Utility function to populate config from provider config - /// - /// - public override void PopulateFromProviderConfig(IProviderConfiguration providerConfiguration) - { - base.PopulateFromProviderConfig(providerConfiguration); - GeneratorConfigType = providerConfiguration.GetTypeProperty(GeneratorConfigTypeName, null); - if (string.IsNullOrWhiteSpace(StreamProviderName)) - { - throw new ArgumentOutOfRangeException("providerConfiguration", "StreamProviderName not set."); - } - TotalQueueCount = providerConfiguration.GetIntProperty(TotalQueueCountName, TotalQueueCountDefault); - } - } -} diff --git a/src/OrleansProviders/Streams/Generator/GeneratorAdapterFactory.cs b/src/OrleansProviders/Streams/Generator/GeneratorAdapterFactory.cs index a8feedc3c80..83ceeb2e1ca 100644 --- a/src/OrleansProviders/Streams/Generator/GeneratorAdapterFactory.cs +++ b/src/OrleansProviders/Streams/Generator/GeneratorAdapterFactory.cs @@ -3,13 +3,15 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading.Tasks; +using System.Diagnostics; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Orleans.Providers.Streams.Common; using Orleans.Runtime; using Orleans.Serialization; using Orleans.Streams; -using System.Diagnostics; -using Microsoft.Extensions.Logging; +using Orleans.Configuration; namespace Orleans.Providers.Streams.Generator { @@ -34,19 +36,18 @@ public class GeneratorAdapterFactory : IQueueAdapterFactory, IQueueAdapter, IQue /// /// Configuration property name for generator configuration type /// - public const string GeneratorConfigTypeName = "StreamGeneratorConfigType"; - private IServiceProvider serviceProvider; - private GeneratorAdapterConfig adapterConfig; + private readonly GeneratedStreamOptions options; + private readonly IServiceProvider serviceProvider; + private readonly SerializationManager serializationManager; + private readonly ITelemetryProducer telemetryProducer; + private readonly ILoggerFactory loggerFactory; + private readonly ILogger logger; private IStreamGeneratorConfig generatorConfig; private IStreamQueueMapper streamQueueMapper; private IStreamFailureHandler streamFailureHandler; private ConcurrentDictionary receivers; private IObjectPool bufferPool; - private SerializationManager serializationManager; - private ITelemetryProducer telemetryProducer; private BlockPoolMonitorDimensions blockPoolMonitorDimensions; - private ILoggerFactory loggerFactory; - private string providerName; /// /// Determines whether this is a rewindable stream adapter - supports subscribing from previous point in time. /// @@ -59,6 +60,11 @@ public class GeneratorAdapterFactory : IQueueAdapterFactory, IQueueAdapter, IQue /// The direction in which this adapter provides data. public StreamProviderDirection Direction => StreamProviderDirection.ReadOnly; + /// + /// Name of the adapter. From IQueueAdapter. + /// + public string Name { get; } + /// /// Create a cache monitor to report cache related metrics /// Return a ICacheMonitor @@ -77,36 +83,33 @@ public class GeneratorAdapterFactory : IQueueAdapterFactory, IQueueAdapter, IQue /// protected Func ReceiverMonitorFactory; + public GeneratorAdapterFactory(string providerName, GeneratedStreamOptions options, IServiceProvider serviceProvider, SerializationManager serializationManager, ITelemetryProducer telemetryProducer, ILoggerFactory loggerFactory) + { + this.Name = providerName; + this.options = options ?? throw new ArgumentNullException(nameof(options)); + this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + this.serializationManager = serializationManager ?? throw new ArgumentNullException(nameof(serializationManager)); + this.telemetryProducer = telemetryProducer ?? throw new ArgumentNullException(nameof(telemetryProducer)); + this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); + this.logger = loggerFactory.CreateLogger(); + } + /// /// Initialize the factory /// - /// - /// - /// - public void Init(IProviderConfiguration providerConfig, string providerName, IServiceProvider svcProvider) + public void Init() { - this.loggerFactory = svcProvider.GetRequiredService(); - serviceProvider = svcProvider; - this.providerName = providerName; - receivers = new ConcurrentDictionary(); - adapterConfig = new GeneratorAdapterConfig(providerName); - adapterConfig.PopulateFromProviderConfig(providerConfig); - this.serializationManager = svcProvider.GetRequiredService(); - this.telemetryProducer = svcProvider.GetService(); + this.receivers = new ConcurrentDictionary(); if (CacheMonitorFactory == null) this.CacheMonitorFactory = (dimensions, telemetryProducer) => new DefaultCacheMonitor(dimensions, telemetryProducer); if (this.BlockPoolMonitorFactory == null) this.BlockPoolMonitorFactory = (dimensions, telemetryProducer) => new DefaultBlockPoolMonitor(dimensions, telemetryProducer); if (this.ReceiverMonitorFactory == null) this.ReceiverMonitorFactory = (dimensions, telemetryProducer) => new DefaultQueueAdapterReceiverMonitor(dimensions, telemetryProducer); - if (adapterConfig.GeneratorConfigType != null) + generatorConfig = this.serviceProvider.GetServiceByName(this.Name); + if(generatorConfig == null) { - generatorConfig = (IStreamGeneratorConfig)(serviceProvider?.GetService(adapterConfig.GeneratorConfigType) ?? Activator.CreateInstance(adapterConfig.GeneratorConfigType)); - if (generatorConfig == null) - { - throw new ArgumentOutOfRangeException(nameof(providerConfig), "GeneratorConfigType not valid."); - } - generatorConfig.PopulateFromProviderConfig(providerConfig); + this.logger.LogInformation("No generator configuration found for stream provider {0}. Inactive until provided with configuration by command.", this.Name); } } @@ -118,7 +121,7 @@ private void CreateBufferPoolIfNotCreatedYet() this.blockPoolMonitorDimensions = new BlockPoolMonitorDimensions($"BlockPool-{Guid.NewGuid()}"); var oneMb = 1 << 20; var objectPoolMonitor = new ObjectPoolMonitorBridge(this.BlockPoolMonitorFactory(blockPoolMonitorDimensions, this.telemetryProducer), oneMb); - this.bufferPool = new ObjectPool(() => new FixedSizeBuffer(oneMb), objectPoolMonitor, this.adapterConfig.StatisticMonitorWriteInterval); + this.bufferPool = new ObjectPool(() => new FixedSizeBuffer(oneMb), objectPoolMonitor, this.options.StatisticMonitorWriteInterval); } } @@ -146,7 +149,7 @@ public IQueueAdapterCache GetQueueAdapterCache() /// public IStreamQueueMapper GetStreamQueueMapper() { - return streamQueueMapper ?? (streamQueueMapper = new HashRingBasedStreamQueueMapper(adapterConfig.TotalQueueCount, adapterConfig.StreamProviderName)); + return streamQueueMapper ?? (streamQueueMapper = new HashRingBasedStreamQueueMapper(this.options.TotalQueueCount, this.Name)); } /// @@ -159,11 +162,6 @@ public Task GetDeliveryFailureHandler(QueueId queueId) return Task.FromResult(streamFailureHandler ?? (streamFailureHandler = new NoOpStreamDeliveryFailureHandler())); } - /// - /// Name of the adapter. Primarily for logging purposes - /// - public string Name => adapterConfig.StreamProviderName; - /// /// Stores a batch of messages /// @@ -297,8 +295,16 @@ public IQueueCache CreateQueueCache(QueueId queueId) CreateBufferPoolIfNotCreatedYet(); var dimensions = new CacheMonitorDimensions(queueId.ToString(), this.blockPoolMonitorDimensions.BlockPoolId); var cacheMonitor = this.CacheMonitorFactory(dimensions, this.telemetryProducer); - return new GeneratorPooledCache(bufferPool, this.loggerFactory.CreateLogger($"{typeof(GeneratorPooledCache).FullName}.{this.providerName}.{queueId}"), serializationManager, - cacheMonitor, this.adapterConfig.StatisticMonitorWriteInterval); + return new GeneratorPooledCache(bufferPool, this.loggerFactory.CreateLogger($"{typeof(GeneratorPooledCache).FullName}.{this.Name}.{queueId}"), serializationManager, + cacheMonitor, this.options.StatisticMonitorWriteInterval); + } + + public static GeneratorAdapterFactory Create(IServiceProvider services, string name) + { + IOptionsSnapshot optionsSnapshot = services.GetRequiredService>(); + var factory = ActivatorUtilities.CreateInstance(services, name, optionsSnapshot.Get(name)); + factory.Init(); + return factory; } } } diff --git a/src/OrleansProviders/Streams/Generator/GeneratorStreamProvider.cs b/src/OrleansProviders/Streams/Generator/GeneratorStreamProvider.cs deleted file mode 100644 index 1c320775556..00000000000 --- a/src/OrleansProviders/Streams/Generator/GeneratorStreamProvider.cs +++ /dev/null @@ -1,13 +0,0 @@ - -using Orleans.Providers.Streams.Common; - -namespace Orleans.Providers.Streams.Generator -{ - /// - /// This is a persistent stream provider that generates it's own events rather than reading them from storage. - /// This is primarily for test purposes. - /// - public class GeneratorStreamProvider : PersistentStreamProvider - { - } -} diff --git a/src/OrleansProviders/Streams/Generator/Generators/SimpleGenerator.cs b/src/OrleansProviders/Streams/Generator/Generators/SimpleGenerator.cs index bb8a32108c9..cd99e40d68b 100644 --- a/src/OrleansProviders/Streams/Generator/Generators/SimpleGenerator.cs +++ b/src/OrleansProviders/Streams/Generator/Generators/SimpleGenerator.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; +using Orleans.Hosting; using Orleans.Providers.Streams.Common; using Orleans.Streams; @@ -12,18 +13,18 @@ namespace Orleans.Providers.Streams.Generator /// internal class SimpleGenerator : IStreamGenerator { - private SimpleGeneratorConfig config; + private SimpleGeneratorOptions options; private Guid streamGuid; private int sequenceId; public void Configure(IServiceProvider serviceProvider, IStreamGeneratorConfig generatorConfig) { - var cfg = generatorConfig as SimpleGeneratorConfig; + var cfg = generatorConfig as SimpleGeneratorOptions; if (cfg == null) { throw new ArgumentOutOfRangeException(nameof(generatorConfig)); } - config = cfg; + options = cfg; sequenceId = 0; streamGuid = Guid.NewGuid(); } @@ -37,7 +38,7 @@ public void Configure(IServiceProvider serviceProvider, IStreamGeneratorConfig g public bool TryReadEvents(DateTime utcNow, out List events) { events = new List(); - if (sequenceId >= config.EventsInStream) + if (sequenceId >= this.options.EventsInStream) { return false; } @@ -53,11 +54,11 @@ private GeneratedBatchContainer GenerateBatch() var evt = new GeneratedEvent { // If this is the last event generated, mark it as such, so test grains know to report results. - EventType = (sequenceId != config.EventsInStream) + EventType = (sequenceId != this.options.EventsInStream) ? GeneratedEvent.GeneratedEventType.Fill : GeneratedEvent.GeneratedEventType.Report }; - return new GeneratedBatchContainer(streamGuid, config.StreamNamespace, evt, new EventSequenceTokenV2(sequenceId)); + return new GeneratedBatchContainer(streamGuid, this.options.StreamNamespace, evt, new EventSequenceTokenV2(sequenceId)); } } } diff --git a/src/OrleansProviders/Streams/Generator/Generators/SimpleGeneratorConfig.cs b/src/OrleansProviders/Streams/Generator/Generators/SimpleGeneratorConfig.cs index 736035f5d98..e4687152d9e 100644 --- a/src/OrleansProviders/Streams/Generator/Generators/SimpleGeneratorConfig.cs +++ b/src/OrleansProviders/Streams/Generator/Generators/SimpleGeneratorConfig.cs @@ -1,18 +1,18 @@ using System; using System.Collections.Generic; -using System.Globalization; +using Microsoft.Extensions.Options; +using Orleans.Providers.Streams.Generator; -namespace Orleans.Providers.Streams.Generator +namespace Orleans.Hosting { /// /// Simple generator configuration class. /// This class is used to configure a generator stream provider to generate streams using the SimpleGenerator /// [Serializable] - public class SimpleGeneratorConfig : IStreamGeneratorConfig + public class SimpleGeneratorOptions : IStreamGeneratorConfig { - private const string StreamNamespaceName = "StreamNamespace"; /// /// Stream namespace /// @@ -26,37 +26,45 @@ public class SimpleGeneratorConfig : IStreamGeneratorConfig /// /// Nuber of events to generate on this stream /// - public int EventsInStream { get; set; } - private const string EventsInStreamName = "EventsInStream"; - private const int EventsInStreamDefault = 100; + public int EventsInStream { get; set; } = DEFAULT_EVENTS_IN_STREAM; + public const int DEFAULT_EVENTS_IN_STREAM = 100; + } - /// - /// Configuration for simple stream generator - /// - public SimpleGeneratorConfig() + public class SimpleGeneratorOptionsFormatterResolver : IOptionFormatterResolver + { + private IOptionsSnapshot optionsSnapshot; + + public SimpleGeneratorOptionsFormatterResolver(IOptionsSnapshot optionsSnapshot) { - EventsInStream = EventsInStreamDefault; + this.optionsSnapshot = optionsSnapshot; } - /// - /// Utility function to convert config to property bag for use in stream provider configuration - /// - /// - public void WriteProperties(Dictionary properties) + public IOptionFormatter Resolve(string name) { - properties.Add(GeneratorAdapterFactory.GeneratorConfigTypeName, GetType().AssemblyQualifiedName); - properties.Add(EventsInStreamName, EventsInStream.ToString(CultureInfo.InvariantCulture)); - properties.Add(StreamNamespaceName, StreamNamespace); + return new Formatter(name, optionsSnapshot.Get(name)); } - /// - /// Utility function to populate config from provider config - /// - /// - public void PopulateFromProviderConfig(IProviderConfiguration providerConfiguration) + private class Formatter : IOptionFormatter { - EventsInStream = providerConfiguration.GetIntProperty(EventsInStreamName, EventsInStreamDefault); - StreamNamespace = providerConfiguration.GetProperty(StreamNamespaceName, null); + private SimpleGeneratorOptions options; + + public string Name { get; } + + public Formatter(string name, SimpleGeneratorOptions options) + { + this.options = options; + this.Name = OptionFormattingUtilities.Name(name); + } + + public IEnumerable Format() + { + return new List + { + OptionFormattingUtilities.Format(nameof(this.options.StreamNamespace), this.options.StreamNamespace), + OptionFormattingUtilities.Format(nameof(this.options.StreamGeneratorType), this.options.StreamGeneratorType), + OptionFormattingUtilities.Format(nameof(this.options.EventsInStream), this.options.EventsInStream), + }; + } } } } diff --git a/src/OrleansProviders/Streams/Generator/IStreamGenerator.cs b/src/OrleansProviders/Streams/Generator/IStreamGenerator.cs index beb45004d02..4f73e7f1945 100644 --- a/src/OrleansProviders/Streams/Generator/IStreamGenerator.cs +++ b/src/OrleansProviders/Streams/Generator/IStreamGenerator.cs @@ -38,11 +38,5 @@ public interface IStreamGeneratorConfig /// Stream generator type /// Type StreamGeneratorType { get; } - - /// - /// Populates generator configuration from provider configuration - /// - /// - void PopulateFromProviderConfig(IProviderConfiguration providerConfiguration); } } diff --git a/src/OrleansProviders/Streams/Memory/MemoryAdapterConfig.cs b/src/OrleansProviders/Streams/Memory/MemoryAdapterConfig.cs deleted file mode 100644 index 99a66179a1e..00000000000 --- a/src/OrleansProviders/Streams/Memory/MemoryAdapterConfig.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Orleans.Providers.Streams.Common; -using System; -using System.Collections.Generic; -using System.Globalization; - -namespace Orleans.Providers -{ - /// - /// This configuration class is used to configure the MemoryStreamProvider. - /// It tells the stream provider how many queues to create. - /// - public class MemoryAdapterConfig : RecoverableStreamProviderSettings - { - /// - /// Stream provider name. - /// - public String StreamProviderName { get; private set; } - - /// - /// Total queue count name. Indicates the name of the property in provider config. - /// - private const string TotalQueueCountName = "TotalQueueCount"; - - /// - /// Total queue count default value. - /// - private const int TotalQueueCountDefault = 4; - - /// - /// Actual total queue count. - /// - public int TotalQueueCount { get; set; } - - /// - /// Constructor - /// - /// - /// - public MemoryAdapterConfig(string streamProviderName, int totalQueueCount = TotalQueueCountDefault) - { - if (string.IsNullOrWhiteSpace(streamProviderName)) - { - throw new ArgumentNullException(nameof(streamProviderName)); - } - if (totalQueueCount <= 0) - { - throw new ArgumentOutOfRangeException(nameof(totalQueueCount), "totalQueueCount must be larger than 0."); - } - this.StreamProviderName = streamProviderName; - this.TotalQueueCount = totalQueueCount; - } - - /// - /// Utility function to convert config to property bag for use in stream provider configuration - /// - /// - public override void WriteProperties(Dictionary properties) - { - properties.Add(TotalQueueCountName, TotalQueueCount.ToString(CultureInfo.InvariantCulture)); - base.WriteProperties(properties); - } - - /// - /// Utility function to populate config from provider config - /// - /// - public override void PopulateFromProviderConfig(IProviderConfiguration providerConfiguration) - { - TotalQueueCount = providerConfiguration.GetIntProperty(TotalQueueCountName, TotalQueueCountDefault); - base.PopulateFromProviderConfig(providerConfiguration); - } - } -} diff --git a/src/OrleansProviders/Streams/Memory/MemoryAdapterFactory.cs b/src/OrleansProviders/Streams/Memory/MemoryAdapterFactory.cs index eb535050bad..6af4487b86c 100644 --- a/src/OrleansProviders/Streams/Memory/MemoryAdapterFactory.cs +++ b/src/OrleansProviders/Streams/Memory/MemoryAdapterFactory.cs @@ -4,11 +4,13 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Logging; using Orleans.Providers.Streams.Common; using Orleans.Runtime; using Orleans.Streams; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; +using Orleans.Configuration; namespace Orleans.Providers { @@ -20,25 +22,23 @@ namespace Orleans.Providers public class MemoryAdapterFactory : IQueueAdapterFactory, IQueueAdapter, IQueueAdapterCache where TSerializer : class, IMemoryMessageBodySerializer { - - private TSerializer serializer; + private readonly MemoryStreamOptions options; + private readonly IGrainFactory grainFactory; + private readonly ITelemetryProducer telemetryProducer; + private readonly ILoggerFactory loggerFactory; + private readonly ILogger logger; + private readonly TSerializer serializer; private IStreamQueueMapper streamQueueMapper; private ConcurrentDictionary queueGrains; private IObjectPool bufferPool; private BlockPoolMonitorDimensions blockPoolMonitorDimensions; private IStreamFailureHandler streamFailureHandler; - private IServiceProvider serviceProvider; - private MemoryAdapterConfig adapterConfig; - private ITelemetryProducer telemetryProducer; - private ILogger logger; - private ILoggerFactory loggerFactory; - private String providerName; - private IGrainFactory grainFactory; private TimePurgePredicate purgePredicate; + /// /// Name of the adapter. Primarily for logging purposes /// - public string Name => adapterConfig.StreamProviderName; + public string Name { get; } /// /// Determines whether this is a rewindable stream adapter - supports subscribing from previous point in time. @@ -75,33 +75,34 @@ public class MemoryAdapterFactory : IQueueAdapterFactory, IQueueAda /// protected Func ReceiverMonitorFactory; + public MemoryAdapterFactory(string providerName, MemoryStreamOptions options, IServiceProvider serviceProvider, IGrainFactory grainFactory, ITelemetryProducer telemetryProducer, ILoggerFactory loggerFactory) + { + this.Name = providerName; + this.options = options ?? throw new ArgumentNullException(nameof(options)); + this.grainFactory = grainFactory ?? throw new ArgumentNullException(nameof(grainFactory)); + this.telemetryProducer = telemetryProducer ?? throw new ArgumentNullException(nameof(telemetryProducer)); + this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); + this.logger = loggerFactory.CreateLogger>>(); + this.serializer = MemoryMessageBodySerializerFactory.GetOrCreateSerializer(serviceProvider); + } + /// /// Factory initialization. /// /// /// /// - public void Init(IProviderConfiguration providerConfig, string name, IServiceProvider svcProvider) + public void Init() { - logger = svcProvider.GetService>>(); - this.loggerFactory = svcProvider.GetRequiredService(); - serviceProvider = svcProvider; - providerName = name; - queueGrains = new ConcurrentDictionary(); - adapterConfig = new MemoryAdapterConfig(providerName); - this.telemetryProducer = svcProvider.GetService(); + this.queueGrains = new ConcurrentDictionary(); if (CacheMonitorFactory == null) this.CacheMonitorFactory = (dimensions, telemetryProducer) => new DefaultCacheMonitor(dimensions, telemetryProducer); if (this.BlockPoolMonitorFactory == null) this.BlockPoolMonitorFactory = (dimensions, telemetryProducer) => new DefaultBlockPoolMonitor(dimensions, telemetryProducer); if (this.ReceiverMonitorFactory == null) this.ReceiverMonitorFactory = (dimensions, telemetryProducer) => new DefaultQueueAdapterReceiverMonitor(dimensions, telemetryProducer); - purgePredicate = new TimePurgePredicate(adapterConfig.DataMinTimeInCache, adapterConfig.DataMaxAgeInCache); - grainFactory = (IGrainFactory)serviceProvider.GetService(typeof(IGrainFactory)); - adapterConfig.PopulateFromProviderConfig(providerConfig); - streamQueueMapper = new HashRingBasedStreamQueueMapper(adapterConfig.TotalQueueCount, adapterConfig.StreamProviderName); - - this.serializer = MemoryMessageBodySerializerFactory.GetOrCreateSerializer(svcProvider); + this.purgePredicate = new TimePurgePredicate(this.options.DataMinTimeInCache, this.options.DataMaxAgeInCache); + this.streamQueueMapper = new HashRingBasedStreamQueueMapper(this.options.TotalQueueCount, this.Name); } private void CreateBufferPoolIfNotCreatedYet() @@ -112,7 +113,7 @@ private void CreateBufferPoolIfNotCreatedYet() this.blockPoolMonitorDimensions = new BlockPoolMonitorDimensions($"BlockPool-{Guid.NewGuid()}"); var oneMb = 1 << 20; var objectPoolMonitor = new ObjectPoolMonitorBridge(this.BlockPoolMonitorFactory(blockPoolMonitorDimensions, this.telemetryProducer), oneMb); - this.bufferPool = new ObjectPool(() => new FixedSizeBuffer(oneMb), objectPoolMonitor, this.adapterConfig.StatisticMonitorWriteInterval); + this.bufferPool = new ObjectPool(() => new FixedSizeBuffer(oneMb), objectPoolMonitor, this.options.StatisticMonitorWriteInterval); } } @@ -151,7 +152,7 @@ public IStreamQueueMapper GetStreamQueueMapper() public IQueueAdapterReceiver CreateReceiver(QueueId queueId) { var dimensions = new ReceiverMonitorDimensions(queueId.ToString()); - var receiverLogger = this.loggerFactory.CreateLogger($"{typeof(MemoryAdapterReceiver).FullName}.{this.providerName}.{queueId}"); + var receiverLogger = this.loggerFactory.CreateLogger($"{typeof(MemoryAdapterReceiver).FullName}.{this.Name}.{queueId}"); var receiverMonitor = this.ReceiverMonitorFactory(dimensions, this.telemetryProducer); IQueueAdapterReceiver receiver = new MemoryAdapterReceiver(GetQueueGrain(queueId), receiverLogger, this.serializer, receiverMonitor); return receiver; @@ -192,9 +193,9 @@ public IQueueCache CreateQueueCache(QueueId queueId) { //move block pool creation from init method to here, to avoid unnecessary block pool creation when stream provider is initialized in client side. CreateBufferPoolIfNotCreatedYet(); - var logger = this.loggerFactory.CreateLogger($"{typeof(MemoryPooledCache).FullName}.{this.providerName}.{queueId}"); + var logger = this.loggerFactory.CreateLogger($"{typeof(MemoryPooledCache).FullName}.{this.Name}.{queueId}"); var monitor = this.CacheMonitorFactory(new CacheMonitorDimensions(queueId.ToString(), this.blockPoolMonitorDimensions.BlockPoolId), this.telemetryProducer); - return new MemoryPooledCache(bufferPool, purgePredicate, logger, this.serializer, monitor, this.adapterConfig.StatisticMonitorWriteInterval); + return new MemoryPooledCache(bufferPool, purgePredicate, logger, this.serializer, monitor, this.options.StatisticMonitorWriteInterval); } /// @@ -215,7 +216,7 @@ public Task GetDeliveryFailureHandler(QueueId queueId) private Guid GenerateDeterministicGuid(QueueId queueId) { // provider name hash code - int providerNameGuidHash = (int)JenkinsHash.ComputeHash(providerName); + int providerNameGuidHash = (int)JenkinsHash.ComputeHash(this.Name); // get queueId hash code uint queueIdHash = queueId.GetUniformHashCode(); @@ -244,5 +245,13 @@ private IMemoryStreamQueueGrain GetQueueGrain(QueueId queueId) { return queueGrains.GetOrAdd(queueId, grainFactory.GetGrain(GenerateDeterministicGuid(queueId))); } + + public static MemoryAdapterFactory Create(IServiceProvider services, string name) + { + IOptionsSnapshot optionsSnapshot = services.GetRequiredService>(); + var factory = ActivatorUtilities.CreateInstance>(services, name, optionsSnapshot.Get(name)); + factory.Init(); + return factory; + } } } diff --git a/src/OrleansProviders/Streams/Memory/MemoryAdapterOptions.cs b/src/OrleansProviders/Streams/Memory/MemoryAdapterOptions.cs new file mode 100644 index 00000000000..e5c6c4250b0 --- /dev/null +++ b/src/OrleansProviders/Streams/Memory/MemoryAdapterOptions.cs @@ -0,0 +1,22 @@ + +using System.Collections.Generic; +using Microsoft.Extensions.Options; + +namespace Orleans.Configuration +{ + /// + /// This configuration class is used to configure the MemoryStreamProvider. + /// It tells the stream provider how many queues to create. + /// + public class MemoryStreamOptions : RecoverableStreamOptions + { + /// + /// Actual total queue count. + /// + public int TotalQueueCount { get; set; } = DEFAULT_TOTAL_QUEUE_COUNT; + /// + /// Total queue count default value. + /// + public const int DEFAULT_TOTAL_QUEUE_COUNT = 4; + } +} diff --git a/src/OrleansProviders/Streams/Memory/MemoryStreamProvider.cs b/src/OrleansProviders/Streams/Memory/MemoryStreamProvider.cs deleted file mode 100644 index d518589f501..00000000000 --- a/src/OrleansProviders/Streams/Memory/MemoryStreamProvider.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Orleans.Providers.Streams.Common; - -namespace Orleans.Providers -{ - /// - /// This is a persistent stream provider that uses in-memory grain to queue the events. - /// This is primarily for test purposes. - /// - public class MemoryStreamProvider : PersistentStreamProvider> - { - } - - /// - /// This is a persistent stream provider that uses in-memory grain to queue the events. - /// This is primarily for test purposes. - /// - public class MemoryStreamProvider : PersistentStreamProvider> - where TSerializer : class, IMemoryMessageBodySerializer - { - } -} diff --git a/test/AWSUtils.Tests/Streaming/SQSAdapterTests.cs b/test/AWSUtils.Tests/Streaming/SQSAdapterTests.cs index bcf1c95415b..f4b8e1930e2 100644 --- a/test/AWSUtils.Tests/Streaming/SQSAdapterTests.cs +++ b/test/AWSUtils.Tests/Streaming/SQSAdapterTests.cs @@ -1,22 +1,22 @@ -using Orleans.Providers; -using Orleans.Providers.Streams.Common; -using Orleans.Runtime; -using Orleans.Runtime.Configuration; -using Orleans.Streams; -using OrleansAWSUtils.Streams; -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; -using AWSUtils.Tests.StorageTests; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Orleans.Providers.Streams.Common; +using Orleans.Runtime; +using Orleans.Streams; +using OrleansAWSUtils.Streams; +using AWSUtils.Tests.StorageTests; using TestExtensions; using Xunit; using Xunit.Abstractions; using OrleansAWSUtils.Storage; +using Orleans.Configuration; namespace AWSUtils.Tests.Streaming { @@ -53,19 +53,17 @@ public void Dispose() [SkippableFact] public async Task SendAndReceiveFromSQS() { - var properties = new Dictionary - { - {SQSAdapterFactory.DataConnectionStringPropertyName, AWSTestConstants.DefaultSQSConnectionString}, - {SQSAdapterFactory.DeploymentIdPropertyName, this.clusterId} - }; - var config = new ProviderConfiguration(properties, "type", "name"); - - var adapterFactory = new SQSAdapterFactory(); - adapterFactory.Init(config, SQS_STREAM_PROVIDER_NAME, this.fixture.Services); - await SendAndReceiveFromQueueAdapter(adapterFactory, config); + var options = new SqsStreamOptions + { + ConnectionString = AWSTestConstants.DefaultSQSConnectionString, + ClusterId = this.clusterId + }; + var adapterFactory = new SQSAdapterFactory(SQS_STREAM_PROVIDER_NAME, options, null, Options.Create(new SiloOptions()), null, null); + adapterFactory.Init(); + await SendAndReceiveFromQueueAdapter(adapterFactory); } - private async Task SendAndReceiveFromQueueAdapter(IQueueAdapterFactory adapterFactory, IProviderConfiguration config) + private async Task SendAndReceiveFromQueueAdapter(IQueueAdapterFactory adapterFactory) { IQueueAdapter adapter = await adapterFactory.CreateAdapter(); IQueueAdapterCache cache = adapterFactory.GetQueueAdapterCache(); diff --git a/test/AWSUtils.Tests/Streaming/SQSClientStreamTests.cs b/test/AWSUtils.Tests/Streaming/SQSClientStreamTests.cs index b96d3d492f7..0c7b01ad8ff 100644 --- a/test/AWSUtils.Tests/Streaming/SQSClientStreamTests.cs +++ b/test/AWSUtils.Tests/Streaming/SQSClientStreamTests.cs @@ -12,6 +12,11 @@ using Xunit; using Xunit.Abstractions; using OrleansAWSUtils.Streams; +using Orleans.Hosting; +using Microsoft.Extensions.Configuration; +using Orleans; +using Microsoft.Extensions.Options; +using Orleans.Configuration; namespace AWSUtils.Tests.Streaming { @@ -38,11 +43,6 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) } var clusterId = Guid.NewGuid().ToString(); - var streamConnectionString = new Dictionary - { - {"DataConnectionString", StorageConnectionString}, - {"DeploymentId", clusterId} - }; builder.ConfigureLegacyConfiguration(legacy => { legacy.ClusterConfiguration.AddMemoryStorageProvider("PubSubStore"); @@ -52,9 +52,33 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) legacy.ClusterConfiguration.Globals.ClientDropTimeout = TimeSpan.FromSeconds(5); legacy.ClientConfiguration.DataConnectionString = StorageConnectionString; legacy.ClusterConfiguration.Globals.DataConnectionString = StorageConnectionString; - legacy.ClusterConfiguration.Globals.RegisterStreamProvider(SQSStreamProviderName, streamConnectionString); - legacy.ClientConfiguration.RegisterStreamProvider(SQSStreamProviderName, streamConnectionString); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddSqsStreams(SQSStreamProviderName, options => + { + options.ConnectionString = AWSTestConstants.DefaultSQSConnectionString; + }); + } + } + + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddSqsStreams(SQSStreamProviderName, options => + { + options.ConnectionString = AWSTestConstants.DefaultSQSConnectionString; + }); + } } public override void Dispose() diff --git a/test/AWSUtils.Tests/Streaming/SQSStreamTests.cs b/test/AWSUtils.Tests/Streaming/SQSStreamTests.cs index 45c86a19477..0ee4a6105a7 100644 --- a/test/AWSUtils.Tests/Streaming/SQSStreamTests.cs +++ b/test/AWSUtils.Tests/Streaming/SQSStreamTests.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using AWSUtils.Tests.StorageTests; using Microsoft.Extensions.Logging.Abstractions; -using Orleans.Providers.Streams; +using Microsoft.Extensions.Configuration; using Orleans.Storage; using Orleans.TestingHost; using UnitTests.StreamingTests; @@ -11,6 +11,8 @@ using TestExtensions; using UnitTests.Streaming; using OrleansAWSUtils.Streams; +using Orleans.Hosting; +using Orleans; namespace AWSUtils.Tests.Streaming { @@ -40,15 +42,6 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) //previous silo creation options.ClusterConfiguration.Globals.DataConnectionString = AWSTestConstants.DefaultSQSConnectionString; options.ClientConfiguration.DataConnectionString = AWSTestConstants.DefaultSQSConnectionString; - var streamConnectionString = new Dictionary - { - {"DataConnectionString", AWSTestConstants.DefaultSQSConnectionString} - }; - - options.ClientConfiguration.RegisterStreamProvider("SQSProvider", streamConnectionString); - - options.ClusterConfiguration.Globals.RegisterStreamProvider("SQSProvider", streamConnectionString); - options.ClusterConfiguration.Globals.RegisterStreamProvider("SQSProvider2", streamConnectionString); var storageConnectionString = new Dictionary { @@ -64,9 +57,38 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) }; options.ClusterConfiguration.Globals.RegisterStorageProvider("PubSubStore", storageConnectionString2); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); } + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddSqsStreams("SQSProvider", options => + { + options.ConnectionString = AWSTestConstants.DefaultSQSConnectionString; + }) + .AddSqsStreams("SQSProvider2", options => + { + options.ConnectionString = AWSTestConstants.DefaultSQSConnectionString; + }); + } + } + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddSqsStreams("SQSProvider", options => + { + options.ConnectionString = AWSTestConstants.DefaultSQSConnectionString; + }); + } + } + public SQSStreamTests() { runner = new SingleStreamTestRunner(this.InternalClient, SQS_STREAM_PROVIDER_NAME); diff --git a/test/AWSUtils.Tests/Streaming/SQSSubscriptionMultiplicityTests.cs b/test/AWSUtils.Tests/Streaming/SQSSubscriptionMultiplicityTests.cs index 4ce624af80f..fe86597351b 100644 --- a/test/AWSUtils.Tests/Streaming/SQSSubscriptionMultiplicityTests.cs +++ b/test/AWSUtils.Tests/Streaming/SQSSubscriptionMultiplicityTests.cs @@ -1,17 +1,19 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; using AWSUtils.Tests.StorageTests; +using Xunit; using Orleans; -using Orleans.Providers.Streams; using Orleans.Runtime; using Orleans.Runtime.Configuration; using Orleans.TestingHost; using OrleansAWSUtils.Streams; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging.Abstractions; +using Orleans.Hosting; using TestExtensions; using UnitTests.StreamingTests; -using Xunit; +using Orleans.Configuration; namespace AWSUtils.Tests.Streaming { @@ -30,11 +32,6 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) } var clusterId = Guid.NewGuid().ToString(); - var streamConnectionString = new Dictionary - { - {"DataConnectionString", StreamConnectionString}, - {"DeploymentId", clusterId} - }; builder.ConfigureLegacyConfiguration(legacy => { @@ -44,9 +41,33 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) legacy.ClientConfiguration.ClusterId = clusterId; legacy.ClientConfiguration.DataConnectionString = StreamConnectionString; legacy.ClusterConfiguration.Globals.DataConnectionString = StreamConnectionString; - legacy.ClusterConfiguration.Globals.RegisterStreamProvider(SQSStreamProviderName, streamConnectionString); - legacy.ClientConfiguration.RegisterStreamProvider(SQSStreamProviderName, streamConnectionString); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddSqsStreams(SQSStreamProviderName, options => + { + options.ConnectionString = AWSTestConstants.DefaultSQSConnectionString; + }); + } + } + + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddSqsStreams(SQSStreamProviderName, options => + { + options.ConnectionString = AWSTestConstants.DefaultSQSConnectionString; + }); + } } public SQSSubscriptionMultiplicityTests() diff --git a/test/GoogleUtils.Tests/Streaming/PubSubClientStreamTests.cs b/test/GoogleUtils.Tests/Streaming/PubSubClientStreamTests.cs index c59e3f3d4a6..99e345eb15f 100644 --- a/test/GoogleUtils.Tests/Streaming/PubSubClientStreamTests.cs +++ b/test/GoogleUtils.Tests/Streaming/PubSubClientStreamTests.cs @@ -9,6 +9,9 @@ using Xunit; using Xunit.Abstractions; using Orleans.Providers.GCP.Streams.PubSub; +using Orleans.Hosting; +using Microsoft.Extensions.Configuration; +using Orleans; namespace GoogleUtils.Tests.Streaming { @@ -34,22 +37,43 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) throw new SkipException("Google PubSub Simulator not available"); } - var providerSettings = new Dictionary - { - {"ProjectId", GoogleTestUtils.ProjectId}, - {"TopicId", GoogleTestUtils.TopicId}, - {"DeploymentId", GoogleTestUtils.DeploymentId.ToString()}, - {"Deadline", "600"}, - //{ "CustomEndpoint", "localhost:8085" } - }; - builder.ConfigureLegacyConfiguration(legacy => { legacy.ClusterConfiguration.AddMemoryStorageProvider("PubSubStore"); - legacy.ClusterConfiguration.Globals.RegisterStreamProvider(PROVIDER_NAME, providerSettings); legacy.ClusterConfiguration.Globals.ClientDropTimeout = TimeSpan.FromSeconds(5); - legacy.ClientConfiguration.RegisterStreamProvider(PROVIDER_NAME, providerSettings); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddPubSubStreams(PROVIDER_NAME, options => + { + options.ProjectId = GoogleTestUtils.ProjectId; + options.TopicId = GoogleTestUtils.TopicId; + options.ClusterId = GoogleTestUtils.DeploymentId.ToString(); + options.Deadline = TimeSpan.FromSeconds(600); + }); + } + } + + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddPubSubStreams(PROVIDER_NAME, options => + { + options.ProjectId = GoogleTestUtils.ProjectId; + options.TopicId = GoogleTestUtils.TopicId; + options.ClusterId = GoogleTestUtils.DeploymentId.ToString(); + options.Deadline = TimeSpan.FromSeconds(600); + }); + } } [SkippableFact] diff --git a/test/GoogleUtils.Tests/Streaming/PubSubStreamTests.cs b/test/GoogleUtils.Tests/Streaming/PubSubStreamTests.cs index 207f1996f84..b0397e7a41d 100644 --- a/test/GoogleUtils.Tests/Streaming/PubSubStreamTests.cs +++ b/test/GoogleUtils.Tests/Streaming/PubSubStreamTests.cs @@ -1,9 +1,12 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Orleans; +using Orleans.Hosting; using Orleans.Providers.GCP.Streams.PubSub; using Orleans.Runtime.Configuration; using Orleans.Storage; using Orleans.TestingHost; -using System.Collections.Generic; -using System.Threading.Tasks; using TestExtensions; using UnitTests.Streaming; using UnitTests.StreamingTests; @@ -31,19 +34,40 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) legacy.ClusterConfiguration.AddSimpleMessageStreamProvider("SMSProvider", fireAndForgetDelivery: false); legacy.ClientConfiguration.AddSimpleMessageStreamProvider("SMSProvider", fireAndForgetDelivery: false); - var providerSettings = new Dictionary - { - {"ProjectId", GoogleTestUtils.ProjectId}, - {"TopicId", GoogleTestUtils.TopicId}, - {"DeploymentId", GoogleTestUtils.DeploymentId.ToString()}, - {"Deadline", "600"}, - //{ "CustomEndpoint", "localhost:8085" } - }; - - legacy.ClientConfiguration.RegisterStreamProvider(PUBSUB_STREAM_PROVIDER_NAME, providerSettings); - legacy.ClusterConfiguration.Globals.RegisterStreamProvider(PUBSUB_STREAM_PROVIDER_NAME, providerSettings); legacy.ClusterConfiguration.Globals.RegisterStorageProvider("PubSubStore"); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddPubSubStreams(PUBSUB_STREAM_PROVIDER_NAME, options => + { + options.ProjectId = GoogleTestUtils.ProjectId; + options.TopicId = GoogleTestUtils.TopicId; + options.ClusterId = GoogleTestUtils.DeploymentId.ToString(); + options.Deadline = TimeSpan.FromSeconds(600); + }); + } + } + + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddPubSubStreams(PUBSUB_STREAM_PROVIDER_NAME, options => + { + options.ProjectId = GoogleTestUtils.ProjectId; + options.TopicId = GoogleTestUtils.TopicId; + options.ClusterId = GoogleTestUtils.DeploymentId.ToString(); + options.Deadline = TimeSpan.FromSeconds(600); + }); + } } public PubSubStreamTests() diff --git a/test/GoogleUtils.Tests/Streaming/PubSubSubscriptionMultiplicityTests.cs b/test/GoogleUtils.Tests/Streaming/PubSubSubscriptionMultiplicityTests.cs index 11d958d4c34..6b89b97e33c 100644 --- a/test/GoogleUtils.Tests/Streaming/PubSubSubscriptionMultiplicityTests.cs +++ b/test/GoogleUtils.Tests/Streaming/PubSubSubscriptionMultiplicityTests.cs @@ -1,9 +1,11 @@ +using Microsoft.Extensions.Configuration; +using Orleans; +using Orleans.Hosting; using Orleans.Providers.GCP.Streams.PubSub; using Orleans.Runtime; using Orleans.Runtime.Configuration; using Orleans.TestingHost; using System; -using System.Collections.Generic; using System.Threading.Tasks; using TestExtensions; using UnitTests.StreamingTests; @@ -25,23 +27,45 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) throw new SkipException("Google PubSub Simulator not available"); } - var providerSettings = new Dictionary - { - { "ProjectId", GoogleTestUtils.ProjectId }, - { "TopicId", GoogleTestUtils.TopicId }, - { "DeploymentId", GoogleTestUtils.DeploymentId.ToString()}, - { "Deadline", "600" }, - //{ "CustomEndpoint", "localhost:8085" } - }; builder.ConfigureLegacyConfiguration(legacy => { legacy.ClusterConfiguration.AddMemoryStorageProvider("PubSubStore"); legacy.ClusterConfiguration.Globals.ClusterId = GoogleTestUtils.ProjectId; legacy.ClientConfiguration.ClusterId = GoogleTestUtils.ProjectId; - legacy.ClientConfiguration.RegisterStreamProvider(PROVIDER_NAME, providerSettings); - legacy.ClusterConfiguration.Globals.RegisterStreamProvider(PROVIDER_NAME, providerSettings); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddPubSubStreams(PROVIDER_NAME, options => + { + options.ProjectId = GoogleTestUtils.ProjectId; + options.TopicId = GoogleTestUtils.TopicId; + options.ClusterId = GoogleTestUtils.DeploymentId.ToString(); + options.Deadline = TimeSpan.FromSeconds(600); + }); + } + } + + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddPubSubStreams(PROVIDER_NAME, options => + { + options.ProjectId = GoogleTestUtils.ProjectId; + options.TopicId = GoogleTestUtils.TopicId; + options.ClusterId = GoogleTestUtils.DeploymentId.ToString(); + options.Deadline = TimeSpan.FromSeconds(600); + }); + } } public PubSubSubscriptionMultiplicityTests() diff --git a/test/ServiceBus.Tests/EvictionStrategyTests/EHPurgeLogicTests.cs b/test/ServiceBus.Tests/EvictionStrategyTests/EHPurgeLogicTests.cs index 81624c67274..3714326ecbe 100644 --- a/test/ServiceBus.Tests/EvictionStrategyTests/EHPurgeLogicTests.cs +++ b/test/ServiceBus.Tests/EvictionStrategyTests/EHPurgeLogicTests.cs @@ -17,6 +17,7 @@ using TestExtensions; using Xunit; using Orleans.ServiceBus.Providers.Testing; +using Orleans.Hosting; namespace ServiceBus.Tests.EvictionStrategyTests { @@ -40,7 +41,7 @@ public EHPurgeLogicTests() //an mock eh settings this.ehSettings = new EventHubPartitionSettings { - Hub = new EventHubSettings(), + Hub = new EventHubStreamOptions(), Partition = "MockPartition" }; diff --git a/test/ServiceBus.Tests/PluggableQueueBalancerTests.cs b/test/ServiceBus.Tests/PluggableQueueBalancerTests.cs index eff77cd290c..76b20ac82f8 100644 --- a/test/ServiceBus.Tests/PluggableQueueBalancerTests.cs +++ b/test/ServiceBus.Tests/PluggableQueueBalancerTests.cs @@ -1,15 +1,10 @@ -using Microsoft.Extensions.DependencyInjection; -using Orleans.Runtime; +using System.Threading.Tasks; +using Orleans.Configuration; +using Orleans.Hosting; using Orleans.Runtime.Configuration; using Orleans.ServiceBus.Providers.Testing; using Orleans.Storage; -using Orleans.Streams; using Orleans.TestingHost; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Tester.StreamingTests; using TestExtensions; using Xunit; @@ -22,9 +17,6 @@ public class PluggableQueueBalancerTestsWithEHStreamProvider : PluggableQueueBal private const string StreamProviderName = "EventHubStreamProvider"; private static readonly int TotalQueueCount = 6; private static readonly short SiloCount = 2; - public static readonly EventHubGeneratorStreamProviderSettings ProviderSettings = - new EventHubGeneratorStreamProviderSettings(StreamProviderName); - private readonly Fixture fixture; public class Fixture : BaseTestClusterFixture @@ -32,8 +24,8 @@ public class Fixture : BaseTestClusterFixture protected override void ConfigureTestCluster(TestClusterBuilder builder) { builder.Options.InitialSilosCount = SiloCount; - ProviderSettings.EventHubPartitionCount = TotalQueueCount; builder.AddSiloBuilderConfigurator(); + builder.AddSiloBuilderConfigurator(); builder.ConfigureLegacyConfiguration(legacy => { AdjustClusterConfiguration(legacy.ClusterConfiguration); @@ -42,16 +34,24 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) private static void AdjustClusterConfiguration(ClusterConfiguration config) { - var settings = new Dictionary(); - // get initial settings from configs - ProviderSettings.WriteProperties(settings); - ProviderSettings.WriteDataGeneratingConfig(settings); - ConfigureCustomQueueBalancer(settings, config); - // register stream provider - config.Globals.RegisterStreamProvider(StreamProviderName, settings); config.Globals.RegisterStorageProvider("PubSubStore"); } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddPersistentStreams(StreamProviderName, + EventDataGeneratorAdapterFactory.Create, + options => + { + options.EventHubPartitionCount = TotalQueueCount; + options.BalancerType = typeof(LeaseBasedQueueBalancerForTest); + }); + } + } } public PluggableQueueBalancerTestsWithEHStreamProvider(Fixture fixture) diff --git a/test/ServiceBus.Tests/SlowConsumingTests/EHSlowConsumingTests.cs b/test/ServiceBus.Tests/SlowConsumingTests/EHSlowConsumingTests.cs index 1792cfe3ffc..557e3853897 100644 --- a/test/ServiceBus.Tests/SlowConsumingTests/EHSlowConsumingTests.cs +++ b/test/ServiceBus.Tests/SlowConsumingTests/EHSlowConsumingTests.cs @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Microsoft.WindowsAzure.Storage.Table; using Orleans; -using Orleans.AzureUtils; +using Orleans.Configuration; +using Orleans.Hosting; +using Orleans.Providers.Streams.Common; using Orleans.Runtime; using Orleans.Runtime.Configuration; -using Orleans.ServiceBus.Providers; using Orleans.ServiceBus.Providers.Testing; using Orleans.Storage; using Orleans.Streams; @@ -29,8 +29,6 @@ public class EHSlowConsumingTests : OrleansTestingBase, IClassFixture AdjustClusterConfiguration(legacy.ClusterConfiguration)); + builder.AddSiloBuilderConfigurator(); } private static void AdjustClusterConfiguration(ClusterConfiguration config) { - var settings = new Dictionary(); - // get initial settings from configs - ProviderSettings.WriteProperties(settings); - ProviderSettings.WriteDataGeneratingConfig(settings); - - // add queue balancer setting - settings.Add(PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.AssemblyQualifiedName); - - // register stream provider - config.Globals.RegisterStreamProvider(StreamProviderName, settings); config.Globals.RegisterStorageProvider("PubSubStore"); } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder.AddPersistentStreams(StreamProviderName, EHStreamProviderWithCreatedCacheListAdapterFactory.Create, options => + { + options.SlowConsumingMonitorPressureWindowSize = monitorPressureWindowSize; + options.SlowConsumingMonitorFlowControlThreshold = flowControlThredhold; + options.AveragingCachePressureMonitorFlowControlThreshold = null; + options.BalancerType = StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer; + }); + } + } } private readonly Random seed; @@ -83,9 +83,9 @@ public async Task EHSlowConsuming_ShouldFavorSlowConsumer() //configure data generator for stream and start producing var mgmtGrain = this.fixture.GrainFactory.GetGrain(0); - var randomStreamPlacementArg = new EventDataGeneratorStreamProvider.AdapterFactory.StreamRandomPlacementArg(streamId, this.seed.Next(100)); - await mgmtGrain.SendControlCommandToProvider(typeof(EHStreamProviderWithCreatedCacheList).FullName, StreamProviderName, - (int)EventDataGeneratorStreamProvider.AdapterFactory.Commands.Randomly_Place_Stream_To_Queue, randomStreamPlacementArg); + var randomStreamPlacementArg = new EventDataGeneratorAdapterFactory.StreamRandomPlacementArg(streamId, this.seed.Next(100)); + await mgmtGrain.SendControlCommandToProvider(typeof(PersistentStreamProvider).FullName, StreamProviderName, + (int)EventDataGeneratorAdapterFactory.Commands.Randomly_Place_Stream_To_Queue, randomStreamPlacementArg); //since there's an extreme slow consumer, so the back pressure algorithm should be triggered await TestingUtils.WaitUntilAsync(lastTry => AssertCacheBackPressureTriggered(true, lastTry), timeout); @@ -98,8 +98,8 @@ await mgmtGrain.SendControlCommandToProvider(typeof(EHStreamProviderWithCreatedC //clean up test await StopHealthyConsumerGrainComing(healthyConsumers); - await mgmtGrain.SendControlCommandToProvider(typeof(EHStreamProviderWithCreatedCacheList).FullName, StreamProviderName, - (int)EventDataGeneratorStreamProvider.AdapterFactory.Commands.Stop_Producing_On_Stream, streamId); + await mgmtGrain.SendControlCommandToProvider(typeof(PersistentStreamProvider).FullName, StreamProviderName, + (int)EventDataGeneratorAdapterFactory.Commands.Stop_Producing_On_Stream, streamId); } public static async Task> SetUpHealthyConsumerGrain(IGrainFactory GrainFactory, Guid streamId, string streamNameSpace, string streamProvider, int grainCount) @@ -144,8 +144,8 @@ private async Task AssertCacheBackPressureTriggered(bool expectedResult, b private async Task IsBackPressureTriggered() { IManagementGrain mgmtGrain = this.fixture.HostedCluster.GrainFactory.GetGrain(0); - object[] replies = await mgmtGrain.SendControlCommandToProvider(typeof(EHStreamProviderWithCreatedCacheList).FullName, - StreamProviderName, EHStreamProviderWithCreatedCacheList.AdapterFactory.IsCacheBackPressureTriggeredCommand, null); + object[] replies = await mgmtGrain.SendControlCommandToProvider(typeof(PersistentStreamProvider).FullName, + StreamProviderName, EHStreamProviderWithCreatedCacheListAdapterFactory.IsCacheBackPressureTriggeredCommand, null); foreach (var re in replies) { if ((bool)re) diff --git a/test/ServiceBus.Tests/SlowConsumingTests/EventHubStreamProviderSettingsTests.cs b/test/ServiceBus.Tests/SlowConsumingTests/EventHubStreamProviderSettingsTests.cs deleted file mode 100644 index 80bf26b0f5e..00000000000 --- a/test/ServiceBus.Tests/SlowConsumingTests/EventHubStreamProviderSettingsTests.cs +++ /dev/null @@ -1,84 +0,0 @@ -using Orleans.Providers; -using Orleans.Runtime.Configuration; -using Orleans.ServiceBus.Providers; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Xunit; - -namespace ServiceBus.Tests.SlowConsumingTests -{ - - /// - /// EventHubAdapterFactory populate EventHubStreamProviderSettings from IProviderConfiguration. - /// So this test suit tests that EventHubStreamProviderSettings will be populated back as the same as before - /// it is written into ProviderConfiguration. - /// - public class EventHubStreamProviderSettingsTests - { - private static string StreamProviderName = "EHStreamProvider"; - [Fact, TestCategory("EventHub"), TestCategory("Streaming"), TestCategory("BVT")] - public void DefaultSetting_Write_Into_ProviderConfiguration_PopulateBack() - { - var expectedSetting = new EventHubStreamProviderSettings(StreamProviderName); - AssertSettingEqual_After_WriteInto_ProviderConfiguration_AndPopulateBack(expectedSetting); - } - - [Fact, TestCategory("EventHub"), TestCategory("Streaming"), TestCategory("BVT")] - public void SettingWithSlowConsumingMonitorSetUp_Write_Into_ProviderConfiguration_PopulateBack() - { - var expectedSetting = new EventHubStreamProviderSettings(StreamProviderName); - expectedSetting.SlowConsumingMonitorPressureWindowSize = TimeSpan.FromMinutes(2); - expectedSetting.SlowConsumingMonitorFlowControlThreshold = 0.6; - AssertSettingEqual_After_WriteInto_ProviderConfiguration_AndPopulateBack(expectedSetting); - } - - [Fact, TestCategory("EventHub"), TestCategory("Streaming"), TestCategory("BVT")] - public void SettingWithAvgConsumingMonitorSetUp_Write_Into_ProviderConfiguration_PopulateBack() - { - var expectedSetting = new EventHubStreamProviderSettings(StreamProviderName); - expectedSetting.AveragingCachePressureMonitorFlowControlThreshold = 0.1; - AssertSettingEqual_After_WriteInto_ProviderConfiguration_AndPopulateBack(expectedSetting); - } - - private void AssertSettingEqual_After_WriteInto_ProviderConfiguration_AndPopulateBack(EventHubStreamProviderSettings expectedSetting) - { - var properties = new Dictionary(); - expectedSetting.WriteProperties(properties); - var config = new ProviderConfiguration(properties, typeof(EventHubStreamProvider).FullName, StreamProviderName); - - var actualSettings = new EventHubStreamProviderSettings(StreamProviderName); - actualSettings.PopulateFromProviderConfig(config); - AssertEqual(expectedSetting, actualSettings); - } - private void AssertEqual(EventHubStreamProviderSettings expectedSettings, EventHubStreamProviderSettings actualSettings) - { - - Assert.Equal(expectedSettings.StreamProviderName, actualSettings.StreamProviderName); - Assert.True(TwoSettingValueEquals(expectedSettings.SlowConsumingMonitorFlowControlThreshold, - actualSettings.SlowConsumingMonitorFlowControlThreshold)); - Assert.Equal(expectedSettings.SlowConsumingMonitorPressureWindowSize, actualSettings.SlowConsumingMonitorPressureWindowSize); - Assert.True(TwoSettingValueEquals(expectedSettings.AveragingCachePressureMonitorFlowControlThreshold, - actualSettings.AveragingCachePressureMonitorFlowControlThreshold)); - Assert.Equal(expectedSettings.EventHubSettingsType, actualSettings.EventHubSettingsType); - Assert.Equal(expectedSettings.CheckpointerSettingsType, actualSettings.CheckpointerSettingsType); - Assert.Equal(expectedSettings.DataMinTimeInCache, actualSettings.DataMinTimeInCache); - Assert.Equal(expectedSettings.DataMaxAgeInCache, actualSettings.DataMaxAgeInCache); - } - - private bool TwoSettingValueEquals(double? v1, double? v2) - { - //if both null. then return true - if (!v1.HasValue && !v2.HasValue) - return true; - if (v1.HasValue && v2.HasValue) - { - double tolerance = Math.Min(Math.Abs(v1.Value * .00001), Math.Abs(v2.Value * .00001)); - return Math.Abs(v1.Value - v2.Value) < tolerance; - } - return false; - } - } -} diff --git a/test/ServiceBus.Tests/StatisticMonitorTests/EHStatisticMonitorTests.cs b/test/ServiceBus.Tests/StatisticMonitorTests/EHStatisticMonitorTests.cs index 18aae2d667e..92de0cdb032 100644 --- a/test/ServiceBus.Tests/StatisticMonitorTests/EHStatisticMonitorTests.cs +++ b/test/ServiceBus.Tests/StatisticMonitorTests/EHStatisticMonitorTests.cs @@ -1,9 +1,8 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Azure.EventHubs; using Orleans.Runtime; using Orleans.Runtime.Configuration; -using Orleans.ServiceBus.Providers.Testing; using Orleans.Storage; using Orleans.Streams; using Orleans.TestingHost; @@ -12,6 +11,10 @@ using UnitTests.Grains.ProgrammaticSubscribe; using Xunit; using ServiceBus.Tests.SlowConsumingTests; +using Orleans.Hosting; +using Orleans.Providers.Streams.Common; +using Orleans.ServiceBus.Providers.Testing; +using Orleans.Configuration; namespace ServiceBus.Tests.MonitorTests { @@ -23,9 +26,6 @@ public class EHStatisticMonitorTests : OrleansTestingBase, IClassFixture AdjustClusterConfiguration(legacy.ClusterConfiguration)); + builder.AddSiloBuilderConfigurator(); } private static void AdjustClusterConfiguration(ClusterConfiguration config) { - var settings = new Dictionary(); - // get initial settings from configs - ProviderSettings.WriteProperties(settings); - ProviderSettings.WriteDataGeneratingConfig(settings); - - // add queue balancer setting - settings.Add(PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.AssemblyQualifiedName); - - // register stream provider - config.Globals.RegisterStreamProvider(StreamProviderName, settings); config.Globals.RegisterStorageProvider("PubSubStore"); } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddPersistentStreams(StreamProviderName, EHStreamProviderForMonitorTestsAdapterFactory.Create, options => + { + options.StatisticMonitorWriteInterval = monitorWriteInterval; + options.BalancerType = StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer; + }) + .ConfigureServices(services => + { + services.AddTransientNamedService>>(StreamProviderName, (s, n) => SimpleStreamEventDataGenerator.CreateFactory(s)); + }); + } + } + } private readonly Random seed; @@ -73,34 +81,34 @@ public async Task EHStatistics_MonitorCalledAccordingly() //configure data generator for stream and start producing var mgmtGrain = this.fixture.GrainFactory.GetGrain(0); - var randomStreamPlacementArg = new EventDataGeneratorStreamProvider.AdapterFactory.StreamRandomPlacementArg(streamId, this.seed.Next(100)); - await mgmtGrain.SendControlCommandToProvider(typeof(EHStreamProviderForMonitorTests).FullName, StreamProviderName, - (int)EventDataGeneratorStreamProvider.AdapterFactory.Commands.Randomly_Place_Stream_To_Queue, randomStreamPlacementArg); + var randomStreamPlacementArg = new EHStreamProviderForMonitorTestsAdapterFactory.StreamRandomPlacementArg(streamId, this.seed.Next(100)); + await mgmtGrain.SendControlCommandToProvider(typeof(PersistentStreamProvider).FullName, StreamProviderName, + (int)EHStreamProviderForMonitorTestsAdapterFactory.Commands.Randomly_Place_Stream_To_Queue, randomStreamPlacementArg); // let the test to run for a while to build up some streaming traffic await Task.Delay(timeout); //wait sometime after cache pressure changing, for the system to notice it and trigger cache monitor to track it - await mgmtGrain.SendControlCommandToProvider(typeof(EHStreamProviderForMonitorTests).FullName, StreamProviderName, - (int)EHStreamProviderForMonitorTests.AdapterFactory.QueryCommands.ChangeCachePressure, null); + await mgmtGrain.SendControlCommandToProvider(typeof(PersistentStreamProvider).FullName, StreamProviderName, + (int)EHStreamProviderForMonitorTestsAdapterFactory.QueryCommands.ChangeCachePressure, null); await Task.Delay(timeout); //assert EventHubReceiverMonitor call counters - var receiverMonitorCounters = await mgmtGrain.SendControlCommandToProvider(typeof(EHStreamProviderForMonitorTests).FullName, StreamProviderName, - (int)EHStreamProviderForMonitorTests.AdapterFactory.QueryCommands.GetReceiverMonitorCallCounters, null); + var receiverMonitorCounters = await mgmtGrain.SendControlCommandToProvider(typeof(PersistentStreamProvider).FullName, StreamProviderName, + (int)EHStreamProviderForMonitorTestsAdapterFactory.QueryCommands.GetReceiverMonitorCallCounters, null); foreach (var callCounter in receiverMonitorCounters) { AssertReceiverMonitorCallCounters(callCounter as EventHubReceiverMonitorCounters); } - var cacheMonitorCounters = await mgmtGrain.SendControlCommandToProvider(typeof(EHStreamProviderForMonitorTests).FullName, StreamProviderName, - (int)EHStreamProviderForMonitorTests.AdapterFactory.QueryCommands.GetCacheMonitorCallCounters, null); + var cacheMonitorCounters = await mgmtGrain.SendControlCommandToProvider(typeof(PersistentStreamProvider).FullName, StreamProviderName, + (int)EHStreamProviderForMonitorTestsAdapterFactory.QueryCommands.GetCacheMonitorCallCounters, null); foreach (var callCounter in cacheMonitorCounters) { AssertCacheMonitorCallCounters(callCounter as CacheMonitorCounters); } - var objectPoolMonitorCounters = await mgmtGrain.SendControlCommandToProvider(typeof(EHStreamProviderForMonitorTests).FullName, StreamProviderName, - (int)EHStreamProviderForMonitorTests.AdapterFactory.QueryCommands.GetObjectPoolMonitorCallCounters, null); + var objectPoolMonitorCounters = await mgmtGrain.SendControlCommandToProvider(typeof(PersistentStreamProvider).FullName, StreamProviderName, + (int)EHStreamProviderForMonitorTestsAdapterFactory.QueryCommands.GetObjectPoolMonitorCallCounters, null); foreach (var callCounter in objectPoolMonitorCounters) { AssertObjectPoolMonitorCallCounters(callCounter as ObjectPoolMonitorCounters); diff --git a/test/ServiceBus.Tests/Streaming/EHClientStreamTests.cs b/test/ServiceBus.Tests/Streaming/EHClientStreamTests.cs index 9aefb7aed30..b867c3187bd 100644 --- a/test/ServiceBus.Tests/Streaming/EHClientStreamTests.cs +++ b/test/ServiceBus.Tests/Streaming/EHClientStreamTests.cs @@ -1,11 +1,13 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.WindowsAzure.Storage.Table; +using Microsoft.Extensions.Configuration; using Orleans.Runtime; +using Orleans.Hosting; +using Orleans; +using Orleans.Configuration; using Orleans.Runtime.Configuration; -using Orleans.ServiceBus.Providers; using Orleans.Streaming.EventHubs; using Orleans.TestingHost; using Tester.TestStreamProviders; @@ -27,19 +29,6 @@ public class EHClientStreamTests : TestClusterPerTest private const string EHCheckpointTable = "ehcheckpoint"; private static readonly string CheckpointNamespace = Guid.NewGuid().ToString(); - private static readonly Lazy EventHubConfig = new Lazy(() => - new EventHubSettings( - TestDefaultConfiguration.EventHubConnectionString, - EHConsumerGroup, EHPath)); - - private static readonly EventHubStreamProviderSettings ProviderSettings = - new EventHubStreamProviderSettings(StreamProviderName); - - private static readonly EventHubCheckpointerSettings CheckpointerSettings = - new EventHubCheckpointerSettings(TestDefaultConfiguration.DataConnectionString, EHCheckpointTable, - CheckpointNamespace, - TimeSpan.FromSeconds(10)); - private readonly ITestOutputHelper output; private readonly ClientStreamTestRunner runner; public EHClientStreamTests(ITestOutputHelper output) @@ -53,14 +42,49 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) builder.ConfigureLegacyConfiguration(legacy => { AdjustConfig(legacy.ClusterConfiguration); - AdjustConfig(legacy.ClientConfiguration); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddPersistentStreams(StreamProviderName, TestEventHubStreamAdapterFactory.Create, + options => + { + options.ConnectionString = TestDefaultConfiguration.EventHubConnectionString; + options.ConsumerGroup = EHConsumerGroup; + options.Path = EHPath; + options.CheckpointConnectionString = TestDefaultConfiguration.DataConnectionString; + options.CheckpointTableName = EHCheckpointTable; + options.CheckpointNamespace = CheckpointNamespace; + options.CheckpointPersistInterval = TimeSpan.FromSeconds(10); + }); + } + } + + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddPersistentStreams(StreamProviderName, TestEventHubStreamAdapterFactory.Create, + options => + { + options.ConnectionString = TestDefaultConfiguration.EventHubConnectionString; + options.ConsumerGroup = EHConsumerGroup; + options.Path = EHPath; + }); + } } public override void Dispose() { base.Dispose(); - var dataManager = new AzureTableDataManager(CheckpointerSettings.TableName, CheckpointerSettings.DataConnectionString, NullLoggerFactory.Instance); + var dataManager = new AzureTableDataManager(EHCheckpointTable, TestDefaultConfiguration.DataConnectionString, NullLoggerFactory.Instance); dataManager.InitTableAsync().Wait(); dataManager.ClearTableAsync().Wait(); TestAzureTableStorageStreamFailureHandler.DeleteAll().Wait(); @@ -85,23 +109,7 @@ private static void AdjustConfig(ClusterConfiguration config) { // register stream provider config.AddMemoryStorageProvider("PubSubStore"); - config.Globals.RegisterStreamProvider(StreamProviderName, BuildProviderSettings()); config.Globals.ClientDropTimeout = TimeSpan.FromSeconds(5); } - - private static void AdjustConfig(ClientConfiguration config) - { - config.RegisterStreamProvider(StreamProviderName, BuildProviderSettings()); - } - - private static Dictionary BuildProviderSettings() - { - var settings = new Dictionary(); - // get initial settings from configs - ProviderSettings.WriteProperties(settings); - EventHubConfig.Value.WriteProperties(settings); - CheckpointerSettings.WriteProperties(settings); - return settings; - } } } diff --git a/test/ServiceBus.Tests/Streaming/EHImplicitSubscriptionStreamRecoveryTests.cs b/test/ServiceBus.Tests/Streaming/EHImplicitSubscriptionStreamRecoveryTests.cs index a95259486f7..ce44f84cd60 100644 --- a/test/ServiceBus.Tests/Streaming/EHImplicitSubscriptionStreamRecoveryTests.cs +++ b/test/ServiceBus.Tests/Streaming/EHImplicitSubscriptionStreamRecoveryTests.cs @@ -16,6 +16,9 @@ using Xunit; using Microsoft.WindowsAzure.Storage.Table; using Microsoft.Extensions.Logging.Abstractions; +using Orleans.Hosting; +using Orleans; +using Microsoft.Extensions.Configuration; namespace ServiceBus.Tests.StreamingTests { @@ -29,18 +32,6 @@ public class EHImplicitSubscriptionStreamRecoveryTests : OrleansTestingBase, ICl private const string EHCheckpointTable = "ehcheckpoint"; private static readonly string CheckpointNamespace = Guid.NewGuid().ToString(); - private static readonly Lazy EventHubConfig = new Lazy(() => - new EventHubSettings( - TestDefaultConfiguration.EventHubConnectionString, - EHConsumerGroup, EHPath)); - - private static readonly EventHubCheckpointerSettings CheckpointerSettings = - new EventHubCheckpointerSettings(TestDefaultConfiguration.DataConnectionString, - EHCheckpointTable, CheckpointNamespace, TimeSpan.FromSeconds(1)); - - private static readonly EventHubStreamProviderSettings ProviderSettings = - new EventHubStreamProviderSettings(StreamProviderName); - private readonly ImplicitSubscritionRecoverableStreamTestRunner runner; public class Fixture : BaseTestClusterFixture @@ -54,34 +45,52 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) { // register stream provider legacy.ClusterConfiguration.AddMemoryStorageProvider("Default"); - legacy.ClusterConfiguration.Globals.RegisterStreamProvider(StreamProviderName, BuildProviderSettings()); - legacy.ClientConfiguration.RegisterStreamProvider(StreamProviderName, BuildProviderSettings()); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); } public override void Dispose() { base.Dispose(); - var dataManager = new AzureTableDataManager(CheckpointerSettings.TableName, CheckpointerSettings.DataConnectionString, NullLoggerFactory.Instance); + var dataManager = new AzureTableDataManager(EHCheckpointTable, TestDefaultConfiguration.DataConnectionString, NullLoggerFactory.Instance); dataManager.InitTableAsync().Wait(); dataManager.ClearTableAsync().Wait(); } - private static Dictionary BuildProviderSettings() + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator { - var settings = new Dictionary(); - - // get initial settings from configs - ProviderSettings.WriteProperties(settings); - EventHubConfig.Value.WriteProperties(settings); - CheckpointerSettings.WriteProperties(settings); - - // add queue balancer setting - settings.Add(PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.AssemblyQualifiedName); + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddEventHubStreams(StreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.EventHubConnectionString; + options.ConsumerGroup = EHConsumerGroup; + options.Path = EHPath; + options.BalancerType = StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer; + options.PubSubType = StreamPubSubType.ImplicitOnly; + options.CheckpointConnectionString = TestDefaultConfiguration.DataConnectionString; + options.CheckpointTableName = EHCheckpointTable; + options.CheckpointNamespace = CheckpointNamespace; + options.CheckpointPersistInterval = TimeSpan.FromSeconds(1); + }); + } + } - // add pub/sub settting - settings.Add(PersistentStreamProviderConfig.STREAM_PUBSUB_TYPE, StreamPubSubType.ImplicitOnly.ToString()); - return settings; + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder.AddEventHubStreams(StreamProviderName, options => + { + options.ConnectionString = TestDefaultConfiguration.EventHubConnectionString; + options.ConsumerGroup = EHConsumerGroup; + options.Path = EHPath; + options.PubSubType = StreamPubSubType.ImplicitOnly; + }); + } } } diff --git a/test/ServiceBus.Tests/Streaming/EHProgrammaticSubscribeTests.cs b/test/ServiceBus.Tests/Streaming/EHProgrammaticSubscribeTests.cs index f073d43f667..a010c521f8b 100644 --- a/test/ServiceBus.Tests/Streaming/EHProgrammaticSubscribeTests.cs +++ b/test/ServiceBus.Tests/Streaming/EHProgrammaticSubscribeTests.cs @@ -1,9 +1,8 @@ using System; -using System.Collections.Generic; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.WindowsAzure.Storage.Table; +using Orleans.Hosting; using Orleans.Runtime.Configuration; -using Orleans.ServiceBus.Providers; using Orleans.Storage; using Orleans.Streaming.EventHubs; using Orleans.TestingHost; @@ -22,22 +21,7 @@ public class EHProgrammaticSubscribeTest : ProgrammaticSubcribeTestsRunner, ICla private const string EHConsumerGroup = "orleansnightly"; private const string EHCheckpointTable = "ehcheckpoint"; private static readonly string CheckpointNamespace = Guid.NewGuid().ToString(); - - private static readonly Lazy EventHubConfig = new Lazy(() => - new EventHubSettings( - TestDefaultConfiguration.EventHubConnectionString, - EHConsumerGroup, EHPath)); - - private static readonly EventHubStreamProviderSettings ProviderSettings = - new EventHubStreamProviderSettings(StreamProviderName); - - private static readonly EventHubCheckpointerSettings CheckpointerSettings = - new EventHubCheckpointerSettings(TestDefaultConfiguration.DataConnectionString, EHCheckpointTable, - CheckpointNamespace, - TimeSpan.FromSeconds(10)); - - public static readonly EventHubStreamProviderSettings ProviderSettings2 = - new EventHubStreamProviderSettings(StreamProviderName2); + private static readonly string CheckpointNamespace2 = Guid.NewGuid().ToString(); public class Fixture : BaseTestClusterFixture { @@ -47,34 +31,51 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) { AdjustClusterConfiguration(legacy.ClusterConfiguration); }); - } - - private static Dictionary BuildProviderSettings(EventHubStreamProviderSettings providerSettings) - { - var settings = new Dictionary(); - // get initial settings from configs - providerSettings.WriteProperties(settings); - EventHubConfig.Value.WriteProperties(settings); - CheckpointerSettings.WriteProperties(settings); - return settings; + builder.AddSiloBuilderConfigurator(); } private static void AdjustClusterConfiguration(ClusterConfiguration config) { - // register stream provider - config.Globals.RegisterStreamProvider(StreamProviderName, BuildProviderSettings(ProviderSettings)); - config.Globals.RegisterStreamProvider(StreamProviderName2, BuildProviderSettings(ProviderSettings2)); config.Globals.RegisterStorageProvider("PubSubStore"); } public override void Dispose() { base.Dispose(); - var dataManager = new AzureTableDataManager(CheckpointerSettings.TableName, CheckpointerSettings.DataConnectionString, NullLoggerFactory.Instance); + var dataManager = new AzureTableDataManager(EHCheckpointTable, TestDefaultConfiguration.DataConnectionString, NullLoggerFactory.Instance); dataManager.InitTableAsync().Wait(); dataManager.ClearTableAsync().Wait(); TestAzureTableStorageStreamFailureHandler.DeleteAll().Wait(); } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddEventHubStreams(StreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.EventHubConnectionString; + options.ConsumerGroup = EHConsumerGroup; + options.Path = EHPath; + options.CheckpointConnectionString = TestDefaultConfiguration.DataConnectionString; + options.CheckpointTableName = EHCheckpointTable; + options.CheckpointNamespace = CheckpointNamespace; + options.CheckpointPersistInterval = TimeSpan.FromSeconds(10); + }) + .AddEventHubStreams(StreamProviderName2, options => + { + options.ConnectionString = TestDefaultConfiguration.EventHubConnectionString; + options.ConsumerGroup = EHConsumerGroup; + options.Path = EHPath; + options.CheckpointConnectionString = TestDefaultConfiguration.DataConnectionString; + options.CheckpointTableName = EHCheckpointTable; + options.CheckpointNamespace = CheckpointNamespace2; + options.CheckpointPersistInterval = TimeSpan.FromSeconds(10); + }); + } + } } public EHProgrammaticSubscribeTest(ITestOutputHelper output, Fixture fixture) diff --git a/test/ServiceBus.Tests/Streaming/EHStreamPerPartitionTests.cs b/test/ServiceBus.Tests/Streaming/EHStreamPerPartitionTests.cs index 2e48b3814d9..637e05f84e2 100644 --- a/test/ServiceBus.Tests/Streaming/EHStreamPerPartitionTests.cs +++ b/test/ServiceBus.Tests/Streaming/EHStreamPerPartitionTests.cs @@ -4,10 +4,13 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.WindowsAzure.Storage.Table; +using Microsoft.Extensions.Configuration; +using Orleans; +using Orleans.Hosting; +using Orleans.Configuration; using Orleans.Streaming.EventHubs; using Orleans.Runtime; using Orleans.Runtime.Configuration; -using Orleans.ServiceBus.Providers; using Orleans.Streams; using Orleans.TestingHost; using Orleans.TestingHost.Utils; @@ -28,18 +31,6 @@ public class EHStreamPerPartitionTests : OrleansTestingBase, IClassFixture EventHubConfig = new Lazy(() => - new EventHubSettings( - TestDefaultConfiguration.EventHubConnectionString, - EHConsumerGroup, EHPath)); - - private static readonly EventHubCheckpointerSettings CheckpointerSettings = - new EventHubCheckpointerSettings(TestDefaultConfiguration.DataConnectionString, - EHCheckpointTable, CheckpointNamespace, TimeSpan.FromSeconds(1)); - - private static readonly EventHubStreamProviderSettings ProviderSettings = - new EventHubStreamProviderSettings(StreamProviderName); - public class Fixture : BaseTestClusterFixture { protected override void ConfigureTestCluster(TestClusterBuilder builder) @@ -48,32 +39,52 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) { // register stream provider legacy.ClusterConfiguration.AddMemoryStorageProvider("PubSubStore"); - legacy.ClusterConfiguration.Globals.RegisterStreamProvider(StreamProviderName, BuildProviderSettings()); - legacy.ClientConfiguration.RegisterStreamProvider(StreamProviderName, BuildProviderSettings()); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); } - public override void Dispose() + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator { - base.Dispose(); - var dataManager = new AzureTableDataManager(CheckpointerSettings.TableName, CheckpointerSettings.DataConnectionString, NullLoggerFactory.Instance); - dataManager.InitTableAsync().Wait(); - dataManager.ClearTableAsync().Wait(); + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddPersistentStreams(StreamProviderName, StreamPerPartitionEventHubStreamAdapterFactory.Create, + options => + { + options.ConnectionString = TestDefaultConfiguration.EventHubConnectionString; + options.ConsumerGroup = EHConsumerGroup; + options.Path = EHPath; + options.BalancerType = StreamQueueBalancerType.StaticClusterConfigDeploymentBalancer; + options.CheckpointConnectionString = TestDefaultConfiguration.DataConnectionString; + options.CheckpointTableName = EHCheckpointTable; + options.CheckpointNamespace = CheckpointNamespace; + options.CheckpointPersistInterval = TimeSpan.FromSeconds(1); + }); + } } - private static Dictionary BuildProviderSettings() + private class MyClientBuilderConfigurator : IClientBuilderConfigurator { - var settings = new Dictionary(); - - // get initial settings from configs - ProviderSettings.WriteProperties(settings); - EventHubConfig.Value.WriteProperties(settings); - CheckpointerSettings.WriteProperties(settings); - - // add queue balancer setting - settings.Add(PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.StaticClusterConfigDeploymentBalancer.AssemblyQualifiedName); + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddPersistentStreams(StreamProviderName, StreamPerPartitionEventHubStreamAdapterFactory.Create, + options => + { + options.ConnectionString = TestDefaultConfiguration.EventHubConnectionString; + options.ConsumerGroup = EHConsumerGroup; + options.Path = EHPath; + }); + } + } - return settings; + public override void Dispose() + { + base.Dispose(); + var dataManager = new AzureTableDataManager(EHCheckpointTable, TestDefaultConfiguration.DataConnectionString, NullLoggerFactory.Instance); + dataManager.InitTableAsync().Wait(); + dataManager.ClearTableAsync().Wait(); } } @@ -99,7 +110,7 @@ public async Task EH100StreamsTo4PartitionStreamsTest() // subscribe to each partition List becomeConsumersTasks = consumers - .Select( (consumer, i) => consumer.BecomeConsumer( StreamPerPartitionEventHubStreamProvider.GetPartitionGuid(i.ToString()), null, StreamProviderName)) + .Select( (consumer, i) => consumer.BecomeConsumer(StreamPerPartitionEventHubStreamAdapterFactory.GetPartitionGuid(i.ToString()), null, StreamProviderName)) .ToList(); await Task.WhenAll(becomeConsumersTasks); diff --git a/test/ServiceBus.Tests/Streaming/EHStreamProviderCheckpointTests.cs b/test/ServiceBus.Tests/Streaming/EHStreamProviderCheckpointTests.cs index 37e5e4c6319..99ed45dae6c 100644 --- a/test/ServiceBus.Tests/Streaming/EHStreamProviderCheckpointTests.cs +++ b/test/ServiceBus.Tests/Streaming/EHStreamProviderCheckpointTests.cs @@ -2,12 +2,13 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.WindowsAzure.Storage.Table; using Orleans; using Orleans.Providers.Streams.Common; using Orleans.Providers.Streams.Generator; using Orleans.Runtime; -using Orleans.Runtime.Configuration; -using Orleans.ServiceBus.Providers; using Orleans.Streams; using Orleans.TestingHost; using Orleans.TestingHost.Utils; @@ -17,56 +18,68 @@ using TestGrains; using UnitTests.Grains; using Xunit; -using Microsoft.WindowsAzure.Storage.Table; -using Microsoft.Extensions.Logging.Abstractions; using Orleans.Hosting; -using Orleans.Storage; +using Orleans.Configuration; namespace ServiceBus.Tests.StreamingTests { [TestCategory("EventHub"), TestCategory("Streaming")] public class EHStreamProviderCheckpointTests : TestClusterPerTest { - private static readonly string StreamProviderTypeName = typeof(EventHubStreamProvider).FullName; + private static readonly string StreamProviderTypeName = typeof(PersistentStreamProvider).FullName; private const string StreamProviderName = GeneratedStreamTestConstants.StreamProviderName; private const string EHPath = "ehorleanstest"; private const string EHConsumerGroup = "orleansnightly"; private const string EHCheckpointTable = "ehcheckpoint"; private static readonly string CheckpointNamespace = Guid.NewGuid().ToString(); - private static readonly Lazy EventHubConfig = new Lazy(() => - new EventHubSettings( - TestDefaultConfiguration.EventHubConnectionString, - EHConsumerGroup, EHPath)); - - private static readonly EventHubCheckpointerSettings CheckpointerSettings = - new EventHubCheckpointerSettings(TestDefaultConfiguration.DataConnectionString, - EHCheckpointTable, CheckpointNamespace, TimeSpan.FromSeconds(1)); - - private static readonly EventHubStreamProviderSettings ProviderSettings = - new EventHubStreamProviderSettings(StreamProviderName); + protected override void ConfigureTestCluster(TestClusterBuilder builder) + { + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); + } - private class SiloBuilderConfigurator : ISiloBuilderConfigurator + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator { public void Configure(ISiloHostBuilder hostBuilder) { - hostBuilder.AddAzureBlobGrainStorage( + hostBuilder + .AddAzureBlobGrainStorage( ImplicitSubscription_RecoverableStream_CollectorGrain.StorageProviderName, (AzureBlobStorageOptions options) => { options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }) + .AddEventHubStreams(StreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.EventHubConnectionString; + options.ConsumerGroup = EHConsumerGroup; + options.Path = EHPath; + options.BalancerType = StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer; + options.PubSubType = StreamPubSubType.ImplicitOnly; + options.CheckpointConnectionString = TestDefaultConfiguration.DataConnectionString; + options.CheckpointTableName = EHCheckpointTable; + options.CheckpointNamespace = CheckpointNamespace; + options.CheckpointPersistInterval = TimeSpan.FromSeconds(1); }); } } - protected override void ConfigureTestCluster(TestClusterBuilder builder) + private class MyClientBuilderConfigurator : IClientBuilderConfigurator { - builder.AddSiloBuilderConfigurator(); - builder.ConfigureLegacyConfiguration(legacy => + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) { - AdjustConfig(legacy.ClusterConfiguration); - AdjustConfig(legacy.ClientConfiguration); - }); + clientBuilder + .AddEventHubStreams(StreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.EventHubConnectionString; + options.ConsumerGroup = EHConsumerGroup; + options.Path = EHPath; + options.PubSubType = StreamPubSubType.ImplicitOnly; + }); + } } [Fact] @@ -85,7 +98,7 @@ public async Task RestartSiloAfterCheckpointTest() public override void Dispose() { - var dataManager = new AzureTableDataManager(CheckpointerSettings.TableName, CheckpointerSettings.DataConnectionString, NullLoggerFactory.Instance); + var dataManager = new AzureTableDataManager(EHCheckpointTable, TestDefaultConfiguration.EventHubConnectionString, NullLoggerFactory.Instance); dataManager.InitTableAsync().Wait(); dataManager.ClearTableAsync().Wait(); base.Dispose(); @@ -183,33 +196,5 @@ private async Task GenerateEvents(string streamNamespace, List streamGuids await producers[j].OnNextAsync(new GeneratedEvent { EventType = GeneratedEvent.GeneratedEventType.Report, Payload = new int[payloadSize] }); } } - - private static void AdjustConfig(ClusterConfiguration config) - { - // register stream provider - config.Globals.RegisterStreamProvider(StreamProviderName, BuildProviderSettings()); - } - - private static void AdjustConfig(ClientConfiguration config) - { - config.RegisterStreamProvider(StreamProviderName, BuildProviderSettings()); - } - - private static Dictionary BuildProviderSettings() - { - var settings = new Dictionary(); - - // get initial settings from configs - ProviderSettings.WriteProperties(settings); - EventHubConfig.Value.WriteProperties(settings); - CheckpointerSettings.WriteProperties(settings); - - // add queue balancer setting - settings.Add(PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.AssemblyQualifiedName); - - // add pub/sub settting - settings.Add(PersistentStreamProviderConfig.STREAM_PUBSUB_TYPE, StreamPubSubType.ImplicitOnly.ToString()); - return settings; - } } } diff --git a/test/ServiceBus.Tests/Streaming/EHSubscriptionMultiplicityTests.cs b/test/ServiceBus.Tests/Streaming/EHSubscriptionMultiplicityTests.cs index 606c4936eb5..d7660c5abde 100644 --- a/test/ServiceBus.Tests/Streaming/EHSubscriptionMultiplicityTests.cs +++ b/test/ServiceBus.Tests/Streaming/EHSubscriptionMultiplicityTests.cs @@ -13,6 +13,7 @@ using TestExtensions; using UnitTests.StreamingTests; using Xunit; +using Orleans.Hosting; namespace ServiceBus.Tests.StreamingTests { @@ -25,18 +26,6 @@ public class EHSubscriptionMultiplicityTests : OrleansTestingBase, IClassFixture private const string EHCheckpointTable = "ehcheckpoint"; private static readonly string CheckpointNamespace = Guid.NewGuid().ToString(); - public static readonly EventHubStreamProviderSettings ProviderSettings = - new EventHubStreamProviderSettings(StreamProviderName); - - private static readonly Lazy EventHubConfig = new Lazy(() => - new EventHubSettings( - TestDefaultConfiguration.EventHubConnectionString, - EHConsumerGroup, EHPath)); - - private static readonly EventHubCheckpointerSettings CheckpointerSettings = - new EventHubCheckpointerSettings(TestDefaultConfiguration.DataConnectionString, - EHCheckpointTable, CheckpointNamespace, TimeSpan.FromSeconds(1)); - private readonly SubscriptionMultiplicityTestRunner runner; private readonly Fixture fixture; @@ -53,24 +42,33 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) public override void Dispose() { base.Dispose(); - var dataManager = new AzureTableDataManager(CheckpointerSettings.TableName, CheckpointerSettings.DataConnectionString, NullLoggerFactory.Instance); + var dataManager = new AzureTableDataManager(EHCheckpointTable, TestDefaultConfiguration.DataConnectionString, NullLoggerFactory.Instance); dataManager.InitTableAsync().Wait(); dataManager.ClearTableAsync().Wait(); } - private static void AdjustClusterConfiguration(ClusterConfiguration config) + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator { - var settings = new Dictionary(); - // get initial settings from configs - ProviderSettings.WriteProperties(settings); - EventHubConfig.Value.WriteProperties(settings); - CheckpointerSettings.WriteProperties(settings); - - // add queue balancer setting - settings.Add(PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.AssemblyQualifiedName); + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddEventHubStreams(StreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.EventHubConnectionString; + options.ConsumerGroup = EHConsumerGroup; + options.Path = EHPath; + options.BalancerType = StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer; + options.CheckpointConnectionString = TestDefaultConfiguration.DataConnectionString; + options.CheckpointTableName = EHCheckpointTable; + options.CheckpointNamespace = CheckpointNamespace; + options.CheckpointPersistInterval = TimeSpan.FromSeconds(1); + }); + } + } - // register stream provider - config.Globals.RegisterStreamProvider(StreamProviderName, settings); + private static void AdjustClusterConfiguration(ClusterConfiguration config) + { config.Globals.RegisterStorageProvider("PubSubStore"); } } diff --git a/test/ServiceBus.Tests/TestStreamProviders/EHStreamProviderForMonitorTests.cs b/test/ServiceBus.Tests/TestStreamProviders/EHStreamProviderForMonitorTests.cs index 7446bc80fa7..eab0a5cccdf 100644 --- a/test/ServiceBus.Tests/TestStreamProviders/EHStreamProviderForMonitorTests.cs +++ b/test/ServiceBus.Tests/TestStreamProviders/EHStreamProviderForMonitorTests.cs @@ -1,103 +1,106 @@ -using Orleans.Providers; +using System; +using System.Threading.Tasks; using Orleans.Providers.Streams.Common; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Logging; using Orleans.Runtime; using Orleans.ServiceBus.Providers; -using Microsoft.Extensions.DependencyInjection; using Orleans.ServiceBus.Providers.Testing; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Orleans; using Orleans.Serialization; -using Orleans.Streams; -using Orleans.Runtime.Configuration; -using System.Threading; -using Microsoft.Azure.EventHubs; -using Microsoft.Extensions.Logging; +using Orleans.Configuration; using ServiceBus.Tests.MonitorTests; namespace ServiceBus.Tests.TestStreamProviders { - public class EHStreamProviderForMonitorTests : PersistentStreamProvider + public class EHStreamProviderForMonitorTestsAdapterFactory : EventDataGeneratorAdapterFactory { - public class AdapterFactory : EventDataGeneratorStreamProvider.AdapterFactory + private CachePressureInjectionMonitor cachePressureInjectionMonitor; + + public EHStreamProviderForMonitorTestsAdapterFactory(string name, EventDataGeneratorStreamOptions options, IServiceProvider serviceProvider, SerializationManager serializationManager, ITelemetryProducer telemetryProducer, ILoggerFactory loggerFactory) + : base(name, options, serviceProvider, serializationManager, telemetryProducer, loggerFactory) { - private CachePressureInjectionMonitor cachePressureInjectionMonitor; + } - public override void Init(IProviderConfiguration providerCfg, string providerName, IServiceProvider svcProvider) - { - this.ReceiverMonitorFactory = (dimensions, logger, telemetryProducer) => EventHubReceiverMonitorForTesting.Instance; - this.cachePressureInjectionMonitor = new CachePressureInjectionMonitor(); - base.Init(providerCfg, providerName, svcProvider); - } + public override void Init() + { + this.ReceiverMonitorFactory = (dimensions, logger, telemetryProducer) => EventHubReceiverMonitorForTesting.Instance; + this.cachePressureInjectionMonitor = new CachePressureInjectionMonitor(); + base.Init(); + } - private void ChangeCachePressure() - { - this.cachePressureInjectionMonitor.UnderPressure = !this.cachePressureInjectionMonitor.UnderPressure; - } + private void ChangeCachePressure() + { + this.cachePressureInjectionMonitor.UnderPressure = !this.cachePressureInjectionMonitor.UnderPressure; + } - protected override IEventHubQueueCacheFactory CreateCacheFactory(EventHubStreamProviderSettings providerSettings) - { - var loggerFactory = this.serviceProvider.GetRequiredService(); - var eventHubPath = this.hubSettings.Path; - var sharedDimensions = new EventHubMonitorAggregationDimensions(eventHubPath); - Func cacheMonitorFactory = (dimensions, logger, telemetryProducer) => CacheMonitorForTesting.Instance; - Func blockPoolMonitorFactory = (dimensions, logger, telemetryProducer) =>BlockPoolMonitorForTesting.Instance; - return new CacheFactoryForMonitorTesting(this.cachePressureInjectionMonitor, providerSettings, this.SerializationManager, - sharedDimensions, loggerFactory, cacheMonitorFactory, blockPoolMonitorFactory); - } + protected override IEventHubQueueCacheFactory CreateCacheFactory(EventHubStreamOptions options) + { + var loggerFactory = this.serviceProvider.GetRequiredService(); + var eventHubPath = options.Path; + var sharedDimensions = new EventHubMonitorAggregationDimensions(eventHubPath); + Func cacheMonitorFactory = (dimensions, logger, telemetryProducer) => CacheMonitorForTesting.Instance; + Func blockPoolMonitorFactory = (dimensions, logger, telemetryProducer) =>BlockPoolMonitorForTesting.Instance; + return new CacheFactoryForMonitorTesting(this.cachePressureInjectionMonitor, options, this.SerializationManager, + sharedDimensions, loggerFactory, cacheMonitorFactory, blockPoolMonitorFactory); + } - private class CacheFactoryForMonitorTesting : EventHubQueueCacheFactory + private class CacheFactoryForMonitorTesting : EventHubQueueCacheFactory + { + private CachePressureInjectionMonitor cachePressureInjectionMonitor; + public CacheFactoryForMonitorTesting(CachePressureInjectionMonitor cachePressureInjectionMonitor, EventHubStreamOptions options, + SerializationManager serializationManager, EventHubMonitorAggregationDimensions sharedDimensions, + ILoggerFactory loggerFactory, + Func cacheMonitorFactory = null, + Func blockPoolMonitorFactory = null) + : base(options, serializationManager, sharedDimensions, loggerFactory, cacheMonitorFactory, blockPoolMonitorFactory) { - private CachePressureInjectionMonitor cachePressureInjectionMonitor; - public CacheFactoryForMonitorTesting(CachePressureInjectionMonitor cachePressureInjectionMonitor, EventHubStreamProviderSettings providerSettings, - SerializationManager serializationManager, EventHubMonitorAggregationDimensions sharedDimensions, - ILoggerFactory loggerFactory, - Func cacheMonitorFactory = null, - Func blockPoolMonitorFactory = null) - : base(providerSettings, serializationManager, sharedDimensions, loggerFactory, cacheMonitorFactory, blockPoolMonitorFactory) - { - this.cachePressureInjectionMonitor = cachePressureInjectionMonitor; - } - - protected override void AddCachePressureMonitors(IEventHubQueueCache cache, EventHubStreamProviderSettings providerSettings, - ILogger cacheLogger) - { - cache.AddCachePressureMonitor(this.cachePressureInjectionMonitor); - } + this.cachePressureInjectionMonitor = cachePressureInjectionMonitor; } - public enum QueryCommands + + protected override void AddCachePressureMonitors(IEventHubQueueCache cache, EventHubStreamOptions options, + ILogger cacheLogger) { - GetCacheMonitorCallCounters = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 10, - GetReceiverMonitorCallCounters = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 11, - GetObjectPoolMonitorCallCounters = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 12, - ChangeCachePressure = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 13 + cache.AddCachePressureMonitor(this.cachePressureInjectionMonitor); } + } + public enum QueryCommands + { + GetCacheMonitorCallCounters = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 10, + GetReceiverMonitorCallCounters = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 11, + GetObjectPoolMonitorCallCounters = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 12, + ChangeCachePressure = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 13 + } - public override Task ExecuteCommand(int command, object arg) + public override Task ExecuteCommand(int command, object arg) + { + object re = null; + switch (command) { - object re = null; - switch (command) - { - case (int)QueryCommands.GetCacheMonitorCallCounters: - re = CacheMonitorForTesting.Instance.CallCounters; - break; - case (int)QueryCommands.GetReceiverMonitorCallCounters: - re = EventHubReceiverMonitorForTesting.Instance.CallCounters; - break; - case (int)QueryCommands.GetObjectPoolMonitorCallCounters: - re = BlockPoolMonitorForTesting.Instance.CallCounters; - break; - case (int)QueryCommands.ChangeCachePressure: - ChangeCachePressure(); - break; - default: return base.ExecuteCommand(command, arg); + case (int)QueryCommands.GetCacheMonitorCallCounters: + re = CacheMonitorForTesting.Instance.CallCounters; + break; + case (int)QueryCommands.GetReceiverMonitorCallCounters: + re = EventHubReceiverMonitorForTesting.Instance.CallCounters; + break; + case (int)QueryCommands.GetObjectPoolMonitorCallCounters: + re = BlockPoolMonitorForTesting.Instance.CallCounters; + break; + case (int)QueryCommands.ChangeCachePressure: + ChangeCachePressure(); + break; + default: return base.ExecuteCommand(command, arg); - } - return Task.FromResult(re); } + return Task.FromResult(re); + } + + public new static EHStreamProviderForMonitorTestsAdapterFactory Create(IServiceProvider services, string name) + { + IOptionsSnapshot streamOptionsSnapshot = services.GetRequiredService>(); + var factory = ActivatorUtilities.CreateInstance(services, name, streamOptionsSnapshot.Get(name)); + factory.Init(); + return factory; } } diff --git a/test/ServiceBus.Tests/TestStreamProviders/EHStreamProviderWithCreatedCacheList.cs b/test/ServiceBus.Tests/TestStreamProviders/EHStreamProviderWithCreatedCacheList.cs index 5ec79b272dd..566d25e660a 100644 --- a/test/ServiceBus.Tests/TestStreamProviders/EHStreamProviderWithCreatedCacheList.cs +++ b/test/ServiceBus.Tests/TestStreamProviders/EHStreamProviderWithCreatedCacheList.cs @@ -1,108 +1,116 @@ using System; -using Orleans.Providers; +using System.Threading.Tasks; +using System.Collections.Concurrent; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Microsoft.Azure.EventHubs; using Orleans.Providers.Streams.Common; using Orleans.Runtime; using Orleans.Serialization; using Orleans.ServiceBus.Providers; using Orleans.Streams; -using System.Collections.Generic; -using System.Threading.Tasks; using Orleans.ServiceBus.Providers.Testing; -using Microsoft.Extensions.DependencyInjection; -using Orleans.Runtime.Configuration; -using Microsoft.Azure.EventHubs; -using System.Collections.Concurrent; -using System.Linq; -using Microsoft.Extensions.Logging; +using Orleans.Configuration; namespace ServiceBus.Tests.TestStreamProviders { - public class EHStreamProviderWithCreatedCacheList : PersistentStreamProvider + public class EHStreamProviderWithCreatedCacheListAdapterFactory : EventDataGeneratorAdapterFactory { - public class AdapterFactory : EventDataGeneratorStreamProvider.AdapterFactory + private readonly ConcurrentBag createdCaches = new ConcurrentBag(); + + public EHStreamProviderWithCreatedCacheListAdapterFactory(string name, EventDataGeneratorStreamOptions options, IServiceProvider serviceProvider, SerializationManager serializationManager, ITelemetryProducer telemetryProducer, ILoggerFactory loggerFactory) + : base(name, options, serviceProvider, serializationManager, telemetryProducer, loggerFactory) + { - private readonly ConcurrentBag createdCaches = new ConcurrentBag(); + this.createdCaches = new ConcurrentBag(); + } - public AdapterFactory() - { - this.createdCaches = new ConcurrentBag(); - } + protected override IEventHubQueueCacheFactory CreateCacheFactory(EventHubStreamOptions options) + { + var eventHubPath = options.Path; + var sharedDimensions = new EventHubMonitorAggregationDimensions(eventHubPath); + return new CacheFactoryForTesting(this.Name, options, this.SerializationManager, this.createdCaches, sharedDimensions, this.serviceProvider.GetRequiredService()); + } + + private class CacheFactoryForTesting : EventHubQueueCacheFactory + { + private readonly ConcurrentBag caches; + private readonly string name; - protected override IEventHubQueueCacheFactory CreateCacheFactory(EventHubStreamProviderSettings providerSettings) + public CacheFactoryForTesting(string name, EventHubStreamOptions options, + SerializationManager serializationManager, ConcurrentBag caches, EventHubMonitorAggregationDimensions sharedDimensions, + ILoggerFactory loggerFactory, + Func cacheMonitorFactory = null, + Func blockPoolMonitorFactory = null) + : base(options, serializationManager, sharedDimensions, loggerFactory, cacheMonitorFactory, blockPoolMonitorFactory) { - var eventHubPath = this.hubSettings.Path; - var sharedDimensions = new EventHubMonitorAggregationDimensions(eventHubPath); - return new CacheFactoryForTesting(providerSettings, this.SerializationManager, this.createdCaches, sharedDimensions, this.serviceProvider.GetRequiredService()); + this.name = name; + this.caches = caches; } - private class CacheFactoryForTesting : EventHubQueueCacheFactory + private const int DefaultMaxAddCount = 10; + protected override IEventHubQueueCache CreateCache(string partition, EventHubStreamOptions options, IStreamQueueCheckpointer checkpointer, + ILoggerFactory loggerFactory, IObjectPool bufferPool, string blockPoolId, TimePurgePredicate timePurge, + SerializationManager serializationManager, EventHubMonitorAggregationDimensions sharedDimensions, ITelemetryProducer telemetryProducer) { - private readonly ConcurrentBag caches; + var cacheMonitorDimensions = new EventHubCacheMonitorDimensions(sharedDimensions, partition, blockPoolId); + var cacheMonitor = this.CacheMonitorFactory(cacheMonitorDimensions, loggerFactory, telemetryProducer); + var cacheLogger = loggerFactory.CreateLogger($"{typeof(EventHubQueueCache).FullName}.{this.name}.{partition}"); + //set defaultMaxAddCount to 10 so TryCalculateCachePressureContribution will start to calculate real contribution shortly + var cache = new QueueCacheForTesting(DefaultMaxAddCount, checkpointer, new EventHubDataAdapter(serializationManager, bufferPool), + EventHubDataComparer.Instance, cacheLogger, new EventHubCacheEvictionStrategy(cacheLogger, timePurge, cacheMonitor, options.StatisticMonitorWriteInterval), + cacheMonitor, options.StatisticMonitorWriteInterval); + this.caches.Add(cache); + return cache; + } + } - public CacheFactoryForTesting(EventHubStreamProviderSettings providerSettings, - SerializationManager serializationManager, ConcurrentBag caches, EventHubMonitorAggregationDimensions sharedDimensions, - ILoggerFactory loggerFactory, - Func cacheMonitorFactory = null, - Func blockPoolMonitorFactory = null) - : base(providerSettings, serializationManager, sharedDimensions, loggerFactory, cacheMonitorFactory, blockPoolMonitorFactory) - { - this.caches = caches; - } + private class QueueCacheForTesting : EventHubQueueCache, IQueueFlowController + { + public bool IsUnderPressure { get; private set; } - private const int DefaultMaxAddCount = 10; - protected override IEventHubQueueCache CreateCache(string partition, EventHubStreamProviderSettings providerSettings, IStreamQueueCheckpointer checkpointer, - ILoggerFactory loggerFactory, IObjectPool bufferPool, string blockPoolId, TimePurgePredicate timePurge, - SerializationManager serializationManager, EventHubMonitorAggregationDimensions sharedDimensions, ITelemetryProducer telemetryProducer) - { - var cacheMonitorDimensions = new EventHubCacheMonitorDimensions(sharedDimensions, partition, blockPoolId); - var cacheMonitor = this.CacheMonitorFactory(cacheMonitorDimensions, loggerFactory, telemetryProducer); - var cacheLogger = loggerFactory.CreateLogger($"{typeof(EventHubQueueCache).FullName}.{providerSettings.StreamProviderName}.{partition}"); - //set defaultMaxAddCount to 10 so TryCalculateCachePressureContribution will start to calculate real contribution shortly - var cache = new QueueCacheForTesting(DefaultMaxAddCount, checkpointer, new EventHubDataAdapter(serializationManager, bufferPool), - EventHubDataComparer.Instance, cacheLogger, new EventHubCacheEvictionStrategy(cacheLogger, timePurge, cacheMonitor, providerSettings.StatisticMonitorWriteInterval), - cacheMonitor, providerSettings.StatisticMonitorWriteInterval); - this.caches.Add(cache); - return cache; - } + public QueueCacheForTesting(int defaultMaxAddCount, IStreamQueueCheckpointer checkpointer, ICacheDataAdapter cacheDataAdapter, + ICacheDataComparer comparer, ILogger logger, IEvictionStrategy evictionStrategy, + ICacheMonitor cacheMonitor, TimeSpan? cacheMonitorWriteInterval) + : base(defaultMaxAddCount, checkpointer, cacheDataAdapter, comparer, logger, evictionStrategy, cacheMonitor, cacheMonitorWriteInterval) + { } - private class QueueCacheForTesting : EventHubQueueCache, IQueueFlowController + int IQueueFlowController.GetMaxAddCount() { - public bool IsUnderPressure { get; private set; } - - public QueueCacheForTesting(int defaultMaxAddCount, IStreamQueueCheckpointer checkpointer, ICacheDataAdapter cacheDataAdapter, - ICacheDataComparer comparer, ILogger logger, IEvictionStrategy evictionStrategy, - ICacheMonitor cacheMonitor, TimeSpan? cacheMonitorWriteInterval) - : base(defaultMaxAddCount, checkpointer, cacheDataAdapter, comparer, logger, evictionStrategy, cacheMonitor, cacheMonitorWriteInterval) - { - } - - int IQueueFlowController.GetMaxAddCount() - { - int maxAddCount = base.GetMaxAddCount(); - this.IsUnderPressure = maxAddCount <= 0; - return maxAddCount; - } + int maxAddCount = base.GetMaxAddCount(); + this.IsUnderPressure = maxAddCount <= 0; + return maxAddCount; } + } - public const int IsCacheBackPressureTriggeredCommand = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 3; + public const int IsCacheBackPressureTriggeredCommand = (int)PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 3; - /// - /// Only command expecting: determine whether back pressure algorithm on any of the created caches - /// is triggered. - /// - /// - /// - /// - public override Task ExecuteCommand(int command, object arg) + /// + /// Only command expecting: determine whether back pressure algorithm on any of the created caches + /// is triggered. + /// + /// + /// + /// + public override Task ExecuteCommand(int command, object arg) + { + switch (command) { - switch (command) - { - case IsCacheBackPressureTriggeredCommand: - return Task.FromResult(this.createdCaches.Any(cache => cache.IsUnderPressure)); - default: return base.ExecuteCommand(command, arg); - } + case IsCacheBackPressureTriggeredCommand: + return Task.FromResult(this.createdCaches.Any(cache => cache.IsUnderPressure)); + default: return base.ExecuteCommand(command, arg); } } + + public new static EHStreamProviderWithCreatedCacheListAdapterFactory Create(IServiceProvider services, string name) + { + IOptionsSnapshot streamOptionsSnapshot = services.GetRequiredService>(); + var factory = ActivatorUtilities.CreateInstance(services, name, streamOptionsSnapshot.Get(name)); + factory.Init(); + return factory; + } } } \ No newline at end of file diff --git a/test/ServiceBus.Tests/TestStreamProviders/StreamPerPartitionEventHubStreamProvider.cs b/test/ServiceBus.Tests/TestStreamProviders/StreamPerPartitionEventHubStreamProvider.cs index 2da8f47494b..e6f1b89ae14 100644 --- a/test/ServiceBus.Tests/TestStreamProviders/StreamPerPartitionEventHubStreamProvider.cs +++ b/test/ServiceBus.Tests/TestStreamProviders/StreamPerPartitionEventHubStreamProvider.cs @@ -1,7 +1,10 @@ using System; using System.Text; using Microsoft.Azure.EventHubs; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Orleans.Configuration; using Orleans.Providers.Streams.Common; using Orleans.Runtime; using Orleans.Serialization; @@ -13,37 +16,16 @@ namespace ServiceBus.Tests.TestStreamProviders.EventHub { [Collection(TestEnvironmentFixture.DefaultCollection)] - public class StreamPerPartitionEventHubStreamProvider : PersistentStreamProvider + public class StreamPerPartitionEventHubStreamAdapterFactory : EventHubAdapterFactory { - private class CacheFactory : IEventHubQueueCacheFactory + public StreamPerPartitionEventHubStreamAdapterFactory(string name, EventHubStreamOptions options, IServiceProvider serviceProvider, SerializationManager serializationManager, ITelemetryProducer telemetryProducer, ILoggerFactory loggerFactory) + : base(name, options, serviceProvider, serializationManager, telemetryProducer, loggerFactory) { - private readonly EventHubStreamProviderSettings adapterSettings; - private readonly SerializationManager serializationManager; - private readonly TimePurgePredicate timePurgePredicate; - - public CacheFactory(EventHubStreamProviderSettings adapterSettings, SerializationManager serializationManager) - { - this.adapterSettings = adapterSettings; - this.serializationManager = serializationManager; - timePurgePredicate = new TimePurgePredicate(adapterSettings.DataMinTimeInCache, adapterSettings.DataMaxAgeInCache); - } - - public IEventHubQueueCache CreateCache(string partition, IStreamQueueCheckpointer checkpointer, ILoggerFactory loggerFactory, ITelemetryProducer telemetryProducer) - { - var bufferPool = new ObjectPool(() => new FixedSizeBuffer(1 << 20), null, null); - var dataAdapter = new CachedDataAdapter(partition, bufferPool, this.serializationManager); - var cacheLogger = loggerFactory.CreateLogger($"{typeof(EventHubQueueCache).FullName}.{this.adapterSettings.StreamProviderName}.{partition}"); - return new EventHubQueueCache(checkpointer, dataAdapter, EventHubDataComparer.Instance, cacheLogger, - new EventHubCacheEvictionStrategy(cacheLogger, this.timePurgePredicate, null, null), null, null); - } } - public class AdapterFactory : EventHubAdapterFactory + protected override IEventHubQueueCacheFactory CreateCacheFactory(EventHubStreamOptions options) { - protected override IEventHubQueueCacheFactory CreateCacheFactory(EventHubStreamProviderSettings providerSettings) - { - return new CacheFactory(providerSettings, SerializationManager); - } + return new CustomCacheFactory(this.Name, options, SerializationManager); } private class CachedDataAdapter : EventHubDataAdapter @@ -72,5 +54,38 @@ public static Guid GetPartitionGuid(string partition) Array.Resize(ref bytes, 10); return new Guid(partition.GetHashCode(), bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8], bytes[9]); } + + private class CustomCacheFactory : IEventHubQueueCacheFactory + { + private readonly string name; + private readonly EventHubStreamOptions options; + private readonly SerializationManager serializationManager; + private readonly TimePurgePredicate timePurgePredicate; + + public CustomCacheFactory(string name, EventHubStreamOptions options, SerializationManager serializationManager) + { + this.name = name; + this.options = options; + this.serializationManager = serializationManager; + timePurgePredicate = new TimePurgePredicate(options.DataMinTimeInCache, options.DataMaxAgeInCache); + } + + public IEventHubQueueCache CreateCache(string partition, IStreamQueueCheckpointer checkpointer, ILoggerFactory loggerFactory, ITelemetryProducer telemetryProducer) + { + var bufferPool = new ObjectPool(() => new FixedSizeBuffer(1 << 20), null, null); + var dataAdapter = new CachedDataAdapter(partition, bufferPool, this.serializationManager); + var cacheLogger = loggerFactory.CreateLogger($"{typeof(EventHubQueueCache).FullName}.{this.name}.{partition}"); + return new EventHubQueueCache(checkpointer, dataAdapter, EventHubDataComparer.Instance, cacheLogger, + new EventHubCacheEvictionStrategy(cacheLogger, this.timePurgePredicate, null, null), null, null); + } + } + + public static new StreamPerPartitionEventHubStreamAdapterFactory Create(IServiceProvider services, string name) + { + IOptionsSnapshot streamOptionsSnapshot = services.GetRequiredService>(); + var factory = ActivatorUtilities.CreateInstance(services, name, streamOptionsSnapshot.Get(name)); + factory.Init(); + return factory; + } } } \ No newline at end of file diff --git a/test/ServiceBus.Tests/TestStreamProviders/TestEventHubStreamProvider.cs b/test/ServiceBus.Tests/TestStreamProviders/TestEventHubStreamProvider.cs index 95b517517bf..872b3b39b96 100644 --- a/test/ServiceBus.Tests/TestStreamProviders/TestEventHubStreamProvider.cs +++ b/test/ServiceBus.Tests/TestStreamProviders/TestEventHubStreamProvider.cs @@ -1,20 +1,30 @@  +using System; using Microsoft.Extensions.DependencyInjection; -using Orleans.Providers.Streams.Common; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Orleans.Configuration; +using Orleans.Runtime; using Orleans.Serialization; using Orleans.ServiceBus.Providers; using Tester.TestStreamProviders; namespace ServiceBus.Tests.TestStreamProviders.EventHub { - public class TestEventHubStreamProvider : PersistentStreamProvider + public class TestEventHubStreamAdapterFactory : EventHubAdapterFactory { - public class AdapterFactory : EventHubAdapterFactory + public TestEventHubStreamAdapterFactory(string name, EventHubStreamOptions options, IServiceProvider serviceProvider, SerializationManager serializationManager, ITelemetryProducer telemetryProducer, ILoggerFactory loggerFactory) + : base(name, options, serviceProvider, serializationManager, telemetryProducer, loggerFactory) { - public AdapterFactory() - { - StreamFailureHandlerFactory = qid => TestAzureTableStorageStreamFailureHandler.Create(this.serviceProvider.GetRequiredService()); - } + StreamFailureHandlerFactory = qid => TestAzureTableStorageStreamFailureHandler.Create(this.serviceProvider.GetRequiredService()); + } + + public static new TestEventHubStreamAdapterFactory Create(IServiceProvider services, string name) + { + IOptionsSnapshot streamOptionsSnapshot = services.GetRequiredService>(); + var factory = ActivatorUtilities.CreateInstance(services, name, streamOptionsSnapshot.Get(name)); + factory.Init(); + return factory; } } } diff --git a/test/Tester/Forwarding/ShutdownSiloTests.cs b/test/Tester/Forwarding/ShutdownSiloTests.cs index 224093db775..47018734cf7 100644 --- a/test/Tester/Forwarding/ShutdownSiloTests.cs +++ b/test/Tester/Forwarding/ShutdownSiloTests.cs @@ -1,19 +1,13 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading; using System.Threading.Tasks; -using Orleans.Runtime; using Orleans.TestingHost; using TestExtensions; using UnitTests.GrainInterfaces; using Xunit; -using Orleans; -using Orleans.Runtime.Configuration; using Orleans.TestingHost.Utils; using Orleans.Hosting; -using Orleans.Storage; +using Orleans.Configuration; namespace Tester.Forwarding { diff --git a/test/Tester/StreamingTests/ControllableStreamGeneratorProviderTests.cs b/test/Tester/StreamingTests/ControllableStreamGeneratorProviderTests.cs index 9369f60be6f..a4de4d68386 100644 --- a/test/Tester/StreamingTests/ControllableStreamGeneratorProviderTests.cs +++ b/test/Tester/StreamingTests/ControllableStreamGeneratorProviderTests.cs @@ -1,15 +1,16 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Orleans; +using Orleans.Configuration; +using Orleans.Hosting; +using Orleans.Providers.Streams.Common; using Orleans.Providers.Streams.Generator; using Orleans.Runtime; using Orleans.Streams; using Orleans.TestingHost; using Orleans.TestingHost.Utils; -using Tester; using TestExtensions; using TestGrainInterfaces; using TestGrains; @@ -20,37 +21,35 @@ namespace UnitTests.StreamingTests { public class ControllableStreamGeneratorProviderTests : OrleansTestingBase, IClassFixture { + private const int TotalQueueCount = 4; private readonly Fixture fixture; public class Fixture : BaseTestClusterFixture { public const string StreamProviderName = GeneratedStreamTestConstants.StreamProviderName; - public static readonly string StreamProviderTypeName = typeof(GeneratorStreamProvider).FullName; + public static readonly string StreamProviderTypeName = typeof(PersistentStreamProvider).FullName; public const string StreamNamespace = GeneratedEventCollectorGrain.StreamNamespace; - public static readonly GeneratorAdapterConfig AdapterConfig = new GeneratorAdapterConfig(StreamProviderName) - { - TotalQueueCount = 4, - }; - protected override void ConfigureTestCluster(TestClusterBuilder builder) { - var settings = new Dictionary(); - - // get initial settings from configs - AdapterConfig.WriteProperties(settings); - - // add queue balancer setting - settings.Add(PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.AssemblyQualifiedName); - - // add pub/sub settting - settings.Add(PersistentStreamProviderConfig.STREAM_PUBSUB_TYPE, StreamPubSubType.ImplicitOnly.ToString()); + builder.AddSiloBuilderConfigurator(); + } - // register stream provider - builder.ConfigureLegacyConfiguration(legacy => + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) { - legacy.ClusterConfiguration.Globals.RegisterStreamProvider(StreamProviderName, settings); - }); + hostBuilder + .AddPersistentStreams(StreamProviderName, + GeneratorAdapterFactory.Create, options => + { + options.TotalQueueCount = TotalQueueCount; + options.BalancerType = StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer; + options.PubSubType = StreamPubSubType.ImplicitOnly; + }) + .ConfigureServices(services => services + .ConfigureNamedOptionForLogging(StreamProviderName)); + } } } @@ -80,7 +79,7 @@ private async Task ValidateControllableGeneratedStreams() { try { - var generatorConfig = new SimpleGeneratorConfig + var generatorConfig = new SimpleGeneratorOptions { StreamNamespace = Fixture.StreamNamespace, EventsInStream = 100 @@ -105,7 +104,7 @@ private async Task ValidateControllableGeneratedStreams() } } - private async Task CheckCounters(SimpleGeneratorConfig generatorConfig, bool assertIsTrue) + private async Task CheckCounters(SimpleGeneratorOptions generatorConfig, bool assertIsTrue) { var reporter = this.fixture.GrainFactory.GetGrain(GeneratedStreamTestConstants.ReporterId); @@ -113,13 +112,13 @@ private async Task CheckCounters(SimpleGeneratorConfig generatorConfig, bo if (assertIsTrue) { // one stream per queue - Assert.Equal(Fixture.AdapterConfig.TotalQueueCount, report.Count); // stream count + Assert.Equal(TotalQueueCount, report.Count); // stream count foreach (int eventsPerStream in report.Values) { Assert.Equal(generatorConfig.EventsInStream, eventsPerStream); } } - else if (Fixture.AdapterConfig.TotalQueueCount != report.Count || + else if (TotalQueueCount != report.Count || report.Values.Any(count => count != generatorConfig.EventsInStream)) { return false; diff --git a/test/Tester/StreamingTests/ControllableStreamProviderTests.cs b/test/Tester/StreamingTests/ControllableStreamProviderTests.cs index 668f3118fc2..a2d6c793c12 100644 --- a/test/Tester/StreamingTests/ControllableStreamProviderTests.cs +++ b/test/Tester/StreamingTests/ControllableStreamProviderTests.cs @@ -1,12 +1,13 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Orleans; +using Orleans.Configuration; +using Orleans.Hosting; +using Orleans.Providers.Streams.Common; using Orleans.Runtime; using Orleans.Streams; using Orleans.TestingHost; -using Tester; using Tester.TestStreamProviders.Controllable; using TestExtensions; using Xunit; @@ -18,20 +19,25 @@ public class ControllableStreamProviderTests : OrleansTestingBase, IClassFixture public class Fixture : BaseTestClusterFixture { public const string StreamProviderName = "ControllableTestStreamProvider"; - public readonly string StreamProviderTypeName = typeof(ControllableTestStreamProvider).FullName; + public readonly string StreamProviderTypeName = typeof(PersistentStreamProvider).FullName; protected override void ConfigureTestCluster(TestClusterBuilder builder) { - var settings = new Dictionary - { - {PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.AssemblyQualifiedName}, - {PersistentStreamProviderConfig.STREAM_PUBSUB_TYPE, StreamPubSubType.ImplicitOnly.ToString()} - }; + builder.AddSiloBuilderConfigurator(); + } - builder.ConfigureLegacyConfiguration(legacy => + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) { - legacy.ClusterConfiguration.Globals.RegisterStreamProvider(StreamProviderName, settings); - }); + hostBuilder + .AddPersistentStreams(StreamProviderName, + ControllableTestAdapterFactory.Create, options => + { + options.BalancerType = StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer; + options.PubSubType = StreamPubSubType.ImplicitOnly; + }); + } } } diff --git a/test/Tester/StreamingTests/GeneratedStreamRecoveryTests.cs b/test/Tester/StreamingTests/GeneratedStreamRecoveryTests.cs index 74e4cf0b2e3..a382b6c9f11 100644 --- a/test/Tester/StreamingTests/GeneratedStreamRecoveryTests.cs +++ b/test/Tester/StreamingTests/GeneratedStreamRecoveryTests.cs @@ -1,13 +1,14 @@ -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Orleans; +using Orleans.Configuration; +using Orleans.Hosting; +using Orleans.Providers.Streams.Common; using Orleans.Providers.Streams.Generator; using Orleans.Runtime; using Orleans.Runtime.Configuration; using Orleans.Streams; using Orleans.TestingHost; -using Tester; using Tester.StreamingTests; using TestExtensions; using TestGrains; @@ -18,39 +19,38 @@ namespace UnitTests.StreamingTests { public class GeneratedImplicitSubscriptionStreamRecoveryTests : OrleansTestingBase, IClassFixture { - private static readonly string StreamProviderTypeName = typeof(GeneratorStreamProvider).FullName; + private static readonly string StreamProviderTypeName = typeof(PersistentStreamProvider).FullName; + private const int TotalQueueCount = 4; private readonly Fixture fixture; private readonly ImplicitSubscritionRecoverableStreamTestRunner runner; - public class Fixture : BaseTestClusterFixture { public const string StreamProviderName = GeneratedStreamTestConstants.StreamProviderName; - public readonly static GeneratorAdapterConfig AdapterConfig = new GeneratorAdapterConfig(StreamProviderName) - { - TotalQueueCount = 4, - }; - protected override void ConfigureTestCluster(TestClusterBuilder builder) { builder.ConfigureLegacyConfiguration(legacy => { legacy.ClusterConfiguration.AddMemoryStorageProvider("MemoryStore"); legacy.ClusterConfiguration.AddMemoryStorageProvider("Default"); - var settings = new Dictionary(); - // get initial settings from configs - AdapterConfig.WriteProperties(settings); - - // add queue balancer setting - settings.Add(PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.AssemblyQualifiedName); - - // add pub/sub settting - settings.Add(PersistentStreamProviderConfig.STREAM_PUBSUB_TYPE, StreamPubSubType.ImplicitOnly.ToString()); - - // register stream provider - legacy.ClusterConfiguration.Globals.RegisterStreamProvider(StreamProviderName, settings); }); + builder.AddSiloBuilderConfigurator(); + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddPersistentStreams(StreamProviderName, + GeneratorAdapterFactory.Create, options => + { + options.TotalQueueCount = TotalQueueCount; + options.BalancerType = StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer; + options.PubSubType = StreamPubSubType.ImplicitOnly; + }); + } } } @@ -68,7 +68,7 @@ public async Task Recoverable100EventStreamsWithTransientErrorsTest() this.fixture.Logger.Info("************************ Recoverable100EventStreamsWithTransientErrorsTest *********************************"); await runner.Recoverable100EventStreamsWithTransientErrors(GenerateEvents, ImplicitSubscription_TransientError_RecoverableStream_CollectorGrain.StreamNamespace, - Fixture.AdapterConfig.TotalQueueCount, + TotalQueueCount, 100); } @@ -78,13 +78,13 @@ public async Task Recoverable100EventStreamsWith1NonTransientErrorTest() this.fixture.Logger.Info("************************ Recoverable100EventStreamsWith1NonTransientErrorTest *********************************"); await runner.Recoverable100EventStreamsWith1NonTransientError(GenerateEvents, ImplicitSubscription_NonTransientError_RecoverableStream_CollectorGrain.StreamNamespace, - Fixture.AdapterConfig.TotalQueueCount, + TotalQueueCount, 100); } private async Task GenerateEvents(string streamNamespace, int streamCount, int eventsInStream) { - var generatorConfig = new SimpleGeneratorConfig + var generatorConfig = new SimpleGeneratorOptions { StreamNamespace = streamNamespace, EventsInStream = eventsInStream diff --git a/test/Tester/StreamingTests/MemoryStreamProviderClientTests.cs b/test/Tester/StreamingTests/MemoryStreamProviderClientTests.cs index 34c753535c9..a66e84590df 100644 --- a/test/Tester/StreamingTests/MemoryStreamProviderClientTests.cs +++ b/test/Tester/StreamingTests/MemoryStreamProviderClientTests.cs @@ -2,7 +2,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; using Orleans; +using Orleans.Hosting; using Orleans.Providers; using Orleans.Providers.Streams.Generator; using Orleans.Runtime; @@ -18,49 +20,39 @@ public class MemoryStreamProviderClientTests : OrleansTestingBase, IClassFixture { public class Fixture : BaseTestClusterFixture { - public const string StreamProviderName = nameof(MemoryStreamProvider); + public const string StreamProviderName = "MemoryStreamProvider"; public const string StreamNamespace = "StreamNamespace"; - public static readonly SimpleGeneratorConfig GeneratorConfig = new SimpleGeneratorConfig - { - StreamNamespace = StreamNamespace, - EventsInStream = 100 - }; - - public static readonly MemoryAdapterConfig AdapterConfig = new MemoryAdapterConfig(StreamProviderName); - protected override void ConfigureTestCluster(TestClusterBuilder builder) { builder.ConfigureLegacyConfiguration(legacy => { AdjustConfig(legacy.ClusterConfiguration); - AdjustConfig(legacy.ClientConfiguration); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); } - private static void AdjustConfig(ClusterConfiguration config) + private class MyClientBuilderConfigurator : IClientBuilderConfigurator { - // register stream provider - config.AddMemoryStorageProvider("PubSubStore"); - config.Globals.RegisterStreamProvider(StreamProviderName, BuildProviderSettings()); - config.Globals.ClientDropTimeout = TimeSpan.FromSeconds(5); + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) => clientBuilder + .AddMemoryStreams(StreamProviderName); } - private static void AdjustConfig(ClientConfiguration config) + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator { - config.RegisterStreamProvider(StreamProviderName, BuildProviderSettings()); + public void Configure(ISiloHostBuilder hostBuilder) => hostBuilder + .AddMemoryStreams(StreamProviderName); } - private static Dictionary BuildProviderSettings() + private static void AdjustConfig(ClusterConfiguration config) { - var settings = new Dictionary(); - // get initial settings from configs - ProviderConfig.WriteProperties(settings); - return settings; + // register stream provider + config.AddMemoryStorageProvider("PubSubStore"); + config.Globals.ClientDropTimeout = TimeSpan.FromSeconds(5); } } - private static readonly MemoryAdapterConfig ProviderConfig = new MemoryAdapterConfig(Fixture.StreamProviderName); private readonly ITestOutputHelper output = null; private readonly ClientStreamTestRunner runner; diff --git a/test/Tester/StreamingTests/PlugableQueueBalancerTests/LeaseBasedQueueBalancer.cs b/test/Tester/StreamingTests/PlugableQueueBalancerTests/LeaseBasedQueueBalancer.cs index 785955cc006..4d4350b7973 100644 --- a/test/Tester/StreamingTests/PlugableQueueBalancerTests/LeaseBasedQueueBalancer.cs +++ b/test/Tester/StreamingTests/PlugableQueueBalancerTests/LeaseBasedQueueBalancer.cs @@ -1,15 +1,7 @@ using Orleans; -using Orleans.Core; -using Orleans.Placement; -using Orleans.Providers; -using Orleans.Runtime; -using Orleans.Runtime.Configuration; -using Orleans.Services; using Orleans.Streams; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; namespace Tester.StreamingTests @@ -29,8 +21,7 @@ public LeaseBasedQueueBalancerForTest(IGrainFactory grainFactory) public async Task Initialize(string strProviderName, IStreamQueueMapper queueMapper, - TimeSpan siloMaturityPeriod, - IProviderConfiguration providerConfig) + TimeSpan siloMaturityPeriod) { this.leaseManagerGrain = this.grainFactory.GetGrain(strProviderName); await this.leaseManagerGrain.SetQueuesAsLeases(queueMapper.GetAllQueues()); diff --git a/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestBase.cs b/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestBase.cs index d1b749a2847..1598728ee79 100644 --- a/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestBase.cs +++ b/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestBase.cs @@ -1,34 +1,22 @@ -using Microsoft.Extensions.DependencyInjection; +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Orleans.Hosting; -using Orleans.Runtime; -using Orleans.Runtime.Configuration; -using Orleans.Storage; -using Orleans.Streams; using Orleans.TestingHost; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Orleans.TestingHost.Utils; using TestExtensions; using Xunit; +using Orleans.Configuration; namespace Tester.StreamingTests { public class PluggableQueueBalancerTestBase : OrleansTestingBase { private static Type QueueBalancerType = typeof(LeaseBasedQueueBalancerForTest); - private static PersistentStreamProviderConfig CustomPersistentProviderConfig = CreateConfigWithCustomBalancerType(); - - public static void ConfigureCustomQueueBalancer(Dictionary streamProviderSettings, ClusterConfiguration config) - { - CustomPersistentProviderConfig.WriteProperties(streamProviderSettings); - } - private static PersistentStreamProviderConfig CreateConfigWithCustomBalancerType() + public static PersistentStreamOptions ConfigWithCustomBalancerType(PersistentStreamOptions options) { - var config = new PersistentStreamProviderConfig(); - config.BalancerType = QueueBalancerType; - return config; + options.BalancerType = QueueBalancerType; + return options; } public virtual async Task ShouldUseInjectedQueueBalancerAndBalanceCorrectly(BaseTestClusterFixture fixture, string streamProviderName, int siloCount, int totalQueueCount) diff --git a/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestsWithMemoryStreamProvider.cs b/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestsWithMemoryStreamProvider.cs index 41d377a7c1e..95b38a959b9 100644 --- a/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestsWithMemoryStreamProvider.cs +++ b/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestsWithMemoryStreamProvider.cs @@ -1,12 +1,10 @@ +using Microsoft.Extensions.Configuration; +using Orleans; +using Orleans.Hosting; using Orleans.Providers; using Orleans.Runtime.Configuration; using Orleans.Storage; using Orleans.TestingHost; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; using System.Threading.Tasks; using TestExtensions; using Xunit; @@ -18,8 +16,6 @@ public class PluggableQueueBalancerTestsWithMemoryStreamProvider : PluggableQueu private const string StreamProviderName = "MemoryStreamProvider"; private static readonly int totalQueueCount = 6; private static readonly short siloCount = 2; - public static readonly MemoryAdapterConfig ProviderSettings = - new MemoryAdapterConfig(StreamProviderName); private readonly Fixture fixture; @@ -29,22 +25,40 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) { builder.Options.InitialSilosCount = siloCount; builder.AddSiloBuilderConfigurator(); - ProviderSettings.TotalQueueCount = totalQueueCount; builder.ConfigureLegacyConfiguration(legacy => { AdjustClusterConfiguration(legacy.ClusterConfiguration); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); } - private static void AdjustClusterConfiguration(ClusterConfiguration config) + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator { - var settings = new Dictionary(); - // get initial settings from configs - ProviderSettings.WriteProperties(settings); - ConfigureCustomQueueBalancer(settings, config); + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddMemoryStreams(StreamProviderName, options => + { + options.TotalQueueCount = totalQueueCount; + }); + } + } - // register stream provider - config.Globals.RegisterStreamProvider(StreamProviderName, settings); + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddMemoryStreams(StreamProviderName, options => + { + options.TotalQueueCount = totalQueueCount; + }); + } + } + + private static void AdjustClusterConfiguration(ClusterConfiguration config) + { config.Globals.RegisterStorageProvider("PubSubStore"); } } diff --git a/test/Tester/StreamingTests/ProgrammaticSubscribeTests/ProgrammaticSubcribeTestsRunner.cs b/test/Tester/StreamingTests/ProgrammaticSubscribeTests/ProgrammaticSubcribeTestsRunner.cs index 7cc8a364ae8..22542ffd302 100644 --- a/test/Tester/StreamingTests/ProgrammaticSubscribeTests/ProgrammaticSubcribeTestsRunner.cs +++ b/test/Tester/StreamingTests/ProgrammaticSubscribeTests/ProgrammaticSubcribeTestsRunner.cs @@ -1,8 +1,5 @@ using Orleans; -using Orleans.Providers; using Orleans.Runtime; -using Orleans.Runtime.Configuration; -using Orleans.Streams; using Orleans.TestingHost; using System; using System.Collections.Generic; @@ -11,7 +8,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Orleans.Streams.Core; -using Orleans.Streams.PubSub; using TestExtensions; using Xunit; using UnitTests.GrainInterfaces; diff --git a/test/Tester/StreamingTests/PullingAgentManagementTests.cs b/test/Tester/StreamingTests/PullingAgentManagementTests.cs index 3fa8fb4c636..09bbf7295c6 100644 --- a/test/Tester/StreamingTests/PullingAgentManagementTests.cs +++ b/test/Tester/StreamingTests/PullingAgentManagementTests.cs @@ -1,6 +1,9 @@ using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using Orleans.Configuration; +using Orleans.Hosting; using Orleans.Providers.Streams.AzureQueue; using Orleans.Providers.Streams.Common; using Orleans.Runtime; @@ -23,13 +26,17 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) builder.ConfigureLegacyConfiguration(legacy => { legacy.ClusterConfiguration.AddMemoryStorageProvider("PubSubStore"); - - // register stream providers - // options.ClusterConfiguration.AddSimpleMessageStreamProvider(StreamTestsConstants.SMS_STREAM_PROVIDER_NAME, false); - // options.ClientConfiguration.AddSimpleMessageStreamProvider(StreamTestsConstants.SMS_STREAM_PROVIDER_NAME, false); - - legacy.ClusterConfiguration.AddAzureQueueStreamProvider(StreamTestsConstants.AZURE_QUEUE_STREAM_PROVIDER_NAME); }); + builder.AddSiloBuilderConfigurator(); + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) => hostBuilder + .AddAzureQueueStreams(StreamTestsConstants.AZURE_QUEUE_STREAM_PROVIDER_NAME, options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); } protected override void CheckPreconditionsOrThrow() @@ -41,7 +48,7 @@ protected override void CheckPreconditionsOrThrow() private const string adapterName = StreamTestsConstants.AZURE_QUEUE_STREAM_PROVIDER_NAME; #pragma warning disable 618 - private readonly string adapterType = typeof(AzureQueueStreamProvider).FullName; + private readonly string adapterType = typeof(PersistentStreamProvider).FullName; #pragma warning restore 618 public PullingAgentManagementTests(Fixture fixture) @@ -55,21 +62,21 @@ public async Task PullingAgents_ControlCmd_1() { var mgmt = this.fixture.GrainFactory.GetGrain(0);; - await ValidateAgentsState(PersistentStreamProviderState.AgentsStarted); + await ValidateAgentsState(PersistentStreamOptions.RunState.AgentsStarted); await mgmt.SendControlCommandToProvider(adapterType, adapterName, (int)PersistentStreamProviderCommand.StartAgents); - await ValidateAgentsState(PersistentStreamProviderState.AgentsStarted); + await ValidateAgentsState(PersistentStreamOptions.RunState.AgentsStarted); await mgmt.SendControlCommandToProvider(adapterType, adapterName, (int)PersistentStreamProviderCommand.StopAgents); - await ValidateAgentsState(PersistentStreamProviderState.AgentsStopped); + await ValidateAgentsState(PersistentStreamOptions.RunState.AgentsStopped); await mgmt.SendControlCommandToProvider(adapterType, adapterName, (int)PersistentStreamProviderCommand.StartAgents); - await ValidateAgentsState(PersistentStreamProviderState.AgentsStarted); + await ValidateAgentsState(PersistentStreamOptions.RunState.AgentsStarted); } - private async Task ValidateAgentsState(PersistentStreamProviderState expectedState) + private async Task ValidateAgentsState(PersistentStreamOptions.RunState expectedState) { var mgmt = this.fixture.GrainFactory.GetGrain(0); @@ -77,7 +84,7 @@ private async Task ValidateAgentsState(PersistentStreamProviderState expectedSta Assert.Equal(2, states.Length); foreach (var state in states) { - PersistentStreamProviderState providerState; + PersistentStreamOptions.RunState providerState; Enum.TryParse(state.ToString(), out providerState); Assert.Equal(expectedState, providerState); } @@ -85,9 +92,9 @@ private async Task ValidateAgentsState(PersistentStreamProviderState expectedSta var numAgents = await mgmt.SendControlCommandToProvider(adapterType, adapterName, (int)PersistentStreamProviderCommand.GetNumberRunningAgents); Assert.Equal(2, numAgents.Length); int totalNumAgents = numAgents.Select(Convert.ToInt32).Sum(); - if (expectedState == PersistentStreamProviderState.AgentsStarted) + if (expectedState == PersistentStreamOptions.RunState.AgentsStarted) { - Assert.Equal(AzureQueueAdapterConstants.NumQueuesDefaultValue, totalNumAgents); + Assert.Equal(AzureQueueStreamOptions.DEFAULT_NUM_QUEUES, totalNumAgents); } else { diff --git a/test/Tester/StreamingTests/StreamGeneratorProviderTests.cs b/test/Tester/StreamingTests/StreamGeneratorProviderTests.cs index 4f604d1bdf9..1569a5a8722 100644 --- a/test/Tester/StreamingTests/StreamGeneratorProviderTests.cs +++ b/test/Tester/StreamingTests/StreamGeneratorProviderTests.cs @@ -1,7 +1,8 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Orleans.Configuration; +using Orleans.Hosting; using Orleans.Providers.Streams.Generator; using Orleans.Runtime; using Orleans.Streams; @@ -17,6 +18,7 @@ namespace UnitTests.StreamingTests { public class StreamGeneratorProviderTests : OrleansTestingBase, IClassFixture { + private const int TotalQueueCount = 4; private readonly Fixture fixture; public class Fixture : BaseTestClusterFixture @@ -24,36 +26,31 @@ public class Fixture : BaseTestClusterFixture public const string StreamProviderName = GeneratedStreamTestConstants.StreamProviderName; public const string StreamNamespace = GeneratedEventCollectorGrain.StreamNamespace; - public readonly static SimpleGeneratorConfig GeneratorConfig = new SimpleGeneratorConfig + public readonly static SimpleGeneratorOptions GeneratorConfig = new SimpleGeneratorOptions { StreamNamespace = StreamNamespace, EventsInStream = 100 }; - public readonly static GeneratorAdapterConfig AdapterConfig = new GeneratorAdapterConfig(StreamProviderName) - { - TotalQueueCount = 4, - GeneratorConfigType = GeneratorConfig.GetType() - }; - protected override void ConfigureTestCluster(TestClusterBuilder builder) { - var settings = new Dictionary(); - // get initial settings from configs - AdapterConfig.WriteProperties(settings); - GeneratorConfig.WriteProperties(settings); - - // add queue balancer setting - settings.Add(PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.AssemblyQualifiedName); - - // add pub/sub settting - settings.Add(PersistentStreamProviderConfig.STREAM_PUBSUB_TYPE, StreamPubSubType.ImplicitOnly.ToString()); + builder.AddSiloBuilderConfigurator(); + } - // register stream provider - builder.ConfigureLegacyConfiguration(legacy => + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) { - legacy.ClusterConfiguration.Globals.RegisterStreamProvider(StreamProviderName, settings); - }); + hostBuilder + .AddPersistentStreams(StreamProviderName, + GeneratorAdapterFactory.Create, options => + { + options.TotalQueueCount = TotalQueueCount; + options.BalancerType = StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer; + options.PubSubType = StreamPubSubType.ImplicitOnly; + }) + .ConfigureServices(services => services.AddSingletonNamedService(StreamProviderName, (s,n) => GeneratorConfig)); + } } } @@ -79,13 +76,13 @@ private async Task CheckCounters(bool assertIsTrue) if (assertIsTrue) { // one stream per queue - Assert.Equal(Fixture.AdapterConfig.TotalQueueCount, report.Count); + Assert.Equal(TotalQueueCount, report.Count); foreach (int eventsPerStream in report.Values) { Assert.Equal(Fixture.GeneratorConfig.EventsInStream, eventsPerStream); } } - else if (Fixture.AdapterConfig.TotalQueueCount != report.Count || + else if (TotalQueueCount != report.Count || report.Values.Any(count => count != Fixture.GeneratorConfig.EventsInStream)) { return false; diff --git a/test/Tester/TestStreamProviders/Controllable/ControllableTestStreamProvider.cs b/test/Tester/TestStreamProviders/Controllable/ControllableTestStreamProvider.cs index 1bcd64e067b..bdbb512547d 100644 --- a/test/Tester/TestStreamProviders/Controllable/ControllableTestStreamProvider.cs +++ b/test/Tester/TestStreamProviders/Controllable/ControllableTestStreamProvider.cs @@ -1,10 +1,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Orleans; +using Microsoft.Extensions.DependencyInjection; using Orleans.Providers; using Orleans.Providers.Streams.Common; -using Orleans.Runtime; using Orleans.Streams; namespace Tester.TestStreamProviders.Controllable @@ -15,61 +14,65 @@ public enum ControllableTestStreamProviderCommands AdapterFactoryEcho = PersistentStreamProviderCommand.AdapterFactoryCommandStartRange + 1, } - public class ControllableTestStreamProvider : PersistentStreamProvider + public class ControllableTestAdapterFactory : IQueueAdapter, IQueueAdapterFactory, IControllable { - public class ControllableAdapterFactory : IQueueAdapter, IQueueAdapterFactory, IControllable + public string Name { get; private set; } + + public Task QueueMessageBatchAsync(Guid streamGuid, string streamNamespace, IEnumerable events, StreamSequenceToken token, + Dictionary requestContext) { - public string Name { get; private set; } + return Task.CompletedTask; + } - public Task QueueMessageBatchAsync(Guid streamGuid, string streamNamespace, IEnumerable events, StreamSequenceToken token, - Dictionary requestContext) - { - return Task.CompletedTask; - } + public IQueueAdapterReceiver CreateReceiver(QueueId queueId) + { + throw new NotImplementedException(); + } - public IQueueAdapterReceiver CreateReceiver(QueueId queueId) - { - throw new NotImplementedException(); - } + public bool IsRewindable { get; private set; } + public StreamProviderDirection Direction { get; private set; } - public bool IsRewindable { get; private set; } - public StreamProviderDirection Direction { get; private set; } - public void Init(IProviderConfiguration config, string providerName, IServiceProvider serviceProvider) - { - Name = providerName; - } + public ControllableTestAdapterFactory(string name) + { + Name = name; + } - public Task CreateAdapter() - { - return Task.FromResult(this); - } + public Task CreateAdapter() + { + return Task.FromResult(this); + } - public IQueueAdapterCache GetQueueAdapterCache() - { - throw new NotImplementedException(); - } + public IQueueAdapterCache GetQueueAdapterCache() + { + throw new NotImplementedException(); + } - public IStreamQueueMapper GetStreamQueueMapper() - { - return new HashRingBasedStreamQueueMapper(0, Name); - } + public IStreamQueueMapper GetStreamQueueMapper() + { + return new HashRingBasedStreamQueueMapper(0, Name); + } - public Task GetDeliveryFailureHandler(QueueId queueId) - { - throw new NotImplementedException(); - } + public Task GetDeliveryFailureHandler(QueueId queueId) + { + throw new NotImplementedException(); + } - public Task ExecuteCommand(int command, object arg) + public Task ExecuteCommand(int command, object arg) + { + switch ((ControllableTestStreamProviderCommands) command) { - switch ((ControllableTestStreamProviderCommands) command) - { - case ControllableTestStreamProviderCommands.AdapterEcho: - return Task.FromResult(Tuple.Create(ControllableTestStreamProviderCommands.AdapterEcho, arg)); - case ControllableTestStreamProviderCommands.AdapterFactoryEcho: - return Task.FromResult(Tuple.Create(ControllableTestStreamProviderCommands.AdapterFactoryEcho, arg)); - } - throw new ArgumentOutOfRangeException("command"); + case ControllableTestStreamProviderCommands.AdapterEcho: + return Task.FromResult(Tuple.Create(ControllableTestStreamProviderCommands.AdapterEcho, arg)); + case ControllableTestStreamProviderCommands.AdapterFactoryEcho: + return Task.FromResult(Tuple.Create(ControllableTestStreamProviderCommands.AdapterFactoryEcho, arg)); } + throw new ArgumentOutOfRangeException("command"); + } + + public static ControllableTestAdapterFactory Create(IServiceProvider services, string name) + { + var factory = ActivatorUtilities.CreateInstance(services, name); + return factory; } } } diff --git a/test/Tester/TestStreamProviders/FailureInjectionStreamProvider.cs b/test/Tester/TestStreamProviders/FailureInjectionStreamProvider.cs deleted file mode 100644 index 4e70067df21..00000000000 --- a/test/Tester/TestStreamProviders/FailureInjectionStreamProvider.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Threading.Tasks; -using Orleans; -using Orleans.Streams; -using Orleans.Providers; -using Orleans.Streams.Core; -using Orleans.Runtime; - -namespace Tester.TestStreamProviders -{ - /// - /// This is a test stream provider that throws exceptions when config file contains certain properties. - /// - public enum FailureInjectionStreamProviderMode - { - NoFault, - InitializationThrowsException, - StartThrowsException - } - - public class FailureInjectionStreamProvider : IStreamProviderImpl - { - private FailureInjectionStreamProviderMode mode; - - public static string FailureInjectionModeString => "FAILURE_INJECTION_STREAM_PROVIDER_MODE"; - - public string Name { get; set; } - - public IAsyncStream GetStream(Guid streamId, string streamNamespace) - { - throw new NotImplementedException(); - } - - public bool IsRewindable => false; - - public Task Close() - { - return Task.CompletedTask; - } - - public Task Init(string name, IProviderRuntime providerUtilitiesManager, IProviderConfiguration providerConfig) - { - Name = name; - mode = providerConfig.GetEnumProperty(FailureInjectionModeString, FailureInjectionStreamProviderMode.NoFault); - return mode == FailureInjectionStreamProviderMode.InitializationThrowsException - ? Task.FromException(new ProviderInitializationException("Error initializing provider " + typeof(FailureInjectionStreamProvider))) - : Task.CompletedTask; - } - - public Task Start() - { - return mode == FailureInjectionStreamProviderMode.StartThrowsException - ? Task.FromException(new ProviderStartException("Error starting provider " + typeof(FailureInjectionStreamProvider).Name)) - : Task.CompletedTask; - } - } -} diff --git a/test/TesterAzureUtils/Lease/LeaseBasedQueueBalancerTests.cs b/test/TesterAzureUtils/Lease/LeaseBasedQueueBalancerTests.cs index eb1e00df4ad..62a865aaaa0 100644 --- a/test/TesterAzureUtils/Lease/LeaseBasedQueueBalancerTests.cs +++ b/test/TesterAzureUtils/Lease/LeaseBasedQueueBalancerTests.cs @@ -1,7 +1,9 @@ using Microsoft.Extensions.DependencyInjection; +using Orleans.Configuration; using Orleans.Hosting; using Orleans.LeaseProviders; using Orleans.Providers; +using Orleans.Providers.Streams.AzureQueue; using Orleans.Providers.Streams.Common; using Orleans.Runtime; using Orleans.Runtime.Configuration; @@ -25,15 +27,6 @@ public class LeaseBasedQueueBalancerTests : TestClusterPerTest private const string StreamProviderName = "MemoryStreamProvider"; private static readonly int totalQueueCount = 6; private static readonly short siloCount = 4; - public static readonly MemoryAdapterConfig ProviderSettings = - new MemoryAdapterConfig(StreamProviderName); - public static readonly PersistentStreamProviderConfig ProviderConfig = new PersistentStreamProviderConfig() - { BalancerType = StreamQueueBalancerType.ClusterConfigDeploymentLeaseBasedBalancer }; - public static readonly LeaseBasedQueueBalancerConfig BalancerConfig = new LeaseBasedQueueBalancerConfig() - { - LeaseProviderType = typeof(AzureBlobLeaseProvider), - LeaseLength = TimeSpan.FromSeconds(15) - }; //since lease length is 1 min, so set time out to be two minutes to fulfill some test scenario public static readonly TimeSpan TimeOut = TimeSpan.FromMinutes(2); @@ -42,7 +35,6 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) TestUtils.CheckForAzureStorage(); builder.Options.InitialSilosCount = siloCount; builder.AddSiloBuilderConfigurator(); - ProviderSettings.TotalQueueCount = totalQueueCount; builder.ConfigureLegacyConfiguration(legacy => { AdjustClusterConfiguration(legacy.ClusterConfiguration); @@ -60,23 +52,27 @@ private static void ConfigureServices(IServiceCollection services) }; services.AddSingleton(leaseProviderConfig); services.AddTransient(); + services.AddOptions(StreamProviderName).Configure( options => + { + options.LeaseProviderType = typeof(AzureBlobLeaseProvider); + options.LeaseLength = TimeSpan.FromSeconds(15); + }); } public void Configure(ISiloHostBuilder hostBuilder) { - hostBuilder.ConfigureServices(ConfigureServices); + hostBuilder + .ConfigureServices(ConfigureServices) + .AddMemoryStreams(StreamProviderName, options => + { + options.TotalQueueCount = totalQueueCount; + options.BalancerType = StreamQueueBalancerType.ClusterConfigDeploymentLeaseBasedBalancer; + }); } } private static void AdjustClusterConfiguration(ClusterConfiguration config) { - var settings = new Dictionary(); - // get initial settings from configs - ProviderSettings.WriteProperties(settings); - ProviderConfig.WriteProperties(settings); - BalancerConfig.WriterProperties(settings); - // register stream provider - config.Globals.RegisterStreamProvider(StreamProviderName, settings); config.Globals.RegisterStorageProvider("PubSubStore"); } @@ -124,7 +120,7 @@ public static async Task AgentManagerOwnCorrectAmountOfAgents(int expected throw new OrleansException($"AgentManager doesn't own correct amount of agents"); } - var agentStarted = await mgmtGrain.SendControlCommandToProvider(typeof(MemoryStreamProvider).FullName, StreamProviderName, (int)PersistentStreamProviderCommand.GetNumberRunningAgents); + var agentStarted = await mgmtGrain.SendControlCommandToProvider(typeof(PersistentStreamProvider).FullName, StreamProviderName, (int)PersistentStreamProviderCommand.GetNumberRunningAgents); return agentStarted.All(startedAgentInEachSilo => Convert.ToInt32(startedAgentInEachSilo) >= expectedAgentCountMin && Convert.ToInt32(startedAgentInEachSilo) <= expectedAgentCountMax); } catch { return false; } diff --git a/test/TesterAzureUtils/Persistence/PersistenceGrainTests_AzureBlobStore.cs b/test/TesterAzureUtils/Persistence/PersistenceGrainTests_AzureBlobStore.cs index 85f7ab5f520..1a763a9fafe 100644 --- a/test/TesterAzureUtils/Persistence/PersistenceGrainTests_AzureBlobStore.cs +++ b/test/TesterAzureUtils/Persistence/PersistenceGrainTests_AzureBlobStore.cs @@ -9,7 +9,7 @@ using Orleans.Runtime.Configuration; using TestExtensions; using Orleans.Hosting; -using Orleans.Storage; +using Orleans.Configuration; // ReSharper disable RedundantAssignment // ReSharper disable UnusedVariable diff --git a/test/TesterAzureUtils/Streaming/AQClientStreamTests.cs b/test/TesterAzureUtils/Streaming/AQClientStreamTests.cs index ad7891edd3a..020cae354ac 100644 --- a/test/TesterAzureUtils/Streaming/AQClientStreamTests.cs +++ b/test/TesterAzureUtils/Streaming/AQClientStreamTests.cs @@ -1,9 +1,14 @@ using System; using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Orleans; +using Orleans.Configuration; +using Orleans.Hosting; using Orleans.Providers.Streams.AzureQueue; using Orleans.Runtime; using Orleans.Runtime.Configuration; @@ -35,10 +40,36 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) builder.ConfigureLegacyConfiguration(legacy => { legacy.ClusterConfiguration.AddMemoryStorageProvider("PubSubStore"); - legacy.ClusterConfiguration.AddAzureQueueStreamProvider(AQStreamProviderName); legacy.ClusterConfiguration.Globals.ClientDropTimeout = TimeSpan.FromSeconds(5); - legacy.ClientConfiguration.AddAzureQueueStreamProvider(AQStreamProviderName); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); + } + + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddAzureQueueStreams(AQStreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); + } + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddAzureQueueStreams(AQStreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); + } } public override void Dispose() diff --git a/test/TesterAzureUtils/Streaming/AQProgrammaticSubscribeTest.cs b/test/TesterAzureUtils/Streaming/AQProgrammaticSubscribeTest.cs index 9f25e292c7f..e80b04709c4 100644 --- a/test/TesterAzureUtils/Streaming/AQProgrammaticSubscribeTest.cs +++ b/test/TesterAzureUtils/Streaming/AQProgrammaticSubscribeTest.cs @@ -1,5 +1,9 @@ using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Orleans.Configuration; +using Orleans.Hosting; using Orleans.Providers.Streams.AzureQueue; +using Orleans.Runtime; using Orleans.Runtime.Configuration; using Orleans.TestingHost; using Tester.StreamingTests; @@ -20,12 +24,29 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) { legacy.ClusterConfiguration.AddMemoryStorageProvider("Default"); legacy.ClusterConfiguration.AddMemoryStorageProvider("PubSubStore"); - legacy.ClusterConfiguration.AddAzureQueueStreamProviderV2(StreamProviderName); - legacy.ClusterConfiguration.AddAzureQueueStreamProviderV2(StreamProviderName2); }); + builder.AddSiloBuilderConfigurator(); } - public override void Dispose() + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddAzureQueueStreams(StreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }) + .AddAzureQueueStreams(StreamProviderName2, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); + } + } + + public override void Dispose() { base.Dispose(); var clusterId = this.HostedCluster?.Options.ClusterId; diff --git a/test/TesterAzureUtils/Streaming/AQStreamFilteringTests.cs b/test/TesterAzureUtils/Streaming/AQStreamFilteringTests.cs index 342f10bdd68..84abbc54b64 100644 --- a/test/TesterAzureUtils/Streaming/AQStreamFilteringTests.cs +++ b/test/TesterAzureUtils/Streaming/AQStreamFilteringTests.cs @@ -1,15 +1,17 @@ using System; using System.Threading.Tasks; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Orleans.Configuration; +using Orleans.Hosting; using Orleans.Providers.Streams.AzureQueue; +using Orleans.Runtime; using Orleans.Runtime.Configuration; using Orleans.TestingHost; using Tester.StreamingTests; using TestExtensions; using UnitTests.StreamingTests; using Xunit; -using Microsoft.Extensions.DependencyInjection; namespace Tester.AzureUtils.Streaming { @@ -26,9 +28,21 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) { legacy.ClusterConfiguration.AddMemoryStorageProvider("MemoryStore"); legacy.ClusterConfiguration.AddMemoryStorageProvider("PubSubStore"); - - legacy.ClusterConfiguration.AddAzureQueueStreamProvider(StreamProvider); }); + builder.AddSiloBuilderConfigurator(); + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddAzureQueueStreams(StreamProvider, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); + } } public override void Dispose() diff --git a/test/TesterAzureUtils/Streaming/AQStreamingTests.cs b/test/TesterAzureUtils/Streaming/AQStreamingTests.cs index 2e5e49ce90c..b5c86f83068 100644 --- a/test/TesterAzureUtils/Streaming/AQStreamingTests.cs +++ b/test/TesterAzureUtils/Streaming/AQStreamingTests.cs @@ -1,6 +1,9 @@ using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; +using Orleans; using Orleans.Configuration; using Orleans.Hosting; using Orleans.Providers.Streams.AzureQueue; @@ -30,11 +33,22 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) legacy.ClusterConfiguration.AddSimpleMessageStreamProvider(SmsStreamProviderName, fireAndForgetDelivery: false); legacy.ClientConfiguration.AddSimpleMessageStreamProvider(SmsStreamProviderName, fireAndForgetDelivery: false); - - legacy.ClusterConfiguration.AddAzureQueueStreamProviderV2(AzureQueueStreamProviderName); - legacy.ClientConfiguration.AddAzureQueueStreamProviderV2(AzureQueueStreamProviderName); }); builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); + } + + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddAzureQueueStreams(AzureQueueStreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); + } } private class SiloBuilderConfigurator : ISiloBuilderConfigurator @@ -49,11 +63,16 @@ public void Configure(ISiloHostBuilder hostBuilder) options.DeleteStateOnClear = true; })) .AddAzureTableGrainStorage("PubSubStore", builder => builder.Configure>((options, silo) => - { - options.ServiceId = silo.Value.ServiceId.ToString(); - options.ConnectionString = TestDefaultConfiguration.DataConnectionString; - options.DeleteStateOnClear = true; - })); + { + options.ServiceId = silo.Value.ServiceId.ToString(); + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + options.DeleteStateOnClear = true; + })) + .AddAzureQueueStreams(AzureQueueStreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); } } diff --git a/test/TesterAzureUtils/Streaming/AQSubscriptionMultiplicityTests.cs b/test/TesterAzureUtils/Streaming/AQSubscriptionMultiplicityTests.cs index 9da798554ce..b42e473b4c2 100644 --- a/test/TesterAzureUtils/Streaming/AQSubscriptionMultiplicityTests.cs +++ b/test/TesterAzureUtils/Streaming/AQSubscriptionMultiplicityTests.cs @@ -10,6 +10,11 @@ using Microsoft.Extensions.Logging.Abstractions; using UnitTests.StreamingTests; using Xunit; +using Microsoft.Extensions.Configuration; +using Orleans; +using Orleans.Hosting; +using Microsoft.Extensions.Options; +using Orleans.Configuration; namespace Tester.AzureUtils.Streaming { @@ -25,9 +30,35 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) builder.ConfigureLegacyConfiguration(legacy => { legacy.ClusterConfiguration.AddMemoryStorageProvider("PubSubStore"); - legacy.ClusterConfiguration.AddAzureQueueStreamProvider(AQStreamProviderName); - legacy.ClientConfiguration.AddAzureQueueStreamProvider(AQStreamProviderName); }); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); + } + + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddAzureQueueStreams(AQStreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); + } + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddAzureQueueStreams(AQStreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); + } } public AQSubscriptionMultiplicityTests() diff --git a/test/TesterAzureUtils/Streaming/AzureQueueAdapterTests.cs b/test/TesterAzureUtils/Streaming/AzureQueueAdapterTests.cs index 07003912d67..79beed73a48 100644 --- a/test/TesterAzureUtils/Streaming/AzureQueueAdapterTests.cs +++ b/test/TesterAzureUtils/Streaming/AzureQueueAdapterTests.cs @@ -7,17 +7,17 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.WindowsAzure.Storage.Queue; -using Orleans.Providers; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Orleans.Providers.Streams.AzureQueue; using Orleans.Providers.Streams.Common; using Orleans.Runtime; -using Orleans.Runtime.Configuration; using Orleans.Streams; using TestExtensions; using Xunit; -using Microsoft.Extensions.DependencyInjection; using Xunit.Abstractions; using Orleans.Configuration; +using Orleans.Serialization; namespace Tester.AzureUtils.Streaming { @@ -51,20 +51,18 @@ public void Dispose() [SkippableFact, TestCategory("Functional"), TestCategory("Halo")] public async Task SendAndReceiveFromAzureQueue() { - var properties = new Dictionary - { - {AzureQueueAdapterConstants.DataConnectionStringPropertyName, TestDefaultConfiguration.DataConnectionString}, - {AzureQueueAdapterConstants.DeploymentIdPropertyName, this.clusterId}, - {AzureQueueAdapterConstants.MessageVisibilityTimeoutPropertyName, "00:00:30" } - }; - var config = new ProviderConfiguration(properties, "type", "name"); - - var adapterFactory = new AzureQueueAdapterFactory(); - adapterFactory.Init(config, AZURE_QUEUE_STREAM_PROVIDER_NAME, this.fixture.Services); - await SendAndReceiveFromQueueAdapter(adapterFactory, config); + var options = new AzureQueueStreamOptions + { + ConnectionString = TestDefaultConfiguration.DataConnectionString, + ClusterId = this.clusterId, + MessageVisibilityTimeout = TimeSpan.FromSeconds(30) + }; + var adapterFactory = new AzureQueueAdapterFactory(AZURE_QUEUE_STREAM_PROVIDER_NAME, options, this.fixture.Services, this.fixture.Services.GetService>(), this.fixture.Services.GetRequiredService(), loggerFactory); + adapterFactory.Init(); + await SendAndReceiveFromQueueAdapter(adapterFactory); } - private async Task SendAndReceiveFromQueueAdapter(IQueueAdapterFactory adapterFactory, IProviderConfiguration config) + private async Task SendAndReceiveFromQueueAdapter(IQueueAdapterFactory adapterFactory) { IQueueAdapter adapter = await adapterFactory.CreateAdapter(); IQueueAdapterCache cache = adapterFactory.GetQueueAdapterCache(); diff --git a/test/TesterAzureUtils/Streaming/DelayedQueueRebalancingTests.cs b/test/TesterAzureUtils/Streaming/DelayedQueueRebalancingTests.cs index 611f265d848..274fc339e88 100644 --- a/test/TesterAzureUtils/Streaming/DelayedQueueRebalancingTests.cs +++ b/test/TesterAzureUtils/Streaming/DelayedQueueRebalancingTests.cs @@ -1,13 +1,15 @@ using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using Orleans.Configuration; +using Orleans.Hosting; using Orleans.Providers.Streams.AzureQueue; using Orleans.Providers.Streams.Common; using Orleans.Runtime; using Orleans.Runtime.Configuration; using Orleans.Streams; using Orleans.TestingHost; -using Orleans.TestingHost.Utils; using TestExtensions; using UnitTests.StreamingTests; using Xunit; @@ -19,7 +21,7 @@ public class DelayedQueueRebalancingTests : TestClusterPerTest { private const string adapterName = StreamTestsConstants.AZURE_QUEUE_STREAM_PROVIDER_NAME; #pragma warning disable 618 - private readonly string adapterType = typeof(AzureQueueStreamProvider).FullName; + private readonly string adapterType = typeof(PersistentStreamProvider).FullName; #pragma warning restore 618 private static readonly TimeSpan SILO_IMMATURE_PERIOD = TimeSpan.FromSeconds(40); // matches the config private static readonly TimeSpan LEEWAY = TimeSpan.FromSeconds(10); @@ -33,17 +35,26 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) builder.ConfigureLegacyConfiguration(legacy => { legacy.ClusterConfiguration.AddMemoryStorageProvider("PubSubStore"); - var persistentStreamProviderConfig = new PersistentStreamProviderConfig - { - SiloMaturityPeriod = SILO_IMMATURE_PERIOD, - BalancerType = StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer, - }; - - legacy.ClusterConfiguration.AddAzureQueueStreamProvider(adapterName, persistentStreamProviderConfig: persistentStreamProviderConfig); legacy.ClientConfiguration.Gateways = legacy.ClientConfiguration.Gateways.Take(1).ToList(); }); + builder.AddSiloBuilderConfigurator(); } - + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddAzureQueueStreams(adapterName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + options.SiloMaturityPeriod = SILO_IMMATURE_PERIOD; + options.BalancerType = StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer; + }); + } + } + public DelayedQueueRebalancingTests() { this.HostedCluster.StopSilo(this.HostedCluster.Silos.ElementAt(1)); diff --git a/test/TesterAzureUtils/Streaming/HaloStreamSubscribeTests.cs b/test/TesterAzureUtils/Streaming/HaloStreamSubscribeTests.cs index ce94d1158c2..f5a02d94384 100644 --- a/test/TesterAzureUtils/Streaming/HaloStreamSubscribeTests.cs +++ b/test/TesterAzureUtils/Streaming/HaloStreamSubscribeTests.cs @@ -39,9 +39,6 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) legacy.ClusterConfiguration.AddSimpleMessageStreamProvider("SMSProviderDoNotOptimizeForImmutableData", fireAndForgetDelivery: false, optimizeForImmutableData: false); - - legacy.ClusterConfiguration.AddAzureQueueStreamProvider(AzureQueueStreamProviderName); - legacy.ClusterConfiguration.AddAzureQueueStreamProvider("AzureQueueProvider2"); }); builder.AddSiloBuilderConfigurator(); } @@ -62,7 +59,17 @@ public void Configure(ISiloHostBuilder hostBuilder) options.ServiceId = silo.Value.ServiceId.ToString(); options.DeleteStateOnClear = true; options.ConnectionString = TestDefaultConfiguration.DataConnectionString; - })); + })) + .AddAzureQueueStreams(AzureQueueStreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }) + .AddAzureQueueStreams("AzureQueueProvider2", + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); } } diff --git a/test/TesterAzureUtils/Streaming/SampleAzureQueueStreamingTests.cs b/test/TesterAzureUtils/Streaming/SampleAzureQueueStreamingTests.cs index c3a7bdbd908..b5c8d1e03bd 100644 --- a/test/TesterAzureUtils/Streaming/SampleAzureQueueStreamingTests.cs +++ b/test/TesterAzureUtils/Streaming/SampleAzureQueueStreamingTests.cs @@ -13,6 +13,9 @@ using Microsoft.Extensions.Logging.Abstractions; using UnitTests.StreamingTests; using Xunit; +using Orleans.Hosting; +using Microsoft.Extensions.Options; +using Orleans.Configuration; namespace Tester.AzureUtils.Streaming { @@ -27,8 +30,21 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) builder.ConfigureLegacyConfiguration(legacy => { legacy.ClusterConfiguration.AddMemoryStorageProvider("PubSubStore"); - legacy.ClusterConfiguration.AddAzureQueueStreamProvider(StreamProvider); }); + builder.AddSiloBuilderConfigurator(); + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator + { + public void Configure(ISiloHostBuilder hostBuilder) + { + hostBuilder + .AddAzureQueueStreams(StreamProvider, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); + } } public override void Dispose() diff --git a/test/TesterAzureUtils/Streaming/StreamLifecycleTests.cs b/test/TesterAzureUtils/Streaming/StreamLifecycleTests.cs index 14b4a0e35ed..e662957fdea 100644 --- a/test/TesterAzureUtils/Streaming/StreamLifecycleTests.cs +++ b/test/TesterAzureUtils/Streaming/StreamLifecycleTests.cs @@ -14,6 +14,8 @@ using Orleans.Hosting; using Microsoft.Extensions.Options; using Orleans.Configuration; +using Microsoft.Extensions.Configuration; +using Orleans.Providers.Streams.AzureQueue; namespace UnitTests.StreamingTests { @@ -43,16 +45,26 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) fireAndForgetDelivery: false, optimizeForImmutableData: false); - legacy.ClusterConfiguration.AddAzureQueueStreamProvider(AzureQueueStreamProviderName); - legacy.ClusterConfiguration.AddAzureQueueStreamProvider("AzureQueueProvider2"); - legacy.ClientConfiguration.AddSimpleMessageStreamProvider(SmsStreamProviderName, fireAndForgetDelivery: false); - legacy.ClientConfiguration.AddAzureQueueStreamProvider(AzureQueueStreamProviderName); }); - builder.AddSiloBuilderConfigurator(); + builder.AddSiloBuilderConfigurator(); + builder.AddClientBuilderConfigurator(); } - private class SiloBuilderConfigurator : ISiloBuilderConfigurator + private class MyClientBuilderConfigurator : IClientBuilderConfigurator + { + public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) + { + clientBuilder + .AddAzureQueueStreams(AzureQueueStreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); + } + } + + private class MySiloBuilderConfigurator : ISiloBuilderConfigurator { public void Configure(ISiloHostBuilder hostBuilder) { @@ -68,7 +80,17 @@ public void Configure(ISiloHostBuilder hostBuilder) options.ServiceId = silo.Value.ServiceId.ToString(); options.DeleteStateOnClear = true; options.ConnectionString = TestDefaultConfiguration.DataConnectionString; - })); + })) + .AddAzureQueueStreams(AzureQueueStreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }) + .AddAzureQueueStreams("AzureQueueProvider2", + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); } } diff --git a/test/TesterAzureUtils/Streaming/StreamLimitTests.cs b/test/TesterAzureUtils/Streaming/StreamLimitTests.cs index c8debbac1cf..916b1bb006c 100644 --- a/test/TesterAzureUtils/Streaming/StreamLimitTests.cs +++ b/test/TesterAzureUtils/Streaming/StreamLimitTests.cs @@ -16,6 +16,7 @@ using Orleans.Hosting; using Microsoft.Extensions.Options; using Orleans.Configuration; +using Orleans.Providers.Streams.AzureQueue; namespace UnitTests.StreamingTests { @@ -50,9 +51,6 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) legacy.ClusterConfiguration.AddSimpleMessageStreamProvider("SMSProviderDoNotOptimizeForImmutableData", fireAndForgetDelivery: false, optimizeForImmutableData: false); - - legacy.ClusterConfiguration.AddAzureQueueStreamProvider(AzureQueueStreamProviderName); - legacy.ClusterConfiguration.AddAzureQueueStreamProvider("AzureQueueProvider2"); }); builder.AddSiloBuilderConfigurator(); } @@ -73,7 +71,17 @@ public void Configure(ISiloHostBuilder hostBuilder) options.ServiceId = silo.Value.ServiceId.ToString(); options.DeleteStateOnClear = true; options.ConnectionString = TestDefaultConfiguration.DataConnectionString; - })); + })) + .AddAzureQueueStreams(AzureQueueStreamProviderName, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }) + .AddAzureQueueStreams("AzureQueueProvider2", + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); } } diff --git a/test/TesterAzureUtils/Streaming/StreamReliabilityTests.cs b/test/TesterAzureUtils/Streaming/StreamReliabilityTests.cs index 11c32e1acca..cba92a18efe 100644 --- a/test/TesterAzureUtils/Streaming/StreamReliabilityTests.cs +++ b/test/TesterAzureUtils/Streaming/StreamReliabilityTests.cs @@ -56,11 +56,7 @@ protected override void ConfigureTestCluster(TestClusterBuilder builder) legacy.ClusterConfiguration.AddSimpleMessageStreamProvider(SMS_STREAM_PROVIDER_NAME, fireAndForgetDelivery: false); - legacy.ClusterConfiguration.AddAzureQueueStreamProvider(AZURE_QUEUE_STREAM_PROVIDER_NAME); - legacy.ClusterConfiguration.AddAzureQueueStreamProvider("AzureQueueProvider2"); - legacy.ClientConfiguration.AddSimpleMessageStreamProvider(SMS_STREAM_PROVIDER_NAME, fireAndForgetDelivery: false); - legacy.ClientConfiguration.AddAzureQueueStreamProvider(AZURE_QUEUE_STREAM_PROVIDER_NAME); }); builder.AddSiloBuilderConfigurator(); @@ -74,7 +70,12 @@ public void Configure(IConfiguration configuration, IClientBuilder clientBuilder clientBuilder.UseAzureStorageClustering(gatewayOptions => { gatewayOptions.ConnectionString = TestDefaultConfiguration.DataConnectionString; - }); + }) + .AddAzureQueueStreams(AZURE_QUEUE_STREAM_PROVIDER_NAME, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); } } @@ -98,7 +99,17 @@ public void Configure(ISiloHostBuilder hostBuilder) options.ServiceId = silo.Value.ServiceId.ToString(); options.DeleteStateOnClear = true; options.ConnectionString = TestDefaultConfiguration.DataConnectionString; - })); + })) + .AddAzureQueueStreams(AZURE_QUEUE_STREAM_PROVIDER_NAME, + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }) + .AddAzureQueueStreams("AzureQueueProvider2", + options => + { + options.ConnectionString = TestDefaultConfiguration.DataConnectionString; + }); } } diff --git a/test/TesterAzureUtils/Streaming/TestAzureQueueStreamProvider.cs b/test/TesterAzureUtils/Streaming/TestAzureQueueStreamProvider.cs deleted file mode 100644 index 8cb39492f38..00000000000 --- a/test/TesterAzureUtils/Streaming/TestAzureQueueStreamProvider.cs +++ /dev/null @@ -1,18 +0,0 @@ - -using Orleans.Providers.Streams.AzureQueue; -using Orleans.Providers.Streams.Common; -using Tester.TestStreamProviders; - -namespace Tester.AzureUtils.Streaming -{ - public class TestAzureQueueStreamProvider : PersistentStreamProvider - { - public class AdapterFactory : AzureQueueAdapterFactory - { - public AdapterFactory() - { - StreamFailureHandlerFactory = qid => TestAzureTableStorageStreamFailureHandler.Create(this.SerializationManager); - } - } - } -} diff --git a/test/TesterInternal/GeoClusterTests/TestingClusterHost.cs b/test/TesterInternal/GeoClusterTests/TestingClusterHost.cs index 56a92b17b64..6c8894b6883 100644 --- a/test/TesterInternal/GeoClusterTests/TestingClusterHost.cs +++ b/test/TesterInternal/GeoClusterTests/TestingClusterHost.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Orleans; using Orleans.Hosting; using Orleans.Runtime.Configuration; @@ -13,10 +13,7 @@ using Xunit; using Xunit.Abstractions; using Orleans.MultiCluster; -using Orleans.Runtime; -using Microsoft.Extensions.Logging; -using Orleans.TestingHost.Utils; -using Orleans.Storage; +using Orleans.Configuration; namespace Tests.GeoClusterTests { From 82c433513751f60ebc387a16a8ba54561cd430cc Mon Sep 17 00:00:00 2001 From: jason-bragg Date: Tue, 20 Feb 2018 13:25:37 -0800 Subject: [PATCH 2/2] Fixed plugable queue balancer test failures. - Was not setting the blancer type. --- .../PluggableQueueBalancerTestBase.cs | 6 ------ .../PluggableQueueBalancerTestsWithMemoryStreamProvider.cs | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestBase.cs b/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestBase.cs index 1598728ee79..00f2f4a95cb 100644 --- a/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestBase.cs +++ b/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestBase.cs @@ -13,12 +13,6 @@ public class PluggableQueueBalancerTestBase : OrleansTestingBase { private static Type QueueBalancerType = typeof(LeaseBasedQueueBalancerForTest); - public static PersistentStreamOptions ConfigWithCustomBalancerType(PersistentStreamOptions options) - { - options.BalancerType = QueueBalancerType; - return options; - } - public virtual async Task ShouldUseInjectedQueueBalancerAndBalanceCorrectly(BaseTestClusterFixture fixture, string streamProviderName, int siloCount, int totalQueueCount) { var leaseManager = fixture.GrainFactory.GetGrain(streamProviderName); diff --git a/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestsWithMemoryStreamProvider.cs b/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestsWithMemoryStreamProvider.cs index 95b38a959b9..b89d5f4b597 100644 --- a/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestsWithMemoryStreamProvider.cs +++ b/test/Tester/StreamingTests/PlugableQueueBalancerTests/PluggableQueueBalancerTestsWithMemoryStreamProvider.cs @@ -41,6 +41,7 @@ public void Configure(ISiloHostBuilder hostBuilder) .AddMemoryStreams(StreamProviderName, options => { options.TotalQueueCount = totalQueueCount; + options.BalancerType = typeof(LeaseBasedQueueBalancerForTest); }); } }