mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 20:30:50 +08:00 
			
		
		
		
	implemented a send to self pattern for sticky session timeouts rather than a normal timer
This commit is contained in:
		@@ -7,11 +7,11 @@ namespace Ocelot.UnitTests.Infrastructure
 | 
			
		||||
{
 | 
			
		||||
    public class InMemoryBusTests
 | 
			
		||||
    {
 | 
			
		||||
        private InMemoryBus<Message> _bus;
 | 
			
		||||
        private readonly InMemoryBus<object> _bus;
 | 
			
		||||
 | 
			
		||||
        public InMemoryBusTests()
 | 
			
		||||
        {
 | 
			
		||||
            _bus = new InMemoryBus<Message>();
 | 
			
		||||
            _bus = new InMemoryBus<object>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
@@ -21,26 +21,20 @@ namespace Ocelot.UnitTests.Infrastructure
 | 
			
		||||
            _bus.Subscribe(x => {
 | 
			
		||||
                called = true;
 | 
			
		||||
            });
 | 
			
		||||
            await _bus.Publish(new Message(), 1);
 | 
			
		||||
            _bus.Publish(new object(), 1);
 | 
			
		||||
            await Task.Delay(10);
 | 
			
		||||
            called.ShouldBeTrue();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public async Task should_not_be_publish_yet_as_no_delay_in_caller()
 | 
			
		||||
        public void should_not_be_publish_yet_as_no_delay_in_caller()
 | 
			
		||||
        {
 | 
			
		||||
            var called = false;
 | 
			
		||||
            _bus.Subscribe(x => {
 | 
			
		||||
                called = true;
 | 
			
		||||
            });
 | 
			
		||||
            await _bus.Publish(new Message(), 1);
 | 
			
		||||
            _bus.Publish(new object(), 1);
 | 
			
		||||
            called.ShouldBeFalse();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        class Message
 | 
			
		||||
        {
 | 
			
		||||
            
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
namespace Ocelot.UnitTests.LoadBalancer
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Threading.Tasks;
 | 
			
		||||
    using Ocelot.LoadBalancer.LoadBalancers;
 | 
			
		||||
    using Ocelot.Responses;
 | 
			
		||||
@@ -25,13 +26,13 @@ namespace Ocelot.UnitTests.LoadBalancer
 | 
			
		||||
        private Response<ServiceHostAndPort> _result;
 | 
			
		||||
        private Response<ServiceHostAndPort> _firstHostAndPort;
 | 
			
		||||
        private Response<ServiceHostAndPort> _secondHostAndPort;
 | 
			
		||||
        private IBus<StickySession> _bus;
 | 
			
		||||
        private readonly FakeBus<StickySession> _bus;
 | 
			
		||||
 | 
			
		||||
        public CookieStickySessionsTests()
 | 
			
		||||
        {
 | 
			
		||||
            _bus = new InMemoryBus<StickySession>();
 | 
			
		||||
            _bus = new FakeBus<StickySession>();
 | 
			
		||||
            _loadBalancer = new Mock<ILoadBalancer>();
 | 
			
		||||
            _defaultExpiryInMs = 100;
 | 
			
		||||
            _defaultExpiryInMs = 0;
 | 
			
		||||
            _stickySessions = new CookieStickySessions(_loadBalancer.Object, "sessionid", _defaultExpiryInMs, _bus);
 | 
			
		||||
            _downstreamContext = new DownstreamContext(new DefaultHttpContext());
 | 
			
		||||
        }
 | 
			
		||||
@@ -52,6 +53,7 @@ namespace Ocelot.UnitTests.LoadBalancer
 | 
			
		||||
                .And(_ => GivenTheDownstreamRequestHasSessionId("321"))
 | 
			
		||||
                .When(_ => WhenILeaseTwiceInARow())
 | 
			
		||||
                .Then(_ => ThenTheFirstAndSecondResponseAreTheSame())
 | 
			
		||||
                .And(_ => ThenTheStickySessionWillTimeout())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -73,94 +75,12 @@ namespace Ocelot.UnitTests.LoadBalancer
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_expire_sticky_session()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(_ => GivenTheLoadBalancerReturnsSequence())
 | 
			
		||||
                .When(_ => WhenTheStickySessionExpires())
 | 
			
		||||
                .Then(_ => ThenANewHostAndPortIsReturned())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_refresh_sticky_session()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(_ => GivenTheLoadBalancerReturnsSequence())
 | 
			
		||||
                .When(_ => WhenIMakeRequestsToKeepRefreshingTheSession())
 | 
			
		||||
                .Then(_ => ThenTheSessionIsRefreshed())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_dispose()
 | 
			
		||||
        {
 | 
			
		||||
            _stickySessions.Dispose();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_release()
 | 
			
		||||
        {
 | 
			
		||||
            _stickySessions.Release(new ServiceHostAndPort("", 0));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task ThenTheSessionIsRefreshed()
 | 
			
		||||
        {
 | 
			
		||||
            var postExpireHostAndPort = await _stickySessions.Lease(_downstreamContext);
 | 
			
		||||
            postExpireHostAndPort.Data.DownstreamHost.ShouldBe("one");
 | 
			
		||||
            postExpireHostAndPort.Data.DownstreamPort.ShouldBe(80);
 | 
			
		||||
 | 
			
		||||
            _loadBalancer
 | 
			
		||||
                .Verify(x => x.Lease(It.IsAny<DownstreamContext>()), Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task WhenIMakeRequestsToKeepRefreshingTheSession()
 | 
			
		||||
        {
 | 
			
		||||
            var context = new DefaultHttpContext();
 | 
			
		||||
            var cookies = new FakeCookies();
 | 
			
		||||
            cookies.AddCookie("sessionid", "321");
 | 
			
		||||
            context.Request.Cookies = cookies;
 | 
			
		||||
            _downstreamContext = new DownstreamContext(context);
 | 
			
		||||
 | 
			
		||||
            var firstHostAndPort = await _stickySessions.Lease(_downstreamContext);
 | 
			
		||||
            firstHostAndPort.Data.DownstreamHost.ShouldBe("one");
 | 
			
		||||
            firstHostAndPort.Data.DownstreamPort.ShouldBe(80);
 | 
			
		||||
 | 
			
		||||
            Thread.Sleep(80);
 | 
			
		||||
 | 
			
		||||
            var secondHostAndPort = await _stickySessions.Lease(_downstreamContext);
 | 
			
		||||
            secondHostAndPort.Data.DownstreamHost.ShouldBe("one");
 | 
			
		||||
            secondHostAndPort.Data.DownstreamPort.ShouldBe(80);
 | 
			
		||||
 | 
			
		||||
            Thread.Sleep(80);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task ThenANewHostAndPortIsReturned()
 | 
			
		||||
        {
 | 
			
		||||
            var postExpireHostAndPort = await _stickySessions.Lease(_downstreamContext);
 | 
			
		||||
            postExpireHostAndPort.Data.DownstreamHost.ShouldBe("two");
 | 
			
		||||
            postExpireHostAndPort.Data.DownstreamPort.ShouldBe(80);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task WhenTheStickySessionExpires()
 | 
			
		||||
        {
 | 
			
		||||
            var context = new DefaultHttpContext();
 | 
			
		||||
            var cookies = new FakeCookies();
 | 
			
		||||
            cookies.AddCookie("sessionid", "321");
 | 
			
		||||
            context.Request.Cookies = cookies;
 | 
			
		||||
            _downstreamContext = new DownstreamContext(context);
 | 
			
		||||
 | 
			
		||||
            var firstHostAndPort = await _stickySessions.Lease(_downstreamContext);
 | 
			
		||||
            var secondHostAndPort = await _stickySessions.Lease(_downstreamContext);
 | 
			
		||||
 | 
			
		||||
            firstHostAndPort.Data.DownstreamHost.ShouldBe("one");
 | 
			
		||||
            firstHostAndPort.Data.DownstreamPort.ShouldBe(80);
 | 
			
		||||
 | 
			
		||||
            secondHostAndPort.Data.DownstreamHost.ShouldBe("one");
 | 
			
		||||
            secondHostAndPort.Data.DownstreamPort.ShouldBe(80);
 | 
			
		||||
 | 
			
		||||
            Thread.Sleep(300);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenAnErrorIsReturned()
 | 
			
		||||
        {
 | 
			
		||||
            _result.IsError.ShouldBeTrue();
 | 
			
		||||
@@ -240,9 +160,14 @@ namespace Ocelot.UnitTests.LoadBalancer
 | 
			
		||||
        {
 | 
			
		||||
            _result.Data.ShouldNotBeNull();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheStickySessionWillTimeout()
 | 
			
		||||
        {
 | 
			
		||||
            _bus.Messages.Count.ShouldBe(2);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    class FakeCookies : IRequestCookieCollection
 | 
			
		||||
 | 
			
		||||
    internal class FakeCookies : IRequestCookieCollection
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Dictionary<string, string> _cookies = new Dictionary<string, string>();
 | 
			
		||||
 | 
			
		||||
@@ -277,4 +202,23 @@ namespace Ocelot.UnitTests.LoadBalancer
 | 
			
		||||
            return _cookies.GetEnumerator();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal class FakeBus<T> : IBus<T>
 | 
			
		||||
    {
 | 
			
		||||
        public FakeBus()
 | 
			
		||||
        {
 | 
			
		||||
            Messages = new List<T>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public List<T> Messages { get; }
 | 
			
		||||
 | 
			
		||||
        public void Subscribe(Action<T> action)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Publish(T message, int delay)
 | 
			
		||||
        {
 | 
			
		||||
            Messages.Add(message);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user