Skip to content

Commit

Permalink
Merge pull request #3 from flagbug/preload
Browse files Browse the repository at this point in the history
Enable preloading of all settings
  • Loading branch information
flagbug committed Dec 15, 2013
2 parents 24abb6e + 881b0f9 commit dada2be
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 5 deletions.
23 changes: 23 additions & 0 deletions Lager.Tests/DummySettingsStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Akavache;

namespace Lager.Tests
{
public class DummySettingsStorage : SettingsStorage
{
public DummySettingsStorage(string keyPrefix, IBlobCache cache)
: base(keyPrefix, cache)
{ }

public int DummyNumber
{
get { return this.GetOrCreate(42); }
set { this.SetOrCreate(value); }
}

public string DummyText
{
get { return this.GetOrCreate("Yaddayadda"); }
set { this.SetOrCreate(value); }
}
}
}
1 change: 1 addition & 0 deletions Lager.Tests/Lager.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
<Otherwise />
</Choose>
<ItemGroup>
<Compile Include="DummySettingsStorage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SettingsStorageProxy.cs" />
<Compile Include="SettingsStorageTest.cs" />
Expand Down
23 changes: 23 additions & 0 deletions Lager.Tests/SettingsStorageTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using Moq;
using System;
using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Xunit;

namespace Lager.Tests
Expand Down Expand Up @@ -58,6 +60,27 @@ public void GetOrCreateWithNullKeyThrowsArgumentNullException()
Assert.Throws<ArgumentNullException>(() => settings.GetOrCreateProxy(42, null));
}

[Fact]
public async Task InitializeAsyncLoadsValuesIntoCache()
{
var testCache = new TestBlobCache();
testCache.InsertObject("Storage:DummyNumber", 16);
testCache.InsertObject("Storage:DummyText", "Random");

var cache = new Mock<IBlobCache>();
cache.Setup(x => x.GetAsync(It.IsAny<string>())).Returns<string>(testCache.GetAsync);
var settings = new DummySettingsStorage("Storage", cache.Object);

await settings.InitializeAsync();

int number = settings.DummyNumber;
string text = settings.DummyText;

Assert.Equal(16, number);
Assert.Equal("Random", text);
cache.Verify(x => x.GetAsync(It.IsAny<string>()), Times.Exactly(2));
}

[Fact]
public void SetOrCreateInsertsValueIntoBlobCache()
{
Expand Down
37 changes: 32 additions & 5 deletions Lager/SettingsStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Reactive.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

namespace Lager
{
Expand Down Expand Up @@ -42,6 +44,23 @@ protected SettingsStorage(string keyPrefix, IBlobCache cache)

public event PropertyChangedEventHandler PropertyChanged;

/// <summary>
/// Loads every setting in this storage into the internal cache, or, if the value doesn't exist in the storage,
/// initializes it with its default value.
/// You dont HAVE to call this method, but it's handy for applications with a high number of settings
/// where you want to load all settings on startup at once into the internal cache and not one-by-one at each request.
/// </summary>
public Task InitializeAsync()
{
return Task.Run(() =>
{
foreach (var property in this.GetType().GetRuntimeProperties())
{
property.GetValue(this);
}
});
}

/// <summary>
/// Gets the value for the specified key, or, if the value doesn't exist, saves the <paramref name="defaultValue"/> and returns it.
/// </summary>
Expand Down Expand Up @@ -70,7 +89,10 @@ protected T GetOrCreate<T>(T defaultValue, [CallerMemberName] string key = null)
this.cacheLock.ExitReadLock();
}

return this.blobCache.GetOrCreateObject(string.Format("{0}:{1}", this.keyPrefix, key), () => defaultValue).Wait();
T returnValue = this.blobCache.GetOrCreateObject(string.Format("{0}:{1}", this.keyPrefix, key), () => defaultValue)
.Do(x => this.AddToInternalCache(key, x)).Wait();

return returnValue;
}

/// <summary>
Expand All @@ -85,16 +107,21 @@ protected void SetOrCreate<T>(T value, [CallerMemberName] string key = null)
if (key == null)
throw new ArgumentNullException("key");

this.AddToInternalCache(key, value);

this.blobCache.InsertObject(string.Format("{0}:{1}", this.keyPrefix, key), value);

this.OnPropertyChanged(key);
}

private void AddToInternalCache(string key, object value)
{
this.cacheLock.EnterWriteLock();

this.cache.Remove(key);
this.cache.Add(key, value);

this.cacheLock.ExitWriteLock();

this.blobCache.InsertObject(string.Format("{0}:{1}", this.keyPrefix, key), value);

this.OnPropertyChanged(key);
}

private void OnPropertyChanged(string propertyName = null)
Expand Down

0 comments on commit dada2be

Please sign in to comment.