예제 #1
0
        public void GetBulkhead_WhenInitializingBulkheadAndMaxConcurrentConfigIsInvalid_AndThenConfigChangedToValidValue_CreatesBulkhead()
        {
            // Arrange

            var       key = AnyGroupKey;
            const int invalidMaxConcurrent = -1;
            const int validMaxConcurrent   = 1;

            var mockMetricEvents = new Mock <IMetricEvents>(MockBehavior.Strict);

            var mockConfig = new MjolnirConfiguration
            {
                BulkheadConfigurations = new Dictionary <string, BulkheadConfiguration>
                {
                    {
                        key.Name,
                        new BulkheadConfiguration
                        {
                            MaxConcurrent = invalidMaxConcurrent
                        }
                    }
                }
            };

            var mockLogFactory = new Mock <IMjolnirLogFactory>(MockBehavior.Strict);

            mockLogFactory.Setup(m => m.CreateLog <BulkheadFactory>()).Returns(new DefaultMjolnirLog <BulkheadFactory>());
            mockLogFactory.Setup(m => m.CreateLog <SemaphoreBulkheadHolder>()).Returns(new DefaultMjolnirLog <SemaphoreBulkheadHolder>());
            var factory = new BulkheadFactory(mockMetricEvents.Object, mockConfig, mockLogFactory.Object);

            try
            {
                factory.GetBulkhead(key);
            }
            catch (ArgumentOutOfRangeException)
            {
                // Expected, config is invalid for the first attempt.
            }

            mockConfig.BulkheadConfigurations = new Dictionary <string, BulkheadConfiguration>
            {
                {
                    key.Name,
                    new BulkheadConfiguration
                    {
                        MaxConcurrent = validMaxConcurrent
                    }
                }
            };
            mockConfig.NotifyAfterConfigUpdate();

            // Act

            var bulkhead = factory.GetBulkhead(key); // Should not throw.

            // Assert

            Assert.Equal(validMaxConcurrent, bulkhead.CountAvailable);
        }
        private async Task ReloadConfig()
        {
            while (true)
            {
                _root = LoadConfigFromJsonFile();

                // We can add some deep comparision between _currentConfig and new config here so
                // we notify our observers only when config really changes
                _currentConfig?.NotifyAfterConfigUpdate();

                await Task.Delay(_updateTimeInterval);
            }
        }
예제 #3
0
        public void GetBulkhead_ReturnsNewBulkheadWhenConfigChanges()
        {
            // Config can be used to resize the bulkhead at runtime, which results in a new
            // bulkhead being created.

            // To ensure consistency, callers who retrieve a bulkhead and call TryEnter()
            // on it should keep a local reference to the same bulkhead to later call
            // Release() on (rather than re-retrieving the bulkhead from the context).
            // That behavior is tested elsewhere (with the BulkheadInvoker tests).

            // Arrange

            var       key                  = AnyString;
            var       groupKey             = GroupKey.Named(key);
            const int initialExpectedCount = 5;
            const int newExpectedCount     = 6;

            var mockMetricEvents = new Mock <IMetricEvents>(MockBehavior.Strict);

            var mockConfig = new MjolnirConfiguration
            {
                BulkheadConfigurations = new Dictionary <string, BulkheadConfiguration>
                {
                    {
                        groupKey.Name,
                        new BulkheadConfiguration
                        {
                            MaxConcurrent = initialExpectedCount
                        }
                    }
                }
            };


            var mockLogFactory = new Mock <IMjolnirLogFactory>(MockBehavior.Strict);

            mockLogFactory.Setup(m => m.CreateLog <BulkheadFactory>()).Returns(new DefaultMjolnirLog <BulkheadFactory>());
            mockLogFactory.Setup(m => m.CreateLog <SemaphoreBulkheadHolder>()).Returns(new DefaultMjolnirLog <SemaphoreBulkheadHolder>());
            var factory = new BulkheadFactory(mockMetricEvents.Object, mockConfig, mockLogFactory.Object);

            // Act

            var firstBulkhead = factory.GetBulkhead(groupKey);

            mockConfig.BulkheadConfigurations = new Dictionary <string, BulkheadConfiguration>
            {
                {
                    groupKey.Name,
                    new BulkheadConfiguration
                    {
                        MaxConcurrent = newExpectedCount
                    }
                }
            };
            mockConfig.NotifyAfterConfigUpdate();

            // Give the change handler callback enough time to create and reassign the bulkhead.
            Thread.Sleep(500);

            var secondBulkhead = factory.GetBulkhead(groupKey);

            // Assert

            // Shouldn't change any existing referenced bulkheads...
            Assert.Equal(initialExpectedCount, firstBulkhead.CountAvailable);

            // ...but newly-retrieved bulkheads should get a new instance
            // with the updated count.
            Assert.Equal(newExpectedCount, secondBulkhead.CountAvailable);

            // And they shouldn't be the same bulkhead (which should be obvious by this point).
            Assert.False(firstBulkhead == secondBulkhead);
        }