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>
|
<ItemGroup>
|
||||||
<Compile Include="Caching\CacheScopeTests.cs" />
|
<Compile Include="Caching\CacheScopeTests.cs" />
|
||||||
<Compile Include="Caching\CacheTests.cs" />
|
<Compile Include="Caching\CacheTests.cs" />
|
||||||
|
<Compile Include="Caching\ClockCachingTests.cs" />
|
||||||
<Compile Include="Commands\CommandHandlerDescriptorBuilderTests.cs" />
|
<Compile Include="Commands\CommandHandlerDescriptorBuilderTests.cs" />
|
||||||
<Compile Include="Commands\CommandHandlerTests.cs" />
|
<Compile Include="Commands\CommandHandlerTests.cs" />
|
||||||
<Compile Include="Commands\CommandManagerTests.cs" />
|
<Compile Include="Commands\CommandManagerTests.cs" />
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Orchard.Caching;
|
||||||
using Orchard.Services;
|
using Orchard.Services;
|
||||||
|
|
||||||
namespace Orchard.Tests.Stubs {
|
namespace Orchard.Tests.Stubs {
|
||||||
@@ -16,5 +17,14 @@ namespace Orchard.Tests.Stubs {
|
|||||||
public DateTime FutureMoment(TimeSpan span) {
|
public DateTime FutureMoment(TimeSpan span) {
|
||||||
return UtcNow.Add(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 {
|
namespace Orchard.Services {
|
||||||
public interface IClock : IVolatileProvider {
|
public interface IClock : IVolatileProvider {
|
||||||
DateTime UtcNow { get; }
|
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 {
|
public class Clock : IClock {
|
||||||
@@ -11,5 +21,33 @@ namespace Orchard.Services {
|
|||||||
get { return DateTime.UtcNow; }
|
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