public void DoNotCacheScheduledTimeoutsIfMaximumCachedTimeoutInFuture()
            {
                var now        = DateTime.UtcNow;
                var futureTime = now.AddMinutes(5);
                var sagaStore  = new Mock <IStoreSagas>();
                var cache      = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(20));

                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny <DateTime>())).Returns(new SagaTimeout[0]);
                SystemTime.OverrideWith(() => futureTime);
                cache.GetElapsedTimeouts();

                SystemTime.OverrideWith(() => now);
                cache.GetElapsedTimeouts();

                sagaStore.Verify(mock => mock.GetScheduledTimeouts(It.IsAny <DateTime>()), Times.Once());
            }
            public void CanTolerateCachingSameSagaReferenceMoreThanOnce()
            {
                var now         = DateTime.UtcNow;
                var futureTime  = now.AddMinutes(10);
                var sagaStore   = new Mock <IStoreSagas>();
                var cache       = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(5));
                var sagaTimeout = new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(), futureTime);

                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny <DateTime>())).Returns(new[] { sagaTimeout });

                SystemTime.OverrideWith(() => now);
                cache.GetElapsedTimeouts();

                SystemTime.OverrideWith(() => futureTime);
                cache.GetElapsedTimeouts();

                sagaStore.Verify(mock => mock.GetScheduledTimeouts(It.IsAny <DateTime>()), Times.Exactly(2));
            }
            public void ReturnEmptySetIfNoTimeoutsCached()
            {
                var now        = DateTime.UtcNow;
                var futureTime = now.AddMinutes(5);
                var sagaStore  = new Mock <IStoreSagas>();
                var cache      = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(20));

                SystemTime.OverrideWith(() => futureTime);
                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny <DateTime>())).Returns(new SagaTimeout[0]);

                Assert.Equal(0, cache.GetElapsedTimeouts().Count());
            }
            public void DoNotCacheTimeoutsFarInFuture()
            {
                var now         = DateTime.UtcNow;
                var sagaStore   = new Mock <IStoreSagas>();
                var cache       = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(5));
                var sagaTimeout = new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(), now.AddMinutes(10));

                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny <DateTime>())).Returns(new[] { sagaTimeout });

                SystemTime.OverrideWith(() => now);

                cache.GetElapsedTimeouts();
                cache.ScheduleTimeout(sagaTimeout);

                Assert.Equal(0, cache.Count);
            }
            public void ReturnNextScheduledTimeoutIfCacheHasItems()
            {
                var now         = DateTime.UtcNow;
                var nextTimeout = now.AddMinutes(1);
                var sagaStore   = new Mock <IStoreSagas>();
                var cache       = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(10));

                SystemTime.OverrideWith(() => now);
                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny <DateTime>())).Returns(new[] {
                    new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(), nextTimeout),
                    new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(), nextTimeout.AddMinutes(5))
                });

                //NOTE: Because we are using an overriden SystemTime; the get will not actually clear out the cached items.
                Assert.Equal(0, cache.GetElapsedTimeouts().Count());
                Assert.Equal(nextTimeout, cache.GetNextScheduledTimeout());
            }
            public void ReturnNextScheduledTimeoutIfCacheHasItems()
            {
                var now = DateTime.UtcNow;
                var nextTimeout = now.AddMinutes(1);
                var sagaStore = new Mock<IStoreSagas>();
                var cache = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(10));

                SystemTime.OverrideWith(() => now);
                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny<DateTime>())).Returns(new[] {
                    new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(), nextTimeout),
                    new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(), nextTimeout.AddMinutes(5))
                });

                //NOTE: Because we are using an overriden SystemTime; the get will not actually clear out the cached items.
                Assert.Equal(0, cache.GetElapsedTimeouts().Count());
                Assert.Equal(nextTimeout, cache.GetNextScheduledTimeout());
            }
            public void ReturnScheduledTimeoutsInPast()
            {
                var now        = DateTime.UtcNow;
                var futureTime = now.AddMinutes(5);
                var sagaStore  = new Mock <IStoreSagas>();
                var cache      = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(20));

                SystemTime.OverrideWith(() => futureTime);
                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny <DateTime>())).Returns(new[] {
                    new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(), now.AddMinutes(1)),
                    new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(), now.AddMinutes(5)),
                    new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(), now.AddMinutes(10))
                });

                var elapsedTimeouts = cache.GetElapsedTimeouts().ToArray();

                Assert.Equal(2, elapsedTimeouts.Length);
                Assert.Equal(now.AddMinutes(1), elapsedTimeouts[0].Timeout);
                Assert.Equal(now.AddMinutes(5), elapsedTimeouts[1].Timeout);
            }
            public void DoNotCacheScheduledTimeoutsIfMaximumCachedTimeoutInFuture()
            {
                var now = DateTime.UtcNow;
                var futureTime = now.AddMinutes(5);
                var sagaStore = new Mock<IStoreSagas>();
                var cache = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(20));

                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny<DateTime>())).Returns(new SagaTimeout[0]);
                SystemTime.OverrideWith(() => futureTime);
                cache.GetElapsedTimeouts();

                SystemTime.OverrideWith(() => now);
                cache.GetElapsedTimeouts();

                sagaStore.Verify(mock => mock.GetScheduledTimeouts(It.IsAny<DateTime>()), Times.Once());
            }
            public void ReturnEmptySetIfNoTimeoutsCached()
            {
                var now = DateTime.UtcNow;
                var futureTime = now.AddMinutes(5);
                var sagaStore = new Mock<IStoreSagas>();
                var cache = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(20));

                SystemTime.OverrideWith(() => futureTime);
                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny<DateTime>())).Returns(new SagaTimeout[0]);

                Assert.Equal(0, cache.GetElapsedTimeouts().Count());
            }
            public void DoNotCacheTimeoutsFarInFuture()
            {
                var now = DateTime.UtcNow;
                var sagaStore = new Mock<IStoreSagas>();
                var cache = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(5));
                var sagaTimeout = new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(), now.AddMinutes(10));

                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny<DateTime>())).Returns(new[] { sagaTimeout });

                SystemTime.OverrideWith(() => now);

                cache.GetElapsedTimeouts();
                cache.ScheduleTimeout(sagaTimeout);

                Assert.Equal(0, cache.Count);
            }
            public void CanTolerateCachingSameSagaReferenceMoreThanOnce()
            {
                var now = DateTime.UtcNow;
                var futureTime = now.AddMinutes(10);
                var sagaStore = new Mock<IStoreSagas>();
                var cache = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(5));
                var sagaTimeout = new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(), futureTime);

                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny<DateTime>())).Returns(new[] { sagaTimeout });

                SystemTime.OverrideWith(() => now);
                cache.GetElapsedTimeouts();

                SystemTime.OverrideWith(() => futureTime);
                cache.GetElapsedTimeouts();

                sagaStore.Verify(mock => mock.GetScheduledTimeouts(It.IsAny<DateTime>()), Times.Exactly(2));
            }
            public void ReturnScheduledTimeoutsInPast()
            {
                var now = DateTime.UtcNow;
                var futureTime = now.AddMinutes(5);
                var sagaStore = new Mock<IStoreSagas>();
                var cache = new SagaTimeoutCache(sagaStore.Object, TimeSpan.FromMinutes(20));

                SystemTime.OverrideWith(() => futureTime);
                sagaStore.Setup(mock => mock.GetScheduledTimeouts(It.IsAny<DateTime>())).Returns(new[] {
                    new SagaTimeout(typeof(Saga), GuidStrategy.NewGuid(),  now.AddMinutes(1)),
                    new SagaTimeout( typeof(Saga), GuidStrategy.NewGuid(), now.AddMinutes(5)),
                    new SagaTimeout( typeof(Saga),GuidStrategy.NewGuid(),  now.AddMinutes(10))
                });

                var elapsedTimeouts = cache.GetElapsedTimeouts().ToArray();
                Assert.Equal(2, elapsedTimeouts.Length);
                Assert.Equal(now.AddMinutes(1), elapsedTimeouts[0].Timeout);
                Assert.Equal(now.AddMinutes(5), elapsedTimeouts[1].Timeout);
            }