mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 03:25:23 +08:00
Adding clock based cache invalidation
--HG-- branch : dev
This commit is contained in:
85
src/Orchard.Tests/Caching/ClockCachingTests.cs
Normal file
85
src/Orchard.Tests/Caching/ClockCachingTests.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using Autofac;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Caching;
|
||||
using Orchard.Services;
|
||||
using Orchard.Tests.Stubs;
|
||||
|
||||
namespace Orchard.Tests.Caching {
|
||||
[TestFixture]
|
||||
public class ClockCachingTests {
|
||||
private IContainer _container;
|
||||
private ICacheManager _cacheManager;
|
||||
private StubClock _clock;
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterModule(new CacheModule());
|
||||
builder.RegisterType<DefaultCacheManager>().As<ICacheManager>();
|
||||
builder.RegisterType<DefaultCacheHolder>().As<ICacheHolder>().SingleInstance();
|
||||
builder.RegisterType<DefaultCacheManager>().As<ICacheManager>();
|
||||
builder.RegisterInstance<IClock>(_clock = new StubClock());
|
||||
builder.RegisterType<DefaultCacheManager>().As<ICacheManager>();
|
||||
_container = builder.Build();
|
||||
_cacheManager = _container.Resolve<ICacheManager>(new TypedParameter(typeof(Type), GetType()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAbsoluteShouldHandleAbsoluteTime() {
|
||||
var inOneSecond = _clock.UtcNow.AddSeconds(1);
|
||||
var cached = 0;
|
||||
|
||||
// each call after the specified datetime will be reevaluated
|
||||
Func<int> retrieve = ()
|
||||
=> _cacheManager.Get("testItem",
|
||||
ctx => {
|
||||
ctx.Monitor(_clock.WhenUtc(inOneSecond));
|
||||
return ++cached;
|
||||
});
|
||||
|
||||
Assert.That(retrieve(), Is.EqualTo(1));
|
||||
|
||||
for ( var i = 0; i < 10; i++ ) {
|
||||
Assert.That(retrieve(), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
_clock.Advance(TimeSpan.FromSeconds(1));
|
||||
|
||||
Assert.That(retrieve(), Is.EqualTo(2));
|
||||
Assert.That(retrieve(), Is.EqualTo(3));
|
||||
Assert.That(retrieve(), Is.EqualTo(4));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAbsoluteShouldHandleAbsoluteTimeSpan() {
|
||||
var cached = 0;
|
||||
|
||||
// each cached value has a lifetime of the specified duration
|
||||
Func<int> retrieve = ()
|
||||
=> _cacheManager.Get("testItem",
|
||||
ctx => {
|
||||
ctx.Monitor(_clock.When(TimeSpan.FromSeconds(1)));
|
||||
return ++cached;
|
||||
});
|
||||
|
||||
Assert.That(retrieve(), Is.EqualTo(1));
|
||||
|
||||
for ( var i = 0; i < 10; i++ ) {
|
||||
Assert.That(retrieve(), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
_clock.Advance(TimeSpan.FromSeconds(1));
|
||||
|
||||
for ( var i = 0; i < 10; i++ ) {
|
||||
Assert.That(retrieve(), Is.EqualTo(2));
|
||||
}
|
||||
|
||||
_clock.Advance(TimeSpan.FromSeconds(1));
|
||||
|
||||
for ( var i = 0; i < 10; i++ ) {
|
||||
Assert.That(retrieve(), Is.EqualTo(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -160,6 +160,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Caching\CacheScopeTests.cs" />
|
||||
<Compile Include="Caching\CacheTests.cs" />
|
||||
<Compile Include="Caching\ClockCachingTests.cs" />
|
||||
<Compile Include="Commands\CommandHandlerDescriptorBuilderTests.cs" />
|
||||
<Compile Include="Commands\CommandHandlerTests.cs" />
|
||||
<Compile Include="Commands\CommandManagerTests.cs" />
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Orchard.Caching;
|
||||
using Orchard.Services;
|
||||
|
||||
namespace Orchard.Tests.Stubs {
|
||||
@@ -16,5 +17,14 @@ namespace Orchard.Tests.Stubs {
|
||||
public DateTime FutureMoment(TimeSpan span) {
|
||||
return UtcNow.Add(span);
|
||||
}
|
||||
|
||||
|
||||
public IVolatileToken When(TimeSpan duration) {
|
||||
return new Clock.AbsoluteExpirationToken(this, duration);
|
||||
}
|
||||
|
||||
public IVolatileToken WhenUtc(DateTime absoluteUtc) {
|
||||
return new Clock.AbsoluteExpirationToken(this, absoluteUtc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,16 @@ using Orchard.Caching;
|
||||
namespace Orchard.Services {
|
||||
public interface IClock : IVolatileProvider {
|
||||
DateTime UtcNow { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Each retrieved value is cached during the specified amount of time.
|
||||
/// </summary>
|
||||
IVolatileToken When(TimeSpan duration);
|
||||
|
||||
/// <summary>
|
||||
/// The cache is active until the specified time. Each subsequent access won't be cached.
|
||||
/// </summary>
|
||||
IVolatileToken WhenUtc(DateTime absoluteUtc);
|
||||
}
|
||||
|
||||
public class Clock : IClock {
|
||||
@@ -11,5 +21,33 @@ namespace Orchard.Services {
|
||||
get { return DateTime.UtcNow; }
|
||||
}
|
||||
|
||||
public IVolatileToken When(TimeSpan duration) {
|
||||
return new AbsoluteExpirationToken(this, duration);
|
||||
}
|
||||
|
||||
public IVolatileToken WhenUtc(DateTime absoluteUtc) {
|
||||
return new AbsoluteExpirationToken(this, absoluteUtc);
|
||||
}
|
||||
|
||||
public class AbsoluteExpirationToken : IVolatileToken {
|
||||
private readonly IClock _clock;
|
||||
private readonly DateTime _invalidateUtc;
|
||||
|
||||
public AbsoluteExpirationToken(IClock clock, DateTime invalidateUtc) {
|
||||
_clock = clock;
|
||||
_invalidateUtc = invalidateUtc;
|
||||
}
|
||||
|
||||
public AbsoluteExpirationToken(IClock clock, TimeSpan duration) {
|
||||
_clock = clock;
|
||||
_invalidateUtc = _clock.UtcNow.Add(duration);
|
||||
}
|
||||
|
||||
public bool IsCurrent {
|
||||
get {
|
||||
return _clock.UtcNow < _invalidateUtc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user