fix bugs around retrieving cache items, note that sliding expiration doesn't work properly as of now

This commit is contained in:
Tommy Parnell
2016-06-11 10:54:42 -04:00
parent 571c87cc50
commit 3627f93296
5 changed files with 38 additions and 12 deletions

View File

@@ -3,6 +3,8 @@ Use azure table storage for AspNet core 1.0 Distributed Cache.
Azure Table Storage is a very cheap, [super fast](https://www.troyhunt.com/working-with-154-million-records-on/) key value store, and its much cheaper than the redis cluster in azure. This is not a true replacement for redis, and redis should be used if people have money, but this is designed to get people a very cheap cache in azure. Currently this doesn't actually support the dotnet core runtime, and won't until the Azure Storage client is updated to support core. Azure Table Storage is a very cheap, [super fast](https://www.troyhunt.com/working-with-154-million-records-on/) key value store, and its much cheaper than the redis cluster in azure. This is not a true replacement for redis, and redis should be used if people have money, but this is designed to get people a very cheap cache in azure. Currently this doesn't actually support the dotnet core runtime, and won't until the Azure Storage client is updated to support core.
**warning** As of right now sliding expiration doesn't work. This is at the top of the list to get working
## How to use ## How to use
`install-package AzureTableStorageCache` `install-package AzureTableStorageCache`
@@ -22,7 +24,9 @@ In your startup.cs
``` ```
Then in a controller just ask for an IDistributedCache in the constructor. Since this implements Microsoft's IDistributed cache, it could be easily swapped out for redis or another Distributed cache Then in a controller just ask for an IDistributedCache in the constructor. Since this implements Microsoft's IDistributed cache, it could be easily swapped out for redis or another Distributed cache.
```csharp ```csharp

View File

@@ -34,7 +34,6 @@ namespace AzureTableStorageCache
} }
this.tableName = tableName; this.tableName = tableName;
this.partitionKey = partitionKey; this.partitionKey = partitionKey;
Connect();
} }
public AzureTableStorageCacheHandler(string accountName, string accountKey, string tableName, string partitionKey) public AzureTableStorageCacheHandler(string accountName, string accountKey, string tableName, string partitionKey)
@@ -51,6 +50,7 @@ namespace AzureTableStorageCache
this.accountName = accountName; this.accountName = accountName;
this.accountKey = accountKey; this.accountKey = accountKey;
Connect();
} }
private readonly string tableName; private readonly string tableName;
@@ -64,6 +64,7 @@ namespace AzureTableStorageCache
} }
this.connectionString = connectionString; this.connectionString = connectionString;
Connect();
} }
public void Connect() public void Connect()
@@ -99,10 +100,13 @@ namespace AzureTableStorageCache
public async Task<byte[]> GetAsync(string key) public async Task<byte[]> GetAsync(string key)
{ {
await RefreshAsync(key); var cachedItem = await RetrieveAsync(key);
var op = TableOperation.Retrieve(partitionKey, key); if (cachedItem != null && cachedItem.Data != null && ShouldDelete(cachedItem))
var result = await azuretable.ExecuteAsync(op); {
return (result?.Result as CachedItem)?.Data; await RemoveAsync(key);
return null;
}
return cachedItem?.Data;
} }
public void Refresh(string key) public void Refresh(string key)
@@ -112,9 +116,7 @@ namespace AzureTableStorageCache
public async Task RefreshAsync(string key) public async Task RefreshAsync(string key)
{ {
var op = TableOperation.Retrieve(partitionKey, key); var data = await RetrieveAsync(key);
var result = await azuretable.ExecuteAsync(op);
var data = result?.Result as CachedItem;
if (data != null) if (data != null)
{ {
if (ShouldDelete(data)) if (ShouldDelete(data))
@@ -125,6 +127,14 @@ namespace AzureTableStorageCache
} }
} }
private async Task<CachedItem> RetrieveAsync(string key)
{
var op = TableOperation.Retrieve<CachedItem>(partitionKey, key);
var result = await azuretable.ExecuteAsync(op);
var data = result?.Result as CachedItem;
return data;
}
private bool ShouldDelete(CachedItem data) private bool ShouldDelete(CachedItem data)
{ {
var currentTime = DateTimeOffset.UtcNow; var currentTime = DateTimeOffset.UtcNow;
@@ -176,6 +186,14 @@ namespace AzureTableStorageCache
absoluteExpiration = options.AbsoluteExpiration; absoluteExpiration = options.AbsoluteExpiration;
} }
var item = new CachedItem(partitionKey, key, value) { LastAccessTime = currentTime }; var item = new CachedItem(partitionKey, key, value) { LastAccessTime = currentTime };
if (absoluteExpiration.HasValue)
{
item.AbsolutExperiation = absoluteExpiration;
}
if (options.SlidingExpiration.HasValue)
{
item.SlidingExperiation = options.SlidingExpiration;
}
var op = TableOperation.InsertOrReplace(item); var op = TableOperation.InsertOrReplace(item);
return this.azuretable.ExecuteAsync(op); return this.azuretable.ExecuteAsync(op);
} }

View File

@@ -1,5 +1,5 @@
{ {
"version": "1.1.0-*", "version": "1.2.0-*",
"dependencies": { "dependencies": {
"NETStandard.Library": "1.5.0-rc2-24027", "NETStandard.Library": "1.5.0-rc2-24027",

View File

@@ -19,12 +19,16 @@ namespace AzureTableStorageCacheSample.Controllers
public async Task<IActionResult> Index() public async Task<IActionResult> Index()
{ {
var data = await cacheMechanism.GetAsync("awesomeRecord"); await cacheMechanism.SetAsync("awesomeRecord2", Encoding.UTF32.GetBytes("records are awesome"), new DistributedCacheEntryOptions() { SlidingExpiration = new TimeSpan(0, 5, 0) });
var data = await cacheMechanism.GetAsync("awesomeRecord2");
var result = string.Empty; var result = string.Empty;
if (data != null) if (data != null)
{ {
result = Encoding.UTF32.GetString(data); result = Encoding.UTF32.GetString(data);
} }
else
{
}
return View(result); return View(result);
} }

View File

@@ -29,7 +29,7 @@ namespace AzureTableStorageCacheSample
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddAzureTableStorageCache("!!!CONNECTIONSTRINGHERE!!!", "tablename", "partitionKey"); services.AddAzureTableStorageCache("DefaultEndpointsProtocol=https;AccountName=tparnell;AccountKey=cEHdbvM6bljcIYOaODs16vRokLDvxujEn+JR/8MWgYE/9g4mw95n/jusTAdvhc/JrySfZGwaq/WIg9Bi/TeoOw==", "yodawg", "cachingforlyfe");
// Add framework services. // Add framework services.
services.AddMvc(); services.AddMvc();
} }