diff options
Diffstat (limited to 'lib/VNLib.Plugins.Extensions.VNCache')
8 files changed, 151 insertions, 9 deletions
diff --git a/lib/VNLib.Plugins.Extensions.VNCache/LICENSE.txt b/lib/VNLib.Plugins.Extensions.VNCache/LICENSE.txt index 147bcd6..a169586 100644 --- a/lib/VNLib.Plugins.Extensions.VNCache/LICENSE.txt +++ b/lib/VNLib.Plugins.Extensions.VNCache/LICENSE.txt @@ -1,8 +1,8 @@ -Copyright (c) 2022 Vaughn Nugent +Copyright (c) 2023 Vaughn Nugent Contact information Name: Vaughn Nugent - Email: public[at]vaughnnugent[dot]com + Email: vnpublic@proton.me Website: https://www.vaughnnugent.com The software in this repository is licensed under the GNU Affero GPL version 3.0 (or any later version). diff --git a/lib/VNLib.Plugins.Extensions.VNCache/README.md b/lib/VNLib.Plugins.Extensions.VNCache/README.md index 9799fec..157e5ad 100644 --- a/lib/VNLib.Plugins.Extensions.VNCache/README.md +++ b/lib/VNLib.Plugins.Extensions.VNCache/README.md @@ -1,8 +1,18 @@ # VNLib.Plugins.Extensions.VNCache *An extension library for configuring and managing a IGlobalCache connection against a VNCache cluster on a plugin* -#### Builds -Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my [website](https://www.vaughnnugent.com/resources/software). All tar-gzip (.tgz) files will have an associated .sha384 appended checksum of the desired download file. +### Dependency notice +This library depends on the VNLib.Net.Rest.Client library which requires RestSharp. + +## Builds +Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below). + +## Docs and Guides +Documentation, specifications, and setup guides are available on my website. + +[Docs and Articles](https://www.vaughnnugent.com/resources/software/articles?tags=docs,_VNLib.Plugins.Extensions.VNCache) +[Builds and Source](https://www.vaughnnugent.com/resources/software/modules/VNLib.Data.Caching) +[Nuget Feeds](https://www.vaughnnugent.com/resources/software/modules) ## License Source files in for this project are licensed to you under the GNU Affero General Public License (or any later version). See the LICENSE files for more information.
\ No newline at end of file diff --git a/lib/VNLib.Plugins.Extensions.VNCache/src/DataModel/EntityCacheExtensions.cs b/lib/VNLib.Plugins.Extensions.VNCache/src/DataModel/EntityCacheExtensions.cs index 79bb4fc..73baa4a 100644 --- a/lib/VNLib.Plugins.Extensions.VNCache/src/DataModel/EntityCacheExtensions.cs +++ b/lib/VNLib.Plugins.Extensions.VNCache/src/DataModel/EntityCacheExtensions.cs @@ -100,6 +100,7 @@ namespace VNLib.Plugins.Extensions.VNCache.DataModel KeyGen = keyGen; } + ///<inheritdoc/> public override Task AddOrUpdateAsync<T>(string key, string? newKey, T value, CancellationToken cancellation) { _ = key ?? throw new ArgumentNullException(nameof(key)); @@ -113,6 +114,7 @@ namespace VNLib.Plugins.Extensions.VNCache.DataModel return cache.AddOrUpdateAsync(primary, secondary, value, cancellation); } + ///<inheritdoc/> public override Task DeleteAsync(string key, CancellationToken cancellation) { _ = key ?? throw new ArgumentNullException(nameof(key)); @@ -121,6 +123,7 @@ namespace VNLib.Plugins.Extensions.VNCache.DataModel return cache.DeleteAsync(scoped, cancellation); } + ///<inheritdoc/> public override Task<T> GetAsync<T>(string key, CancellationToken cancellation) { _ = key ?? throw new ArgumentNullException(nameof(key)); @@ -131,6 +134,7 @@ namespace VNLib.Plugins.Extensions.VNCache.DataModel return cache.GetAsync<T?>(scoped, cancellation); } + ///<inheritdoc/> public override Task<T> GetAsync<T>(string key, ICacheObjectDeserialzer deserializer, CancellationToken cancellation) { _ = key ?? throw new ArgumentNullException(nameof(key)); @@ -141,6 +145,7 @@ namespace VNLib.Plugins.Extensions.VNCache.DataModel return cache.GetAsync<T?>(scoped, deserializer, cancellation); } + ///<inheritdoc/> public override Task AddOrUpdateAsync<T>(string key, string? newKey, T value, ICacheObjectSerialzer serialzer, CancellationToken cancellation) { _ = key ?? throw new ArgumentNullException(nameof(key)); @@ -153,6 +158,31 @@ namespace VNLib.Plugins.Extensions.VNCache.DataModel return cache.AddOrUpdateAsync(primary, secondary, value, serialzer, cancellation); } + + ///<inheritdoc/> + public override Task GetAsync(string key, IObjectData rawData, CancellationToken cancellation) + { + _ = key ?? throw new ArgumentNullException(nameof(key)); + + //Compute the key for the id + string scoped = KeyGen.ComputedKey(key); + + return cache.GetAsync(scoped, rawData, cancellation); + } + + ///<inheritdoc/> + public override Task AddOrUpdateAsync(string key, string? newKey, IObjectData rawData, ICacheObjectSerialzer serialzer, CancellationToken cancellation) + { + _ = key ?? throw new ArgumentNullException(nameof(key)); + + //Compute primary key from id + string primary = KeyGen.ComputedKey(key); + + //If newkey exists, compute the secondary key + string? secondary = newKey != null ? KeyGen.ComputedKey(newKey) : null; + + return cache.AddOrUpdateAsync(primary, secondary, rawData, serialzer, cancellation); + } } } diff --git a/lib/VNLib.Plugins.Extensions.VNCache/src/DataModel/ScopedCache.cs b/lib/VNLib.Plugins.Extensions.VNCache/src/DataModel/ScopedCache.cs index da2f78a..c26fd1a 100644 --- a/lib/VNLib.Plugins.Extensions.VNCache/src/DataModel/ScopedCache.cs +++ b/lib/VNLib.Plugins.Extensions.VNCache/src/DataModel/ScopedCache.cs @@ -60,5 +60,11 @@ namespace VNLib.Plugins.Extensions.VNCache.DataModel ///<inheritdoc/> public abstract Task AddOrUpdateAsync<T>(string key, string? newKey, T value, ICacheObjectSerialzer serialzer, CancellationToken cancellation); + + ///<inheritdoc/> + public abstract Task GetAsync(string key, IObjectData rawData, CancellationToken cancellation); + + ///<inheritdoc/> + public abstract Task AddOrUpdateAsync(string key, string? newKey, IObjectData rawData, ICacheObjectSerialzer serialzer, CancellationToken cancellation); } } diff --git a/lib/VNLib.Plugins.Extensions.VNCache/src/MemoryCache.cs b/lib/VNLib.Plugins.Extensions.VNCache/src/MemoryCache.cs index a62b5db..e4c95a4 100644 --- a/lib/VNLib.Plugins.Extensions.VNCache/src/MemoryCache.cs +++ b/lib/VNLib.Plugins.Extensions.VNCache/src/MemoryCache.cs @@ -176,5 +176,33 @@ namespace VNLib.Plugins.Extensions.VNCache return default; } + + ///<inheritdoc/> + public async Task GetAsync(string key, IObjectData rawData, CancellationToken cancellation) + { + Check(); + + //Get the bucket from the desired key + IBlobCacheBucket bucket = _memCache.GetBucket(key); + + //Obtain cache handle + using CacheBucketHandle handle = await bucket.WaitAsync(cancellation); + + //Try to read the value + if (handle.Cache.TryGetValue(key, out CacheEntry entry)) + { + //Set result data + rawData.SetData(entry.GetDataSegment()); + } + } + + ///<inheritdoc/> + public Task AddOrUpdateAsync(string key, string? newKey, IObjectData rawData, ICacheObjectSerialzer serialzer, CancellationToken cancellation) + { + Check(); + + //Update object data + return _memCache.AddOrUpdateObjectAsync(key, newKey, static b => b.GetData(), rawData, default, cancellation).AsTask(); + } } }
\ No newline at end of file diff --git a/lib/VNLib.Plugins.Extensions.VNCache/src/RemoteBackedMemoryCache.cs b/lib/VNLib.Plugins.Extensions.VNCache/src/RemoteBackedMemoryCache.cs index ffe9108..ff73f19 100644 --- a/lib/VNLib.Plugins.Extensions.VNCache/src/RemoteBackedMemoryCache.cs +++ b/lib/VNLib.Plugins.Extensions.VNCache/src/RemoteBackedMemoryCache.cs @@ -192,20 +192,61 @@ namespace VNLib.Plugins.Extensions.VNCache { CheckConnected(); - DateTime currentTime = DateTime.UtcNow; - //Alloc serialzation buffer using AddOrUpdateBuffer buffer = new (Client.Config.BufferHeap); //Serialze the value serialzer.Serialize(value, buffer); + //Call update on raw data + await AddOrUpdateAsync(key, newKey, buffer, cancellation); + } + + ///<inheritdoc/> + public override async Task GetAsync(string key, IObjectData rawData, CancellationToken cancellation) + { + CheckConnected(); + + IBlobCacheBucket bucket = _memCache.GetBucket(key); + + //Obtain cache handle + using (CacheBucketHandle handle = await bucket.WaitAsync(cancellation)) + { + //Try to read the value + if (handle.Cache.TryGetValue(key, out CacheEntry entry)) + { + rawData.SetData(entry.GetDataSegment()); + return; + } + } + + //Get the object from the server + await Client.GetObjectAsync(key, rawData, cancellation); + + //See if object data was set + if (rawData.GetData().IsEmpty) + { + return; + } + + //Update local cache + await _memCache.AddOrUpdateObjectAsync(key, null, static b => b.GetData(), rawData, DateTime.UtcNow, CancellationToken.None); + } + + ///<inheritdoc/> + public override async Task AddOrUpdateAsync(string key, string? newKey, IObjectData rawData, ICacheObjectSerialzer serialzer, CancellationToken cancellation) + { + CheckConnected(); + + DateTime currentTime = DateTime.UtcNow; + try { //Update remote first, and if exceptions are raised, do not update local cache - await Client.AddOrUpdateObjectAsync(key, newKey, (IObjectData)buffer, cancellation); + await Client.AddOrUpdateObjectAsync(key, newKey, rawData, cancellation); - await _memCache.AddOrUpdateObjectAsync(key, newKey, static b => b.GetData(), buffer, currentTime, CancellationToken.None); + //Safe to update local cache + await _memCache.AddOrUpdateObjectAsync(key, newKey, static b => b.GetData(), rawData, currentTime, CancellationToken.None); } catch { diff --git a/lib/VNLib.Plugins.Extensions.VNCache/src/VnCacheClient.cs b/lib/VNLib.Plugins.Extensions.VNCache/src/VnCacheClient.cs index b10cef7..72eecd8 100644 --- a/lib/VNLib.Plugins.Extensions.VNCache/src/VnCacheClient.cs +++ b/lib/VNLib.Plugins.Extensions.VNCache/src/VnCacheClient.cs @@ -273,7 +273,22 @@ namespace VNLib.Plugins.Extensions.VNCache ? throw new InvalidOperationException("The underlying client is not connected to a cache node") : Client!.AddOrUpdateObjectAsync(key, newKey, value, serialzer, cancellation); } - + + ///<inheritdoc/> + public virtual Task GetAsync(string key, IObjectData rawData, CancellationToken cancellation) + { + return !IsConnected + ? throw new InvalidOperationException("The underlying client is not connected to a cache node") + : Client!.GetObjectAsync(key, rawData, cancellation); + } + + ///<inheritdoc/> + public virtual Task AddOrUpdateAsync(string key, string? newKey, IObjectData rawData, ICacheObjectSerialzer serialzer, CancellationToken cancellation) + { + return !IsConnected + ? throw new InvalidOperationException("The underlying client is not connected to a cache node") + : Client!.AddOrUpdateObjectAsync(key, newKey, rawData, serialzer, cancellation); + } private sealed class AuthManager : ICacheAuthManager { diff --git a/lib/VNLib.Plugins.Extensions.VNCache/src/VnGlobalCache.cs b/lib/VNLib.Plugins.Extensions.VNCache/src/VnGlobalCache.cs index 981786d..786a085 100644 --- a/lib/VNLib.Plugins.Extensions.VNCache/src/VnGlobalCache.cs +++ b/lib/VNLib.Plugins.Extensions.VNCache/src/VnGlobalCache.cs @@ -172,5 +172,17 @@ namespace VNLib.Plugins.Extensions.VNCache { return _client.GetAsync<T>(key, deserializer, cancellation); } + + ///<inheritdoc/> + public Task GetAsync(string key, IObjectData rawData, CancellationToken cancellation) + { + return _client.GetAsync(key, rawData, cancellation); + } + + ///<inheritdoc/> + public Task AddOrUpdateAsync(string key, string? newKey, IObjectData rawData, ICacheObjectSerialzer serialzer, CancellationToken cancellation) + { + return _client.AddOrUpdateAsync(key, newKey, rawData, serialzer, cancellation); + } } }
\ No newline at end of file |