Skip to content

Instantly share code, notes, and snippets.

@Maarten88
Last active May 8, 2017 20:05
Show Gist options
  • Save Maarten88/5e48ee82e70cfba97797741a4760e33a to your computer and use it in GitHub Desktop.
Save Maarten88/5e48ee82e70cfba97797741a4760e33a to your computer and use it in GitHub Desktop.
using System;
using System.Threading.Tasks;
using Orleans;
using GrainInterfaces;
using Orleans.Concurrency;
namespace Grains
{
public class CacheGrain<T>: Grain, ICacheGrain<T>
{
Immutable<T> item = new Immutable<T>(default(T));
TimeSpan timeToKeep = TimeSpan.Zero;
public Task Set(Immutable<T> item, TimeSpan timeToKeep)
{
this.item = item;
this.timeToKeep = timeToKeep == TimeSpan.Zero ? TimeSpan.FromHours(2) : timeToKeep;
this.DelayDeactivation(timeToKeep);
return Task.FromResult(0);
}
public Task<Immutable<T>> Get()
{
return Task.FromResult(this.item);
}
public Task Clear()
{
this.DeactivateOnIdle();
return Task.FromResult(0);
}
public Task Refresh()
{
this.DelayDeactivation(timeToKeep);
return Task.FromResult(0);
}
}
}
using Orleans;
using System;
using System.Threading.Tasks;
using Orleans.Concurrency;
namespace GrainInterfaces
{
public interface ICacheGrain<T> : IGrainWithStringKey
{
Task Set(Immutable<T> item, TimeSpan timeToKeep);
Task<Immutable<T>> Get();
Task Clear();
Task Refresh();
}
}
using GrainInterfaces;
using Microsoft.Extensions.Caching.Distributed;
using Orleans;
using Orleans.Concurrency;
using System;
using System.Threading.Tasks;
namespace Webapp.Services
{
public class OrleansCache : IDistributedCache
{
readonly IGrainFactory grainFactory;
public OrleansCache()
{
this.grainFactory = GrainClient.GrainFactory;
}
public byte[] Get(string key) => this.GetAsync(key).Result;
public async Task<byte[]> GetAsync(string key) => (await this.grainFactory.GetGrain<ICacheGrain<byte[]>>(key).Get()).Value;
public void Refresh(string key) => this.RefreshAsync(key).Wait();
public Task RefreshAsync(string key) => this.grainFactory.GetGrain<ICacheGrain<byte[]>>(key).Refresh();
public void Remove(string key) => this.RefreshAsync(key).Wait();
public Task RemoveAsync(string key) => this.grainFactory.GetGrain<ICacheGrain<byte[]>>(key).Clear();
public void Set(string key, byte[] value, DistributedCacheEntryOptions options) => this.SetAsync(key, value, options).Wait();
public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options)
{
var creationTime = DateTimeOffset.UtcNow;
var absoluteExpiration = GetAbsoluteExpiration(creationTime, options);
var expirationSeconds = GetExpirationInSeconds(creationTime, absoluteExpiration, options);
return this.grainFactory.GetGrain<ICacheGrain<byte[]>>(key).Set(new Immutable<byte[]>(value), TimeSpan.FromSeconds((double)(expirationSeconds ?? 0)));
}
private static long? GetExpirationInSeconds(DateTimeOffset creationTime, DateTimeOffset? absoluteExpiration, DistributedCacheEntryOptions options)
{
// [ ... some time calculations ...]
}
private static DateTimeOffset? GetAbsoluteExpiration(DateTimeOffset creationTime, DistributedCacheEntryOptions options)
{
// [ ... more time calculations ...]
}
}
}
@erymski
Copy link

erymski commented May 8, 2017

Small nitpick: it seems that line #25 (Remove) should be implemented as this.RemoveAsync.

// thanks for the nice article!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment