public async Task TestSetEndpoint() { var endpoint1 = new TestEndpoint("id"); var endpoint2 = new NullEndpoint("id"); var endpoint3 = new TestEndpoint("id1"); ICheckpointer checkpointer = await Checkpointer.CreateAsync("cid", new CheckpointStore()); var endpointExecutorConfig = new EndpointExecutorConfig(TimeSpan.FromHours(1), RetryStrategy.NoRetry, TimeSpan.FromHours(1)); var asyncEndpointExecutorOptions = new AsyncEndpointExecutorOptions(1, TimeSpan.FromSeconds(1)); var messageStore = new TestMessageStore(); var executor = new StoringAsyncEndpointExecutor(endpoint1, checkpointer, endpointExecutorConfig, asyncEndpointExecutorOptions, messageStore); Assert.Equal(endpoint1, executor.Endpoint); await Assert.ThrowsAsync <ArgumentNullException>(() => executor.SetEndpoint(null)); await Assert.ThrowsAsync <ArgumentException>(() => executor.SetEndpoint(endpoint3)); await executor.SetEndpoint(endpoint2); Assert.Equal(endpoint2, executor.Endpoint); await executor.CloseAsync(); await Assert.ThrowsAsync <InvalidOperationException>(() => executor.SetEndpoint(endpoint1)); }
public async Task PumpMessagesTest() { // Arrange const int MessagesCount = 10; const string EndpointId = "endpoint1"; var endpoint = new TestEndpoint(EndpointId); ICheckpointer checkpointer = await Checkpointer.CreateAsync(EndpointId, new CheckpointStore()); var endpointExecutorConfig = new EndpointExecutorConfig(TimeSpan.FromHours(1), RetryStrategy.NoRetry, TimeSpan.FromHours(1)); var asyncEndpointExecutorOptions = new AsyncEndpointExecutorOptions(4, TimeSpan.FromSeconds(2)); var messageStore = new TestMessageStore(); var storingAsyncEndpointExecutor = new StoringAsyncEndpointExecutor(endpoint, checkpointer, endpointExecutorConfig, asyncEndpointExecutorOptions, messageStore); IEnumerable <IMessage> messages = GetNewMessages(MessagesCount, 0); // Act - Send messages to invoke foreach (IMessage message in messages) { await storingAsyncEndpointExecutor.Invoke(message); } await Task.Delay(TimeSpan.FromSeconds(10)); // Assert - Make sure the endpoint received all the messages. Assert.Equal(MessagesCount, endpoint.N); for (int i = 0; i < MessagesCount; i++) { IMessage message = endpoint.Processed[i]; Assert.True(message.Properties.ContainsKey($"key{i}")); Assert.Equal($"value{i}", message.Properties[$"key{i}"]); } }
public async Task InvokeTest() { // Arrange const int MessagesCount = 10; const string EndpointId = "endpoint1"; var endpoint = new NullEndpoint(EndpointId); var priorities = new List <uint>() { 0, 1, 2, 100, 101, 102 }; var checkpointer = new NullCheckpointer(); var endpointExecutorConfig = new EndpointExecutorConfig(TimeSpan.FromHours(1), RetryStrategy.NoRetry, TimeSpan.FromHours(1)); var asyncEndpointExecutorOptions = new AsyncEndpointExecutorOptions(10); var messageStore = new TestMessageStore(); var storingAsyncEndpointExecutor = new StoringAsyncEndpointExecutor(endpoint, priorities, checkpointer, endpointExecutorConfig, asyncEndpointExecutorOptions, messageStore); IEnumerable <IMessage> messages = GetNewMessages(MessagesCount, 0); // Act - Send messages to invoke foreach (IMessage message in messages) { await storingAsyncEndpointExecutor.Invoke(message, 0, 3600); } // Assert - Check that the message store received the messages sent to invoke. List <IMessage> storeMessages = messageStore.GetReceivedMessagesForEndpoint(EndpointId); Assert.NotNull(storeMessages); Assert.Equal(MessagesCount, storeMessages.Count); for (int i = 0; i < MessagesCount; i++) { IMessage message = storeMessages[i]; Assert.True(message.Properties.ContainsKey($"key{i}")); Assert.Equal($"value{i}", message.Properties[$"key{i}"]); } // Assert - Make sure no additional / duplicate messages were sent. storeMessages = messageStore.GetReceivedMessagesForEndpoint(EndpointId); Assert.NotNull(storeMessages); Assert.Equal(10, storeMessages.Count); // Act - Send messages again to Invoke. messages = GetNewMessages(MessagesCount, MessagesCount); foreach (IMessage message in messages) { await storingAsyncEndpointExecutor.Invoke(message, 0, 3600); } // Assert - Make sure the store now has the old and the new messages. storeMessages = messageStore.GetReceivedMessagesForEndpoint(EndpointId); Assert.NotNull(storeMessages); Assert.Equal(MessagesCount * 2, storeMessages.Count); for (int i = 0; i < MessagesCount * 2; i++) { IMessage message = storeMessages[i]; Assert.True(message.Properties.ContainsKey($"key{i}")); Assert.Equal($"value{i}", message.Properties[$"key{i}"]); } }
static async Task <(IEdgeHub, IConnectionManager)> SetupEdgeHub(IEnumerable <string> routes, IoTHub iotHub, string edgeDeviceId) { string iotHubName = "testHub"; Routing.UserMetricLogger = NullRoutingUserMetricLogger.Instance; Routing.PerfCounter = NullRoutingPerfCounter.Instance; Routing.UserAnalyticsLogger = NullUserAnalyticsLogger.Instance; RetryStrategy defaultRetryStrategy = new FixedInterval(0, TimeSpan.FromSeconds(1)); TimeSpan defaultRevivePeriod = TimeSpan.FromHours(1); TimeSpan defaultTimeout = TimeSpan.FromSeconds(60); var endpointExecutorConfig = new EndpointExecutorConfig(defaultTimeout, defaultRetryStrategy, defaultRevivePeriod, true); var cloudProxy = new Mock <ICloudProxy>(); cloudProxy.Setup(c => c.SendMessageAsync(It.IsAny <IMessage>())).Callback <IMessage>(m => iotHub.ReceivedMessages.Add(m)).Returns(Task.CompletedTask); cloudProxy.Setup(c => c.SendMessageBatchAsync(It.IsAny <IEnumerable <IMessage> >())).Callback <IEnumerable <IMessage> >(m => iotHub.ReceivedMessages.AddRange(m)).Returns(Task.CompletedTask); cloudProxy.Setup(c => c.UpdateReportedPropertiesAsync(It.IsAny <IMessage>())).Callback <IMessage>(m => iotHub.ReceivedMessages.Add(m)).Returns(Task.CompletedTask); cloudProxy.SetupGet(c => c.IsActive).Returns(true); var cloudConnection = Mock.Of <ICloudConnection>(c => c.IsActive && c.CloudProxy == Option.Some(cloudProxy.Object)); var cloudConnectionProvider = new Mock <ICloudConnectionProvider>(); cloudConnectionProvider.Setup(c => c.Connect(It.IsAny <IClientCredentials>(), It.IsAny <Action <string, CloudConnectionStatus> >())).ReturnsAsync(Try.Success(cloudConnection)); var deviceConnectivityManager = Mock.Of <IDeviceConnectivityManager>(); IConnectionManager connectionManager = new ConnectionManager(cloudConnectionProvider.Object, Mock.Of <ICredentialsCache>(), new IdentityProvider(iotHubName), deviceConnectivityManager); var routingMessageConverter = new RoutingMessageConverter(); RouteFactory routeFactory = new EdgeRouteFactory(new EndpointFactory(connectionManager, routingMessageConverter, edgeDeviceId, 10, 10)); IEnumerable <Route> routesList = routeFactory.Create(routes).ToList(); IEnumerable <Endpoint> endpoints = routesList.Select(r => r.Endpoint); var routerConfig = new RouterConfig(endpoints, routesList); IDbStoreProvider dbStoreProvider = new InMemoryDbStoreProvider(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); IMessageStore messageStore = new MessageStore(storeProvider, CheckpointStore.Create(storeProvider), TimeSpan.MaxValue); IEndpointExecutorFactory endpointExecutorFactory = new StoringAsyncEndpointExecutorFactory(endpointExecutorConfig, new AsyncEndpointExecutorOptions(1, TimeSpan.FromMilliseconds(10)), messageStore); Router router = await Router.CreateAsync(Guid.NewGuid().ToString(), iotHubName, routerConfig, endpointExecutorFactory); ITwinManager twinManager = new TwinManager(connectionManager, new TwinCollectionMessageConverter(), new TwinMessageConverter(), Option.None <IEntityStore <string, TwinInfo> >()); var invokeMethodHandler = Mock.Of <IInvokeMethodHandler>(); var subscriptionProcessor = new SubscriptionProcessor(connectionManager, invokeMethodHandler, deviceConnectivityManager); IEdgeHub edgeHub = new RoutingEdgeHub(router, routingMessageConverter, connectionManager, twinManager, edgeDeviceId, invokeMethodHandler, subscriptionProcessor); return(edgeHub, connectionManager); }
public async Task TestFailedEndpoint() { var retryStrategy = new FixedInterval(10, TimeSpan.FromSeconds(1)); TimeSpan revivePeriod = TimeSpan.FromHours(1); TimeSpan execTimeout = TimeSpan.FromSeconds(60); var config = new EndpointExecutorConfig(execTimeout, retryStrategy, revivePeriod, true); var factory = new SyncEndpointExecutorFactory(config); var endpoint = new FailedEndpoint("endpoint1"); var endpoints = new Dictionary <Endpoint, IList <uint> > { { endpoint, new List <uint>() { 0 } } }; using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1))) { Dispatcher dispatcher = await Dispatcher.CreateAsync("dispatcher", "hub", endpoints, factory); // Because the buffer size is one and we are failing we should block on the dispatch Task dispatching = dispatcher.DispatchAsync(Message1, new HashSet <RouteResult> { new RouteResult(endpoint, 0, 3600) }); var endpoint2 = new TestEndpoint("endpoint1"); Task setting = dispatcher.SetEndpoint(endpoint2, new List <uint>() { 0 }); Task timeout = Task.Delay(TimeSpan.FromSeconds(1), cts.Token); await Task.WhenAny(dispatching, setting, timeout); await dispatcher.CloseAsync(CancellationToken.None); var expected = new List <IMessage> { Message1 }; Assert.Equal(expected, endpoint2.Processed); } }
public async Task TestFailedEndpoint() { var message1 = new Message(TelemetryMessageSource.Instance, new byte[] { 1, 2, 3 }, new Dictionary <string, string> { { "key1", "value1" }, { "key2", "value2" } }); var retryStrategy = new FixedInterval(10, TimeSpan.FromSeconds(1)); TimeSpan revivePeriod = TimeSpan.FromHours(1); TimeSpan execTimeout = TimeSpan.FromSeconds(60); var config = new EndpointExecutorConfig(execTimeout, retryStrategy, revivePeriod, true); var factory = new SyncEndpointExecutorFactory(config); var endpoint = new FailedEndpoint("endpoint1"); var endpoints = new HashSet <Endpoint> { endpoint }; var route = new Route("route1", "true", "hub", TelemetryMessageSource.Instance, endpoints); using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1))) using (Router router = await Router.CreateAsync("router1", "hub", new RouterConfig(endpoints, new HashSet <Route> { route }, Fallback), factory)) { // Because the buffer size is one and we are failing we should block on the dispatch Task routing = router.RouteAsync(message1); var endpoint2 = new TestEndpoint("endpoint1"); var newRoute = new Route("id", "true", "hub", TelemetryMessageSource.Instance, new HashSet <Endpoint> { endpoint2 }); Task setting = router.SetRoute(newRoute); Task timeout = Task.Delay(TimeSpan.FromSeconds(1), cts.Token); await Task.WhenAny(routing, setting, timeout); await router.CloseAsync(CancellationToken.None); var expected = new List <IMessage> { message1 }; Assert.Equal(expected, endpoint2.Processed); } }
public async Task TestCancellation() { var retryStrategy = new FixedInterval(10, TimeSpan.FromSeconds(1)); TimeSpan revivePeriod = TimeSpan.FromHours(1); TimeSpan execTimeout = TimeSpan.FromSeconds(60); var config = new EndpointExecutorConfig(execTimeout, retryStrategy, revivePeriod, true); var endpoint = new FailedEndpoint("id"); IProcessor processor = endpoint.CreateProcessor(); Assert.Equal(endpoint, processor.Endpoint); IEndpointExecutor executor = new SyncEndpointExecutor(endpoint, new NullCheckpointer(), config); Task running = executor.Invoke(Default); await executor.CloseAsync(); await running; Assert.True(running.IsCompleted); }
public EndpointExecutorFsm(Endpoint endpoint, ICheckpointer checkpointer, EndpointExecutorConfig config, ISystemTime systemTime) { this.processor = Preconditions.CheckNotNull(endpoint).CreateProcessor(); this.Checkpointer = Preconditions.CheckNotNull(checkpointer); this.config = Preconditions.CheckNotNull(config); this.systemTime = Preconditions.CheckNotNull(systemTime); this.retryTimer = new Timer(this.RetryAsync, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); this.retryPeriod = Timeout.InfiniteTimeSpan; this.lastFailedRevivalTime = checkpointer.LastFailedRevivalTime; this.unhealthySince = checkpointer.UnhealthySince; if (checkpointer.LastFailedRevivalTime.HasValue) { this.state = State.DeadIdle; this.retryAttempts = short.MaxValue; // setting to some big value } else { this.state = State.Idle; } }
public async Task TestSetEndpoint() { var endpoint1 = new TestEndpoint("id"); var endpoint2 = new NullEndpoint("id"); var endpoint3 = new TestEndpoint("id1"); var priorities = new List <uint>() { 100, 101, 102, 0, 1, 2 }; var checkpointerFactory = new NullCheckpointerFactory(); var endpointExecutorConfig = new EndpointExecutorConfig(TimeSpan.FromHours(1), RetryStrategy.NoRetry, TimeSpan.FromHours(1)); var asyncEndpointExecutorOptions = new AsyncEndpointExecutorOptions(1, TimeSpan.FromSeconds(1)); var messageStore = new TestMessageStore(); var executor = new StoringAsyncEndpointExecutor(endpoint1, checkpointerFactory, endpointExecutorConfig, asyncEndpointExecutorOptions, messageStore); await executor.UpdatePriorities(priorities, Option.None <Endpoint>()); Assert.Equal(endpoint1, executor.Endpoint); await Assert.ThrowsAsync <ArgumentNullException>(() => executor.SetEndpoint(null, new List <uint>() { 0 })); await Assert.ThrowsAsync <ArgumentNullException>(() => executor.SetEndpoint(endpoint1, null)); await Assert.ThrowsAsync <ArgumentException>(() => executor.SetEndpoint(endpoint3, new List <uint>() { 0 })); await executor.SetEndpoint(endpoint2, new List <uint>() { 103, 104, 105, 0, 1, 2, 2 }); Assert.Equal(endpoint2, executor.Endpoint); await executor.CloseAsync(); await Assert.ThrowsAsync <InvalidOperationException>(() => executor.SetEndpoint(endpoint1, new List <uint>() { 0 })); }
public async Task PumpMessagesWithLargeIncomingBatchTest() { // Arrange const int MessagesCount = 200; const string EndpointId = "endpoint1"; const int RoutingPumpBatchSize = 10; var endpoint = new TestEndpoint(EndpointId); var priorities = new List <uint>() { 0, 1, 2, 100, 101, 102 }; var checkpointerFactory = new NullCheckpointerFactory(); var endpointExecutorConfig = new EndpointExecutorConfig(TimeSpan.FromHours(1), RetryStrategy.NoRetry, TimeSpan.FromHours(1)); var asyncEndpointExecutorOptions = new AsyncEndpointExecutorOptions(RoutingPumpBatchSize, TimeSpan.FromMilliseconds(1)); var messageStore = new TestMessageStore(); var storingAsyncEndpointExecutor = new StoringAsyncEndpointExecutor(endpoint, checkpointerFactory, endpointExecutorConfig, asyncEndpointExecutorOptions, messageStore); await storingAsyncEndpointExecutor.UpdatePriorities(priorities, Option.None <Endpoint>()); IEnumerable <IMessage> messages = GetNewMessages(MessagesCount, 0); // Act - Send messages to invoke foreach (IMessage message in messages) { await storingAsyncEndpointExecutor.Invoke(message, 0, 3600); } await Task.Delay(TimeSpan.FromSeconds(10)); // Assert - Make sure the endpoint received all the messages. Assert.Equal(MessagesCount, endpoint.N); for (int i = 0; i < MessagesCount; i++) { IMessage message = endpoint.Processed[i]; Assert.True(message.Properties.ContainsKey($"key{i}")); Assert.Equal($"value{i}", message.Properties[$"key{i}"]); } }
public async Task <IEndpointExecutor> CreateAsync(Endpoint endpoint, ICheckpointer checkpointer, EndpointExecutorConfig endpointExecutorConfig) { IEndpointExecutor exec = await this.underlying.CreateAsync(endpoint, checkpointer, endpointExecutorConfig); await exec.CloseAsync(); return(exec); }
public Task <IEndpointExecutor> CreateAsync(Endpoint endpoint, ICheckpointer checkpointer, EndpointExecutorConfig endpointExecutorConfig) { return(this.executorFactory.CreateAsync(endpoint, checkpointer, endpointExecutorConfig)); }
public Task <IEndpointExecutor> CreateAsync(Endpoint endpoint, IList <uint> priorities, ICheckpointer checkpointer, EndpointExecutorConfig endpointExecutorConfig) { return(this.underlying.CreateAsync(endpoint, priorities, checkpointer, endpointExecutorConfig)); }
async Task <(IMessageConsumer, IMessageConsumer, NullBrokerConnector)> SetupEnvironment() { Routing.UserMetricLogger = NullRoutingUserMetricLogger.Instance; Routing.PerfCounter = NullRoutingPerfCounter.Instance; Routing.UserAnalyticsLogger = NullUserAnalyticsLogger.Instance; var defaultRetryStrategy = new FixedInterval(5, TimeSpan.FromSeconds(5)); var defaultRevivePeriod = TimeSpan.FromHours(1); var defaultTimeout = TimeSpan.FromSeconds(60); var endpointExecutorConfig = new EndpointExecutorConfig(defaultTimeout, defaultRetryStrategy, defaultRevivePeriod, true); var cloudProxyDispatcher = new BrokeredCloudProxyDispatcher(); var cloudConnectionProvider = new BrokeredCloudConnectionProvider(cloudProxyDispatcher); var identityProvider = new IdentityProvider(iotHubName); var deviceConnectivityManager = new BrokeredDeviceConnectivityManager(cloudProxyDispatcher); var connectionManager = new ConnectionManager(cloudConnectionProvider, Mock.Of <ICredentialsCache>(), new IdentityProvider(iotHubName), deviceConnectivityManager); var routingMessageConverter = new RoutingMessageConverter(); var routeFactory = new EdgeRouteFactory(new EndpointFactory(connectionManager, routingMessageConverter, edgeDeviceId, 10, 10)); var routesList = new[] { routeFactory.Create("FROM /messages INTO $upstream") }; var endpoints = routesList.Select(r => r.Endpoint); var routerConfig = new RouterConfig(endpoints, routesList); var dbStoreProvider = new InMemoryDbStoreProvider(); var storeProvider = new StoreProvider(dbStoreProvider); var messageStore = new MessageStore(storeProvider, CheckpointStore.Create(storeProvider), TimeSpan.MaxValue, false, 1800); var endpointExecutorFactory = new StoringAsyncEndpointExecutorFactory(endpointExecutorConfig, new AsyncEndpointExecutorOptions(1, TimeSpan.FromMilliseconds(10)), messageStore); var router = await Router.CreateAsync(Guid.NewGuid().ToString(), iotHubName, routerConfig, endpointExecutorFactory); var messageConverterProvider = new MessageConverterProvider( new Dictionary <Type, IMessageConverter>() { { typeof(Twin), new TwinMessageConverter() }, { typeof(TwinCollection), new TwinCollectionMessageConverter() } }); var twinManager = TwinManager.CreateTwinManager(connectionManager, messageConverterProvider, Option.None <IStoreProvider>()); var invokeMethodHandler = Mock.Of <IInvokeMethodHandler>(); var subscriptionProcessor = new SubscriptionProcessor(connectionManager, invokeMethodHandler, deviceConnectivityManager); var edgeHub = new RoutingEdgeHub(router, routingMessageConverter, connectionManager, twinManager, edgeDeviceId, edgeModuleName, invokeMethodHandler, subscriptionProcessor, Mock.Of <IDeviceScopeIdentitiesCache>()); var brokerConnector = new NullBrokerConnector(cloudProxyDispatcher); cloudProxyDispatcher.SetConnector(brokerConnector); cloudProxyDispatcher.BindEdgeHub(edgeHub); var connectionProvider = new ConnectionProvider(connectionManager, edgeHub, TimeSpan.FromSeconds(30)); var authenticator = new NullAuthenticator(); var edgeHubIdentity = new ModuleIdentity(iotHubName, edgeDeviceId, edgeModuleName); var tokenCredentials = new TokenCredentials(edgeHubIdentity, "qwerty", "test-product", Option.Some("test-model"), Option.None <string>(), false); var systemComponentProvider = new SystemComponentIdProvider(tokenCredentials); var connectionHandler = default(ConnectionHandler); connectionHandler = new ConnectionHandler( Task.FromResult <IConnectionProvider>(connectionProvider), Task.FromResult <IAuthenticator>(authenticator), identityProvider, systemComponentProvider, DeviceProxyFactory); DeviceProxy DeviceProxyFactory(IIdentity identity, bool isDirectClient) { return(new DeviceProxy(identity, isDirectClient, connectionHandler, Mock.Of <ITwinHandler>(), Mock.Of <IModuleToModuleMessageHandler>(), Mock.Of <ICloud2DeviceMessageHandler>(), Mock.Of <IDirectMethodHandler>())); } var cloud2DeviceMessageHandler = new Cloud2DeviceMessageHandler(connectionHandler); var moduleToModuleMessageHandler = new ModuleToModuleMessageHandler(connectionHandler, identityProvider, new ModuleToModuleResponseTimeout(TimeSpan.FromSeconds(10))); var directMethodHandler = new DirectMethodHandler(connectionHandler, identityProvider); var twinHandler = new TwinHandler(connectionHandler, identityProvider); var subscriptionChangeHandler = new SubscriptionChangeHandler( cloud2DeviceMessageHandler, moduleToModuleMessageHandler, directMethodHandler, twinHandler, connectionHandler, identityProvider); return(subscriptionChangeHandler, cloudProxyDispatcher, brokerConnector); }
public EndpointExecutorFsm(Endpoint endpoint, ICheckpointer checkpointer, EndpointExecutorConfig config) : this(endpoint, checkpointer, config, SystemTime.Instance) { }
public async Task MessagePrioritiesTest() { // Arrange const string EndpointId = "endpoint1"; const uint HighPri = 0; const uint NormalPri = 5; const uint LowPri = 10; var endpoint = new TestEndpoint(EndpointId); var priorities = new List <uint>() { HighPri, NormalPri, LowPri }; var checkpointerFactory = new NullCheckpointerFactory(); var endpointExecutorConfig = new EndpointExecutorConfig(TimeSpan.FromHours(1), RetryStrategy.DefaultFixed, TimeSpan.FromHours(1)); var asyncEndpointExecutorOptions = new AsyncEndpointExecutorOptions(4, TimeSpan.FromSeconds(2)); var messageStore = new TestMessageStore(); var storingAsyncEndpointExecutor = new StoringAsyncEndpointExecutor(endpoint, checkpointerFactory, endpointExecutorConfig, asyncEndpointExecutorOptions, messageStore); await storingAsyncEndpointExecutor.UpdatePriorities(priorities, Option.None <Endpoint>()); var normalPriMsg1 = new Message(TelemetryMessageSource.Instance, new byte[] { 1 }, new Dictionary <string, string> { { "normalPriority", string.Empty } }, 0L); var normalPriMsg2 = new Message(TelemetryMessageSource.Instance, new byte[] { 2 }, new Dictionary <string, string> { { "normalPriority", string.Empty } }, 1L); var normalPriMsg3 = new Message(TelemetryMessageSource.Instance, new byte[] { 3 }, new Dictionary <string, string> { { "normalPriority", string.Empty } }, 2L); var lowPriMsg1 = new Message(TelemetryMessageSource.Instance, new byte[] { 4 }, new Dictionary <string, string> { { "lowPriority", string.Empty } }, 3L); var lowPriMsg2 = new Message(TelemetryMessageSource.Instance, new byte[] { 5 }, new Dictionary <string, string> { { "lowPriority", string.Empty } }, 4L); var highPriMsg1 = new Message(TelemetryMessageSource.Instance, new byte[] { 6 }, new Dictionary <string, string> { { "highPriority", string.Empty } }, 5L); var normalPriMsg4 = new Message(TelemetryMessageSource.Instance, new byte[] { 7 }, new Dictionary <string, string> { { "normalPriority", string.Empty } }, 6L); var highPriMsg2 = new Message(TelemetryMessageSource.Instance, new byte[] { 8 }, new Dictionary <string, string> { { "highPriority", string.Empty } }, 7L); const int HighPriCount = 2; const int NormalPriCount = 4; const int LowPriCount = 2; // Disable the endpoint so messages are stuck in queue endpoint.CanProcess = false; // Send normal priority messages await storingAsyncEndpointExecutor.Invoke(normalPriMsg1, NormalPri, 3600); await storingAsyncEndpointExecutor.Invoke(normalPriMsg2, NormalPri, 3600); await storingAsyncEndpointExecutor.Invoke(normalPriMsg3, NormalPri, 3600); // Send low priority messages await storingAsyncEndpointExecutor.Invoke(lowPriMsg1, LowPri, 3600); await storingAsyncEndpointExecutor.Invoke(lowPriMsg2, LowPri, 3600); // Send the remaining messages mixed priority await storingAsyncEndpointExecutor.Invoke(highPriMsg1, HighPri, 3600); await storingAsyncEndpointExecutor.Invoke(normalPriMsg4, NormalPri, 3600); await storingAsyncEndpointExecutor.Invoke(highPriMsg2, HighPri, 3600); // Message store should have the messages in the corresponding queues var highPriQueue = messageStore.GetReceivedMessagesForEndpoint($"{endpoint.Id}_Pri{HighPri}"); Assert.Equal(2, highPriQueue.Count); Assert.Contains(highPriMsg1, highPriQueue); Assert.Contains(highPriMsg2, highPriQueue); var normalPriQueue = messageStore.GetReceivedMessagesForEndpoint($"{endpoint.Id}_Pri{NormalPri}"); Assert.Equal(4, normalPriQueue.Count); Assert.Contains(normalPriMsg1, normalPriQueue); Assert.Contains(normalPriMsg2, normalPriQueue); Assert.Contains(normalPriMsg3, normalPriQueue); Assert.Contains(normalPriMsg4, normalPriQueue); var lowPriQueue = messageStore.GetReceivedMessagesForEndpoint($"{endpoint.Id}_Pri{LowPri}"); Assert.Equal(2, lowPriQueue.Count); Assert.Contains(lowPriMsg1, lowPriQueue); Assert.Contains(lowPriMsg2, lowPriQueue); // Re-enable the endpoint and let the queues drain endpoint.CanProcess = true; await Task.Delay(TimeSpan.FromSeconds(10)); // Assert - Make sure the endpoint received all the messages // in the right priority order: // - HighPri messages should finish processing before others // - NormalPri messages should finish processing before LowPri Assert.Equal(8, endpoint.Processed.Count()); int highPriMessagesProcessed = 0; int normalPriMessagesProcessed = 0; int lowPriMessagesProcessed = 0; for (int i = 0; i < endpoint.Processed.Count(); i++) { IMessage message = endpoint.Processed[i]; if (message.Properties.ContainsKey($"highPriority")) { if (++highPriMessagesProcessed == HighPriCount) { // Found all the high-pri messages, // normal and low pri at this point // must not have completed yet Assert.True(normalPriMessagesProcessed < NormalPriCount); Assert.True(lowPriMessagesProcessed < LowPriCount); } } else if (message.Properties.ContainsKey($"normalPriority")) { if (++normalPriMessagesProcessed == NormalPriCount) { // Found all the normal-pri messages, // low pri messages at this point must // not have completed yet Assert.True(lowPriMessagesProcessed < LowPriCount); // High pri messages should have completed Assert.True(highPriMessagesProcessed == HighPriCount); } } else if (message.Properties.ContainsKey($"lowPriority")) { if (++lowPriMessagesProcessed == LowPriCount) { // Found all the low-pri messages, // high-pri and normal-pri should also // have completed before this Assert.True(highPriMessagesProcessed == HighPriCount); Assert.True(normalPriMessagesProcessed == NormalPriCount); } } else { // Bad test setup Assert.True(false, "Bad test setup, processed a message with unexpected priority"); } } }
public async Task <IEndpointExecutor> CreateAsync(Endpoint endpoint, IList <uint> priorities, ICheckpointerFactory checkpointerFactory, EndpointExecutorConfig endpointExecutorConfig) { IEndpointExecutor exec = await this.underlying.CreateAsync(endpoint, priorities, checkpointerFactory, endpointExecutorConfig); await exec.CloseAsync(); return(exec); }