From b75668b164d398b99ee942beced06aa27ef65a50 Mon Sep 17 00:00:00 2001 From: vnugent Date: Thu, 12 Jan 2023 17:47:40 -0500 Subject: Large project reorder and consolidation --- lib/VNLib.Data.Caching/src/ClientExtensions.cs | 328 +++++++++++++++++++++ lib/VNLib.Data.Caching/src/ClientRetryManager.cs | 107 +++++++ lib/VNLib.Data.Caching/src/Constants.cs | 56 ++++ .../src/Exceptions/InvalidStatusException.cs | 63 ++++ .../src/Exceptions/MessageTooLargeException.cs | 50 ++++ .../src/Exceptions/ObjectNotFoundException.cs | 47 +++ lib/VNLib.Data.Caching/src/IGlobalCacheProvider.cs | 68 +++++ .../src/VNLib.Data.Caching.csproj | 46 +++ lib/VNLib.Data.Caching/src/WaitForChangeResult.cs | 45 +++ 9 files changed, 810 insertions(+) create mode 100644 lib/VNLib.Data.Caching/src/ClientExtensions.cs create mode 100644 lib/VNLib.Data.Caching/src/ClientRetryManager.cs create mode 100644 lib/VNLib.Data.Caching/src/Constants.cs create mode 100644 lib/VNLib.Data.Caching/src/Exceptions/InvalidStatusException.cs create mode 100644 lib/VNLib.Data.Caching/src/Exceptions/MessageTooLargeException.cs create mode 100644 lib/VNLib.Data.Caching/src/Exceptions/ObjectNotFoundException.cs create mode 100644 lib/VNLib.Data.Caching/src/IGlobalCacheProvider.cs create mode 100644 lib/VNLib.Data.Caching/src/VNLib.Data.Caching.csproj create mode 100644 lib/VNLib.Data.Caching/src/WaitForChangeResult.cs (limited to 'lib/VNLib.Data.Caching/src') diff --git a/lib/VNLib.Data.Caching/src/ClientExtensions.cs b/lib/VNLib.Data.Caching/src/ClientExtensions.cs new file mode 100644 index 0000000..a207886 --- /dev/null +++ b/lib/VNLib.Data.Caching/src/ClientExtensions.cs @@ -0,0 +1,328 @@ +/* +* Copyright (c) 2022 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Data.Caching +* File: ClientExtensions.cs +* +* ClientExtensions.cs is part of VNLib.Data.Caching which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Data.Caching is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Data.Caching is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System; +using System.IO; +using System.Linq; +using System.Buffers; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +using VNLib.Utils.Logging; +using VNLib.Net.Messaging.FBM; +using VNLib.Net.Messaging.FBM.Client; +using VNLib.Net.Messaging.FBM.Server; +using VNLib.Data.Caching.Exceptions; + +using static VNLib.Data.Caching.Constants; + +namespace VNLib.Data.Caching +{ + + /// + /// Provides caching extension methods for + /// + public static class ClientExtensions + { + private static readonly JsonSerializerOptions LocalOptions = new() + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + NumberHandling = JsonNumberHandling.Strict, + ReadCommentHandling = JsonCommentHandling.Disallow, + WriteIndented = false, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + IgnoreReadOnlyFields = true, + PropertyNameCaseInsensitive = true, + IncludeFields = false, + + //Use small buffers + DefaultBufferSize = 128 + }; + + private static void LogDebug(this FBMClient client, string message, params object?[] args) + { + if (client.Config.DebugLog != null) + { + client.Config.DebugLog.Debug($"[CACHE] : {message}", args); + } + } + + /// + /// Gets an object from the server if it exists + /// + /// + /// + /// The id of the object to get + /// A token to cancel the operation + /// A task that completes to return the results of the response payload + /// + /// + /// + /// + /// + public static async Task GetObjectAsync(this FBMClient client, string objectId, CancellationToken cancellationToken = default) + { + _ = client ?? throw new ArgumentNullException(nameof(client)); + + client.LogDebug("Getting object {id}", objectId); + + //Rent a new request + FBMRequest request = client.RentRequest(); + try + { + //Set action as get/create + request.WriteHeader(HeaderCommand.Action, Actions.Get); + //Set session-id header + request.WriteHeader(Constants.ObjectId, objectId); + + //Make request + using FBMResponse response = await client.SendAsync(request, cancellationToken); + + response.ThrowIfNotSet(); + //Get the status code + ReadOnlyMemory status = response.Headers.FirstOrDefault(static a => a.Key == HeaderCommand.Status).Value; + if (status.Span.Equals(ResponseCodes.Okay, StringComparison.Ordinal)) + { + return JsonSerializer.Deserialize(response.ResponseBody, LocalOptions); + } + //Session may not exist on the server yet + if (status.Span.Equals(ResponseCodes.NotFound, StringComparison.Ordinal)) + { + return default; + } + throw new InvalidStatusException("Invalid status code recived for object get request", status.ToString()); + } + finally + { + client.ReturnRequest(request); + } + } + + /// + /// Updates the state of the object, and optionally updates the ID of the object. The data + /// parameter is serialized, buffered, and streamed to the remote server + /// + /// + /// + /// The id of the object to update or replace + /// An optional parameter to specify a new ID for the old object + /// The payload data to serialize and set as the data state of the session + /// A token to cancel the operation + /// A task that resolves when the server responds + /// + /// + /// + /// + /// + /// + /// + public static async Task AddOrUpdateObjectAsync(this FBMClient client, string objectId, string? newId, T data, CancellationToken cancellationToken = default) + { + _ = client ?? throw new ArgumentNullException(nameof(client)); + + client.LogDebug("Updating object {id}, newid {nid}", objectId, newId); + + //Rent a new request + FBMRequest request = client.RentRequest(); + try + { + //Set action as get/create + request.WriteHeader(HeaderCommand.Action, Actions.AddOrUpdate); + //Set session-id header + request.WriteHeader(Constants.ObjectId, objectId); + //if new-id set, set the new-id header + if (!string.IsNullOrWhiteSpace(newId)) + { + request.WriteHeader(Constants.NewObjectId, newId); + } + //Get the body writer for the message + IBufferWriter bodyWriter = request.GetBodyWriter(); + //Write json data to the message + using (Utf8JsonWriter jsonWriter = new(bodyWriter)) + { + JsonSerializer.Serialize(jsonWriter, data, LocalOptions); + } + + //Make request + using FBMResponse response = await client.SendAsync(request, cancellationToken); + + response.ThrowIfNotSet(); + //Get the status code + ReadOnlyMemory status = response.Headers.FirstOrDefault(static a => a.Key == HeaderCommand.Status).Value; + //Check status code + if (status.Span.Equals(ResponseCodes.Okay, StringComparison.OrdinalIgnoreCase)) + { + return; + } + else if(status.Span.Equals(ResponseCodes.NotFound, StringComparison.OrdinalIgnoreCase)) + { + throw new ObjectNotFoundException($"object {objectId} not found on remote server"); + } + //Invalid status + throw new InvalidStatusException("Invalid status code recived for object upsert request", status.ToString()); + } + finally + { + //Return the request(clears data and reset) + client.ReturnRequest(request); + } + } + + /// + /// Asynchronously deletes an object in the remote store + /// + /// + /// The id of the object to update or replace + /// A token to cancel the operation + /// A task that resolves when the operation has completed + /// + /// + /// + /// + public static async Task DeleteObjectAsync(this FBMClient client, string objectId, CancellationToken cancellationToken = default) + { + _ = client ?? throw new ArgumentNullException(nameof(client)); + + client.LogDebug("Deleting object {id}", objectId); + //Rent a new request + FBMRequest request = client.RentRequest(); + try + { + //Set action as delete + request.WriteHeader(HeaderCommand.Action, Actions.Delete); + //Set session-id header + request.WriteHeader(Constants.ObjectId, objectId); + + //Make request + using FBMResponse response = await client.SendAsync(request, cancellationToken); + + response.ThrowIfNotSet(); + //Get the status code + ReadOnlyMemory status = response.Headers.FirstOrDefault(static a => a.Key == HeaderCommand.Status).Value; + if (status.Span.Equals(ResponseCodes.Okay, StringComparison.Ordinal)) + { + return; + } + else if(status.Span.Equals(ResponseCodes.NotFound, StringComparison.OrdinalIgnoreCase)) + { + throw new ObjectNotFoundException($"object {objectId} not found on remote server"); + } + throw new InvalidStatusException("Invalid status code recived for object get request", status.ToString()); + } + finally + { + client.ReturnRequest(request); + } + } + + /// + /// Dequeues a change event from the server event queue for the current connection, or waits until a change happens + /// + /// + /// A token to cancel the deuque operation + /// A that contains the modified object id and optionally its new id + public static async Task WaitForChangeAsync(this FBMClient client, CancellationToken cancellationToken = default) + { + //Rent a new request + FBMRequest request = client.RentRequest(); + try + { + //Set action as event dequeue to dequeue a change event + request.WriteHeader(HeaderCommand.Action, Actions.Dequeue); + + //Make request + using FBMResponse response = await client.SendAsync(request, cancellationToken); + + response.ThrowIfNotSet(); + + return new() + { + Status = response.Headers.FirstOrDefault(static a => a.Key == HeaderCommand.Status).Value.ToString(), + CurrentId = response.Headers.SingleOrDefault(static v => v.Key == Constants.ObjectId).Value.ToString(), + NewId = response.Headers.SingleOrDefault(static v => v.Key == Constants.NewObjectId).Value.ToString() + }; + } + finally + { + client.ReturnRequest(request); + } + } + + /// + /// Gets the Object-id for the request message, or throws an if not specified + /// + /// + /// The id of the object requested + /// + public static string ObjectId(this FBMContext context) + { + return context.Request.Headers.First(static kvp => kvp.Key == Constants.ObjectId).Value.ToString(); + } + /// + /// Gets the new ID of the object if specified from the request. Null if the request did not specify an id update + /// + /// + /// The new ID of the object if speicifed, null otherwise + public static string? NewObjectId(this FBMContext context) + { + return context.Request.Headers.FirstOrDefault(static kvp => kvp.Key == Constants.NewObjectId).Value.ToString(); + } + /// + /// Gets the request method for the request + /// + /// + /// The request method string + public static string Method(this FBMContext context) + { + return context.Request.Headers.First(static kvp => kvp.Key == HeaderCommand.Action).Value.ToString(); + } + /// + /// Closes a response with a status code + /// + /// + /// The status code to send to the client + public static void CloseResponse(this FBMContext context, string responseCode) + { + context.Response.WriteHeader(HeaderCommand.Status, responseCode); + } + + + /// + /// Initializes the worker for a reconnect policy and returns an object that can listen for changes + /// and configure the connection as necessary + /// + /// + /// The amount of time to wait between retries + /// The uri to reconnect the client to + /// A for listening for retry events + public static ClientRetryManager SetReconnectPolicy(this T worker, TimeSpan retryDelay, Uri serverUri) where T: IStatefulConnection + { + //Return new manager + return new (worker, retryDelay, serverUri); + } + } +} diff --git a/lib/VNLib.Data.Caching/src/ClientRetryManager.cs b/lib/VNLib.Data.Caching/src/ClientRetryManager.cs new file mode 100644 index 0000000..5cee583 --- /dev/null +++ b/lib/VNLib.Data.Caching/src/ClientRetryManager.cs @@ -0,0 +1,107 @@ +/* +* Copyright (c) 2022 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Data.Caching +* File: ClientRetryManager.cs +* +* ClientRetryManager.cs is part of VNLib.Data.Caching which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Data.Caching is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Data.Caching is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System; +using System.Threading.Tasks; +using System.Security.Cryptography; + +using VNLib.Utils; +using VNLib.Net.Messaging.FBM.Client; + +namespace VNLib.Data.Caching +{ + /// + /// Manages a reconnect policy + /// + public class ClientRetryManager : VnDisposeable where T: IStatefulConnection + { + const int RetryRandMaxMsDelay = 1000; + + private readonly TimeSpan RetryDelay; + private readonly T Client; + private readonly Uri ServerUri; + + internal ClientRetryManager(T worker, TimeSpan delay, Uri serverUri) + { + this.Client = worker; + this.RetryDelay = delay; + this.ServerUri = serverUri; + //Register disconnect listener + worker.ConnectionClosed += Worker_Disconnected; + } + + private void Worker_Disconnected(object? sender, EventArgs args) + { + //Exec retry on exit + _ = RetryAsync().ConfigureAwait(false); + } + + + /// + /// Raised before client is to be reconnected + /// + public event Action? OnBeforeReconnect; + /// + /// Raised when the client fails to reconnect. Should return a value that instructs the + /// manager to reconnect + /// + public event Func? OnReconnectFailed; + + async Task RetryAsync() + { + + //Begin random delay with retry ms + int randomDelayMs = (int)RetryDelay.TotalMilliseconds; + //random delay to add to prevent retry-storm + randomDelayMs += RandomNumberGenerator.GetInt32(RetryRandMaxMsDelay); + //Retry loop + bool retry = true; + while (retry) + { + try + { + //Inform Listener for the retry + OnBeforeReconnect?.Invoke(Client); + //wait for delay before reconnecting + await Task.Delay(randomDelayMs); + //Reconnect async + await Client.ConnectAsync(ServerUri).ConfigureAwait(false); + break; + } + catch (Exception Ex) + { + //Invoke error handler, may be null, incase exit + retry = OnReconnectFailed?.Invoke(Client, Ex) ?? false; + } + } + } + + /// + protected override void Free() + { + //Unregister the event listener + Client.ConnectionClosed -= Worker_Disconnected; + } + } +} diff --git a/lib/VNLib.Data.Caching/src/Constants.cs b/lib/VNLib.Data.Caching/src/Constants.cs new file mode 100644 index 0000000..3fb87e0 --- /dev/null +++ b/lib/VNLib.Data.Caching/src/Constants.cs @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2022 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Data.Caching +* File: Constants.cs +* +* Constants.cs is part of VNLib.Data.Caching which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Data.Caching is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Data.Caching is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System; + +using VNLib.Net.Messaging.FBM; + +namespace VNLib.Data.Caching +{ + public static class Constants + { + /// + /// Contains constants the define actions + /// + public static class Actions + { + public const string Get= "g"; + public const string AddOrUpdate = "u"; + public const string Delete = "d"; + public const string Dequeue = "dq"; + } + /// + /// Containts constants for operation response codes + /// + public static class ResponseCodes + { + public const string Okay = "ok"; + public const string Error = "err"; + public const string NotFound = "nf"; + } + + public const HeaderCommand ObjectId = (HeaderCommand)0xAA; + public const HeaderCommand NewObjectId = (HeaderCommand)0xAB; + } +} diff --git a/lib/VNLib.Data.Caching/src/Exceptions/InvalidStatusException.cs b/lib/VNLib.Data.Caching/src/Exceptions/InvalidStatusException.cs new file mode 100644 index 0000000..2296774 --- /dev/null +++ b/lib/VNLib.Data.Caching/src/Exceptions/InvalidStatusException.cs @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2022 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Data.Caching +* File: InvalidStatusException.cs +* +* InvalidStatusException.cs is part of VNLib.Data.Caching which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Data.Caching is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Data.Caching is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System; + +using VNLib.Net.Messaging.FBM; + +namespace VNLib.Data.Caching.Exceptions +{ + /// + /// Raised when the response status code of an FBM Request message is not valid for + /// the specified request + /// + public class InvalidStatusException : InvalidResponseException + { + private readonly string? StatusCode; + /// + /// Initalizes a new with the specfied status code + /// + /// + /// + public InvalidStatusException(string message, string statusCode):this(message) + { + this.StatusCode = statusCode; + } + + /// + public InvalidStatusException() + { + } + /// + public InvalidStatusException(string message) : base(message) + { + } + /// + public InvalidStatusException(string message, Exception innerException) : base(message, innerException) + { + } + /// + public override string Message => $"InvalidStatusException: Status Code {StatusCode} \r\n {base.Message}"; + } +} diff --git a/lib/VNLib.Data.Caching/src/Exceptions/MessageTooLargeException.cs b/lib/VNLib.Data.Caching/src/Exceptions/MessageTooLargeException.cs new file mode 100644 index 0000000..c306ba5 --- /dev/null +++ b/lib/VNLib.Data.Caching/src/Exceptions/MessageTooLargeException.cs @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2022 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Data.Caching +* File: MessageTooLargeException.cs +* +* MessageTooLargeException.cs is part of VNLib.Data.Caching which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Data.Caching is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Data.Caching is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System; +using System.Runtime.Serialization; + +using VNLib.Net.Messaging.FBM; + +namespace VNLib.Data.Caching.Exceptions +{ + /// + /// Raised when a request (or server response) calculates the size of the message to be too large to proccess + /// + public class MessageTooLargeException : FBMException + { + /// + public MessageTooLargeException() + {} + /// + public MessageTooLargeException(string message) : base(message) + {} + /// + public MessageTooLargeException(string message, Exception innerException) : base(message, innerException) + {} + /// + protected MessageTooLargeException(SerializationInfo info, StreamingContext context) : base(info, context) + {} + } +} diff --git a/lib/VNLib.Data.Caching/src/Exceptions/ObjectNotFoundException.cs b/lib/VNLib.Data.Caching/src/Exceptions/ObjectNotFoundException.cs new file mode 100644 index 0000000..e996ad6 --- /dev/null +++ b/lib/VNLib.Data.Caching/src/Exceptions/ObjectNotFoundException.cs @@ -0,0 +1,47 @@ +/* +* Copyright (c) 2022 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Data.Caching +* File: ObjectNotFoundException.cs +* +* ObjectNotFoundException.cs is part of VNLib.Data.Caching which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Data.Caching is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Data.Caching is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System; + +namespace VNLib.Data.Caching.Exceptions +{ + /// + /// Raised when a command was executed on a desired object in the remote cache + /// but the object was not found + /// + public class ObjectNotFoundException : InvalidStatusException + { + internal ObjectNotFoundException() + {} + + internal ObjectNotFoundException(string message) : base(message) + {} + + internal ObjectNotFoundException(string message, string statusCode) : base(message, statusCode) + {} + + internal ObjectNotFoundException(string message, Exception innerException) : base(message, innerException) + {} + } +} diff --git a/lib/VNLib.Data.Caching/src/IGlobalCacheProvider.cs b/lib/VNLib.Data.Caching/src/IGlobalCacheProvider.cs new file mode 100644 index 0000000..eeee9e2 --- /dev/null +++ b/lib/VNLib.Data.Caching/src/IGlobalCacheProvider.cs @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2022 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Data.Caching +* File: IGlobalCacheProvider.cs +* +* IGlobalCacheProvider.cs is part of VNLib.Data.Caching which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Data.Caching is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Data.Caching is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System.Threading; +using System.Threading.Tasks; + +namespace VNLib.Data.Caching +{ + /// + /// A global cache provider interface + /// + public interface IGlobalCacheProvider + { + /// + /// Gets a value that indicates if the cache provider is currently available + /// + bool IsConnected { get; } + + /// + /// Asynchronously gets a value from the backing cache store + /// + /// + /// The key identifying the object to recover from cache + /// A token to cancel the async operation + /// The value if found, or null if it does not exist in the store + Task GetAsync(string key, CancellationToken cancellation); + + /// + /// Asynchronously sets (or updates) a cached value in the backing cache store + /// + /// + /// The key identifying the object to recover from cache + /// An optional key that will be changed for the new object + /// A token to cancel the async operation + /// The value to set at the given key + /// A task that completes when the update operation has compelted + Task AddOrUpdateAsync(string key, string? newKey, T value, CancellationToken cancellation); + + /// + /// Asynchronously deletes an item from cache by its key + /// + /// The key identifying the item to delete + /// A token to cancel the async operation + /// A task that completes when the delete operation has compelted + Task DeleteAsync(string key, CancellationToken cancellation); + } +} \ No newline at end of file diff --git a/lib/VNLib.Data.Caching/src/VNLib.Data.Caching.csproj b/lib/VNLib.Data.Caching/src/VNLib.Data.Caching.csproj new file mode 100644 index 0000000..eeaaa11 --- /dev/null +++ b/lib/VNLib.Data.Caching/src/VNLib.Data.Caching.csproj @@ -0,0 +1,46 @@ + + + + net6.0 + Vaughn Nugent + Copyright © 2023 Vaughn Nugent + 1.0.1.1 + True + enable + + https://www.vaughnnugent.com/resources/software + True + \\vaughnnugent.com\Internal\Folder Redirection\vman\Documents\Programming\Software\StrongNameingKey.snk + + + + true + latest-all + $(AssemblyName) + Provides constants and extensions for a key-value data caching protocol layer atop the Fixed Buffer Messaging protocol to work VNCache servers. Provides rapid cache development + README.md + + + + + True + \ + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/lib/VNLib.Data.Caching/src/WaitForChangeResult.cs b/lib/VNLib.Data.Caching/src/WaitForChangeResult.cs new file mode 100644 index 0000000..76cc002 --- /dev/null +++ b/lib/VNLib.Data.Caching/src/WaitForChangeResult.cs @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2022 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Data.Caching +* File: WaitForChangeResult.cs +* +* WaitForChangeResult.cs is part of VNLib.Data.Caching which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Data.Caching is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Data.Caching is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +namespace VNLib.Data.Caching +{ + /// + /// The result of a cache server change event + /// + public readonly struct WaitForChangeResult + { + /// + /// The operation status code + /// + public readonly string Status { get; init; } + /// + /// The current (or old) id of the element that changed + /// + public readonly string CurrentId { get; init; } + /// + /// The new id of the element that changed + /// + public readonly string NewId { get; init; } + } +} -- cgit