-
Notifications
You must be signed in to change notification settings - Fork 212
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* #52 azure cache invalidate via pooling [draft] * #52 blob storage pooling architecture refactoring * #52 default azure poling interval increased * #52 typos fix, renaming pooling interval property
- Loading branch information
1 parent
f3afacf
commit fdd02fa
Showing
7 changed files
with
238 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
VirtoCommerce.Storefront/Infrastructure/BlobChangeToken.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Extensions.Primitives; | ||
using Microsoft.WindowsAzure.Storage; | ||
using Microsoft.WindowsAzure.Storage.Blob; | ||
using VirtoCommerce.Storefront.Domain; | ||
using VirtoCommerce.Storefront.Model.Common; | ||
|
||
namespace VirtoCommerce.Storefront.Infrastructure | ||
{ | ||
/// <summary> | ||
/// Based on PollingFileChangeToken | ||
/// </summary> | ||
public class BlobChangeToken : IChangeToken | ||
{ | ||
private static ConcurrentDictionary<string, DateTime> _previousChangeTimeUtcTokenLookup = new ConcurrentDictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase); | ||
|
||
public string BlobName { get; set; } | ||
private bool _hasChanged; | ||
private readonly CloudBlobContainer _container; | ||
private readonly AzureBlobContentOptions _options; | ||
private DateTime _lastModifiedUtc; | ||
private DateTime _prevModifiedUtc; | ||
private static DateTime _lastCheckedTimeUtcStatic; | ||
private static object _lock = new object(); | ||
|
||
public BlobChangeToken(string blobName, CloudBlobContainer container, AzureBlobContentOptions options) | ||
{ | ||
BlobName = blobName; | ||
|
||
_container = container; | ||
_options = options; | ||
|
||
_lastModifiedUtc = _prevModifiedUtc = DateTime.UtcNow; | ||
} | ||
|
||
public bool HasChanged | ||
{ | ||
get | ||
{ | ||
//get last modified dt | ||
_lastModifiedUtc = _previousChangeTimeUtcTokenLookup.GetOrAdd(BlobName, _lastModifiedUtc); | ||
|
||
var hasChanged = _lastModifiedUtc > _prevModifiedUtc; | ||
if (hasChanged) | ||
{ | ||
_prevModifiedUtc = _lastModifiedUtc; | ||
_hasChanged = true; | ||
} | ||
|
||
//check pooling interval | ||
var currentTime = DateTime.UtcNow; | ||
if (currentTime - _lastCheckedTimeUtcStatic < _options.ChangesPoolingInterval) | ||
{ | ||
return _hasChanged; | ||
} | ||
|
||
bool lockTaken = Monitor.TryEnter(_lock); | ||
try | ||
{ | ||
if (lockTaken) | ||
{ | ||
Task.Run(() => EvaluateBlobsModifiedDate()); | ||
_lastCheckedTimeUtcStatic = currentTime; | ||
} | ||
} | ||
finally | ||
{ | ||
if (lockTaken) | ||
Monitor.Exit(_lock); | ||
} | ||
|
||
return _hasChanged; | ||
} | ||
} | ||
|
||
private void EvaluateBlobsModifiedDate(CancellationToken cancellationToken = default(CancellationToken)) | ||
{ | ||
var files = ListBlobs().GetAwaiter().GetResult(); | ||
foreach (var file in files) | ||
{ | ||
if (cancellationToken.IsCancellationRequested) | ||
break; | ||
|
||
var lastModifiedUtc = file.Properties.LastModified.HasValue ? file.Properties.LastModified.Value.UtcDateTime : DateTime.MinValue; | ||
|
||
if (!_previousChangeTimeUtcTokenLookup.TryGetValue(file.Name, out DateTime dt)) | ||
{ | ||
_previousChangeTimeUtcTokenLookup.GetOrAdd(file.Name, lastModifiedUtc); | ||
} | ||
else | ||
{ | ||
_previousChangeTimeUtcTokenLookup[file.Name] = lastModifiedUtc; | ||
} | ||
} | ||
} | ||
|
||
private async Task<IEnumerable<CloudBlob>> ListBlobs() | ||
{ | ||
var context = new OperationContext(); | ||
var blobItems = new List<IListBlobItem>(); | ||
BlobContinuationToken token = null; | ||
var operationContext = new OperationContext(); | ||
do | ||
{ | ||
var resultSegment = await _container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.Metadata, null, token, _options.BlobRequestOptions, operationContext); | ||
token = resultSegment.ContinuationToken; | ||
blobItems.AddRange(resultSegment.Results); | ||
} while (token != null); | ||
|
||
var result = blobItems.OfType<CloudBlob>().ToList(); | ||
return result; | ||
} | ||
|
||
/// <summary> | ||
/// Don't know what to do with this one, so false | ||
/// </summary> | ||
public bool ActiveChangeCallbacks => false; | ||
|
||
/// <summary> | ||
/// Don't know what to do with this either | ||
/// </summary> | ||
public IDisposable RegisterChangeCallback(Action<object> callback, object state) => EmptyDisposable.Instance; | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
VirtoCommerce.Storefront/Infrastructure/BlobChangesWatcher.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Extensions.Options; | ||
using Microsoft.Extensions.Primitives; | ||
using Microsoft.WindowsAzure.Storage; | ||
using Microsoft.WindowsAzure.Storage.Blob; | ||
using VirtoCommerce.Storefront.Domain; | ||
|
||
namespace VirtoCommerce.Storefront.Infrastructure | ||
{ | ||
public class BlobChangesWatcher : IBlobChangesWatcher | ||
{ | ||
private readonly AzureBlobContentOptions _options; | ||
private readonly CloudBlobContainer _container; | ||
|
||
public BlobChangesWatcher(IOptions<AzureBlobContentOptions> options) | ||
{ | ||
_options = options.Value; | ||
|
||
if (CloudStorageAccount.TryParse(_options.ConnectionString, out CloudStorageAccount cloudStorageAccount)) | ||
{ | ||
var cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient(); | ||
_container = cloudBlobClient.GetContainerReference(_options.Container); | ||
} | ||
} | ||
|
||
public IChangeToken CreateBlobChangeToken(string key) | ||
{ | ||
if (!_options.PollForChanges || _container == null) | ||
{ | ||
return new CancellationChangeToken(new CancellationToken()); | ||
} | ||
|
||
return new BlobChangeToken(key, _container, _options); | ||
} | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
VirtoCommerce.Storefront/Infrastructure/IBlobChangesWatcher.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using Microsoft.Extensions.Primitives; | ||
|
||
namespace VirtoCommerce.Storefront.Infrastructure | ||
{ | ||
public interface IBlobChangesWatcher | ||
{ | ||
IChangeToken CreateBlobChangeToken(string path); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,27 @@ | ||
{ | ||
"ConnectionStrings": { | ||
"ContentConnectionString": "provider=LocalStorage;rootPath=~/cms-content" | ||
}, | ||
"VirtoCommerce": { | ||
"DefaultStore": "Electronics", | ||
"Endpoint": { | ||
"Url": "http://localhost/admin", | ||
"AppId": "27e0d789f12641049bd0e939185b4fd2", | ||
"SecretKey": "34f0a3c12c9dbb59b63b5fece955b7b2b9a3b20f84370cba1524dd5c53503a2e2cb733536ecf7ea1e77319a47084a3a2c9d94d36069a432ecc73b72aeba6ea78", | ||
"RequestTimeout": "0:0:30" | ||
"ConnectionStrings": { | ||
"ContentConnectionString": "provider=LocalStorage;rootPath=~/cms-content" | ||
}, | ||
"ChangesPoolingInterval": "0:0:15", | ||
"LiquidThemeEngine": { | ||
"RethrowLiquidRenderErrors": false | ||
}, | ||
"RequireHttps": { | ||
"Enabled": false, | ||
"StatusCode": "308", | ||
"Port": "443" | ||
"VirtoCommerce": { | ||
"DefaultStore": "Electronics", | ||
"Endpoint": { | ||
"Url": "http://localhost/admin", | ||
"AppId": "27e0d789f12641049bd0e939185b4fd2", | ||
"SecretKey": "34f0a3c12c9dbb59b63b5fece955b7b2b9a3b20f84370cba1524dd5c53503a2e2cb733536ecf7ea1e77319a47084a3a2c9d94d36069a432ecc73b72aeba6ea78", | ||
"RequestTimeout": "0:0:30" | ||
}, | ||
"ChangesPoolingInterval": "0:0:15", | ||
"LiquidThemeEngine": { | ||
"RethrowLiquidRenderErrors": false | ||
}, | ||
"RequireHttps": { | ||
"Enabled": false, | ||
"StatusCode": "308", | ||
"Port": "443" | ||
}, | ||
"AzureBlobStorage": { | ||
"PollForChanges": true, | ||
"ChangesPoolingInterval": "0:0:15" | ||
} | ||
} | ||
} | ||
} |