diff --git a/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/AddMessageAsyncTests/AddMessageAsyncTests.cs b/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/AddMessageAsyncTests/AddMessageAsyncTests.cs index 1241905..dbce3eb 100644 --- a/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/AddMessageAsyncTests/AddMessageAsyncTests.cs +++ b/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/AddMessageAsyncTests/AddMessageAsyncTests.cs @@ -8,7 +8,7 @@ public class AddMessageAsyncTests : CustomAzuriteTestContainer public async Task AddMessageAsync_GivenSomeSimpleString_ShouldAddTheMessageToTheQueue() { // Arrange. - var cancellationToken = new CancellationToken(); + var cancellationToken = CancellationToken.None; var message = "hello"; // Act. @@ -24,7 +24,7 @@ public async Task AddMessageAsync_GivenSomeSimpleString_ShouldAddTheMessageToThe public async Task AddMessageAsync_GivenASimpleInt_ShouldAddTheMessageToTheQueue() { // Arrange. - var cancellationToken = new CancellationToken(); + var cancellationToken = CancellationToken.None; var message = 1234; // Act. @@ -40,7 +40,7 @@ public async Task AddMessageAsync_GivenASimpleInt_ShouldAddTheMessageToTheQueue( public async Task AddMessageAsync_GivenAComplexInstance_ShouldAddTheMessageToTheQueue() { // Arrange. - var cancellationToken = new CancellationToken(); + var cancellationToken = CancellationToken.None; var message = new FakeMessage(10); // Act. @@ -57,7 +57,7 @@ public async Task AddMessageAsync_GivenAComplexInstance_ShouldAddTheMessageToThe public async Task AddMessageAsync_GivenALargeComplexInstance_ShouldAddTheMessageToABlogAndThenAGuidToTheQueue() { // Arrange. - var cancellationToken = new CancellationToken(); + var cancellationToken = CancellationToken.None; var message = new FakeMessage(QueueClient.MessageMaxBytes + 1); // Act. diff --git a/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/AddMessagesAsyncTests/AddMessagesAsyncTests.cs b/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/AddMessagesAsyncTests/AddMessagesAsyncTests.cs index 3d17554..5171c1f 100644 --- a/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/AddMessagesAsyncTests/AddMessagesAsyncTests.cs +++ b/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/AddMessagesAsyncTests/AddMessagesAsyncTests.cs @@ -8,7 +8,7 @@ public class AddMessagesAsyncTests : CustomAzuriteTestContainer public async Task AddMessagesAsync_GivenSomeSimpleStrings_ShouldAddThemAllToTheQueue() { // Arrange. - var cancellationToken = new CancellationToken(); + var cancellationToken = CancellationToken.None; var messages = new[] { "aaa", "bbb", "ccc", "ddd" }; // Act. @@ -29,7 +29,7 @@ public async Task AddMessagesAsync_GivenSomeSimpleStrings_ShouldAddThemAllToTheQ public async Task AddMessagesAsync_GivenSomeComplexInstances_ShouldAddThemAllToTheQueue() { // Arrange. - var cancellationToken = new CancellationToken(); + var cancellationToken = CancellationToken.None; var messages = new[] { new FakeMessage(20), @@ -57,7 +57,7 @@ public async Task AddMessagesAsync_GivenSomeComplexInstances_ShouldAddThemAllToT public async Task AddMessagesAsync_GivenSomeLargeComplexInstances_ShouldAddThemAllToTheblobAndQueue() { // Arrange. - var cancellationToken = new CancellationToken(); + var cancellationToken = CancellationToken.None; var messages = new[] { new FakeMessage(QueueClient.MessageMaxBytes + 1), diff --git a/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/DeleteMessageAsyncTests/DeleteMessageAsyncTests.cs b/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/DeleteMessageAsyncTests/DeleteMessageAsyncTests.cs index 03413ce..59ec6c6 100644 --- a/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/DeleteMessageAsyncTests/DeleteMessageAsyncTests.cs +++ b/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/DeleteMessageAsyncTests/DeleteMessageAsyncTests.cs @@ -8,11 +8,12 @@ public class DeleteMessageAsyncTests : CustomAzuriteTestContainer public async Task DeleteMessageAsync_GivenALargeComplexInstance_ShouldDeleteTheBlobItemAndQueueMessage() { // Arrange. - var cancellationToken = new CancellationToken(); + var cancellationToken = CancellationToken.None; var message = new FakeMessage(QueueClient.MessageMaxBytes + 1); await HybridQueue.AddMessageAsync(message, default); - var retrievedMessage = await HybridQueue.GetMessageAsync(cancellationToken)!; + var retrievedMessage = await HybridQueue.GetMessageAsync(cancellationToken); + retrievedMessage.ShouldNotBeNull(); // Act. await HybridQueue.DeleteMessageAsync(retrievedMessage, default); diff --git a/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/GetMessagesAsyncTests/GetMessagesAsyncTests.cs b/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/GetMessagesAsyncTests/GetMessagesAsyncTests.cs index 94b124d..aacab5d 100644 --- a/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/GetMessagesAsyncTests/GetMessagesAsyncTests.cs +++ b/src/SimpleAzure.Storage.HybridQueue.Tests/IntegrationTests/GetMessagesAsyncTests/GetMessagesAsyncTests.cs @@ -10,7 +10,7 @@ public class GetMessagesAsyncTests : CustomAzuriteTestContainer public async Task GetMessagesAsync_GivenAnInvalidMaxMessages_ShouldThrowAnException(int maxMessages) { // Arrange. - var cancellationToken = new CancellationToken(); + var cancellationToken = CancellationToken.None; // Act. var exception = await Should.ThrowAsync(HybridQueue.GetMessagesAsync( diff --git a/src/SimpleAzure.Storage.HybridQueue/Helpers.cs b/src/SimpleAzure.Storage.HybridQueue/Helpers.cs index aa8c19f..17a9be3 100644 --- a/src/SimpleAzure.Storage.HybridQueue/Helpers.cs +++ b/src/SimpleAzure.Storage.HybridQueue/Helpers.cs @@ -1,3 +1,6 @@ +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + namespace WorldDomination.SimpleAzure.Storage.HybridQueues; internal static class Helpers @@ -13,4 +16,16 @@ internal static bool IsASimpleType(this Type type) => type.IsPrimitive || type == typeof(string) || type == typeof(decimal); + + /// + /// Has the same intention as the null suppression operator (!) but throws an exception at the use site, + /// rather than the use site which occurs some unknown time later. + /// + internal static T AssumeNotNull( + [NotNull] this T? item, + [CallerArgumentExpression(nameof(item))] string? expr = null) + where T : class + { + return item ?? throw new InvalidOperationException($"Expected '{expr}' to be non-null."); + } } diff --git a/src/SimpleAzure.Storage.HybridQueue/HybridMessage.cs b/src/SimpleAzure.Storage.HybridQueue/HybridMessage.cs index 3777a3c..b43258a 100644 --- a/src/SimpleAzure.Storage.HybridQueue/HybridMessage.cs +++ b/src/SimpleAzure.Storage.HybridQueue/HybridMessage.cs @@ -1,3 +1,3 @@ namespace WorldDomination.SimpleAzure.Storage.HybridQueues; -public record class HybridMessage(T? Content, string MessageId, string PopeReceipt, Guid? BlobId); +public sealed record HybridMessage(T Content, string MessageId, string PopeReceipt, Guid? BlobId); diff --git a/src/SimpleAzure.Storage.HybridQueue/HybridQueue.cs b/src/SimpleAzure.Storage.HybridQueue/HybridQueue.cs index 693add6..d7f0880 100644 --- a/src/SimpleAzure.Storage.HybridQueue/HybridQueue.cs +++ b/src/SimpleAzure.Storage.HybridQueue/HybridQueue.cs @@ -7,21 +7,12 @@ namespace WorldDomination.SimpleAzure.Storage.HybridQueues; -public class HybridQueue : IHybridQueue +public sealed class HybridQueue(QueueClient queueClient, BlobContainerClient blobContainerClient, ILogger logger) : IHybridQueue { - private readonly QueueClient _queueClient; - private readonly BlobContainerClient _blobContainerClient; - private readonly ILogger _logger; + private readonly QueueClient _queueClient = queueClient; + private readonly BlobContainerClient _blobContainerClient = blobContainerClient; + private readonly ILogger _logger = logger; - /// - public HybridQueue(QueueClient queueClient, BlobContainerClient blobContainerClient, ILogger logger) - { - _queueClient = queueClient; - _blobContainerClient = blobContainerClient; - _logger = logger; - } - - /// public async Task AddMessageAsync(T item, TimeSpan? initialVisibilityDelay, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(item); @@ -33,27 +24,23 @@ public async Task AddMessageAsync(T item, TimeSpan? initialVisibilityDelay, C string message; // Don't waste effort serializing a string. It's already in a format that's ready to go. - if (typeof(T).IsASimpleType()) + if (item is string stringItem) { - if (item is string someString) - { - _logger.LogDebug("Item is a SimpleType: string."); - - message = someString; // Note: shouldn't allocate new memory. Should just be a reference to existing memory. - } - else - { - _logger.LogDebug("Item is a SimpleType: something other than a string."); + _logger.LogDebug("Item is a SimpleType: string."); + message = stringItem; + } + else if (typeof(T).IsASimpleType()) + { + _logger.LogDebug("Item is a SimpleType: something other than a string."); - message = item.ToString()!; - } + // IsASimpleType ensures that item is a primitive type, or decimal, and none of them + // return null from their ToString method. + message = item.ToString().AssumeNotNull(); } else { // It's a complex type, so serialize this as Json. - _logger.LogDebug("Item is a ComplexType: {complexType}", item.GetType().ToString()); - message = JsonSerializer.Serialize(item); } @@ -70,7 +57,7 @@ public async Task AddMessageAsync(T item, TimeSpan? initialVisibilityDelay, C var blobId = Guid.NewGuid().ToString(); // Unique Name/Identifier of this blob item. var binaryData = new BinaryData(message); - await _blobContainerClient.UploadBlobAsync(blobId, binaryData, cancellationToken); + await _blobContainerClient.UploadBlobAsync(blobId, binaryData, cancellationToken).ConfigureAwait(false); message = blobId; @@ -81,12 +68,11 @@ await _queueClient.SendMessageAsync( message, initialVisibilityDelay, null, - cancellationToken); + cancellationToken).ConfigureAwait(false); _logger.LogDebug("Finished adding an Item to the queue."); } - /// public async Task AddMessagesAsync( IEnumerable contents, TimeSpan? initialVisibilityDelay, @@ -105,21 +91,15 @@ public async Task AddMessagesAsync( } // Lets batch up these messages to make sure the awaiting of all the tasks doesn't go too crazy. - var contentsSize = contents.Count(); - var finalBatchSize = contentsSize > batchSize - ? batchSize - : contentsSize; - - foreach (var batch in contents.Chunk(finalBatchSize)) + foreach (var batch in contents.Chunk(batchSize)) { var tasks = batch.Select(content => AddMessageAsync(content, initialVisibilityDelay, cancellationToken)); // Execute this batch. - await Task.WhenAll(tasks); + await Task.WhenAll(tasks).ConfigureAwait(false); } } - /// public async Task DeleteMessageAsync(HybridMessage hybridMessage, CancellationToken cancellationToken) { using var _ = _logger.BeginCustomScope( @@ -131,51 +111,42 @@ public async Task DeleteMessageAsync(HybridMessage hybridMessage, Cancella _logger.LogDebug("Deleting a message."); // We start with any blobs. - if (hybridMessage.BlobId.HasValue) + if (hybridMessage.BlobId is { } blobId) { _logger.LogDebug("Deleting message from Blob Container."); - var blobClient = _blobContainerClient.GetBlobClient(hybridMessage.BlobId.Value.ToString()); - var blobResponse = await blobClient.DeleteIfExistsAsync(cancellationToken: cancellationToken); - + var blobClient = _blobContainerClient.GetBlobClient(blobId.ToString()); + var blobResponse = await blobClient.DeleteIfExistsAsync(cancellationToken: cancellationToken).ConfigureAwait(false); if (!blobResponse.Value) { _logger.LogWarning("Failed to delete message from Blob Container."); } } - var queueResponse = await _queueClient.DeleteMessageAsync(hybridMessage.MessageId, hybridMessage.PopeReceipt, cancellationToken); + var queueResponse = await _queueClient.DeleteMessageAsync(hybridMessage.MessageId, hybridMessage.PopeReceipt, cancellationToken).ConfigureAwait(false); _logger.LogDebug("Deleted a message from the queue."); } - /// - public async Task> GetMessageAsync(TimeSpan? visibilityTimeout, CancellationToken cancellationToken) + public async Task?> GetMessageAsync(TimeSpan? visibilityTimeout, CancellationToken cancellationToken) { - var messages = await GetMessagesAsync(1, visibilityTimeout, cancellationToken); + var messages = await GetMessagesAsync(1, visibilityTimeout, cancellationToken).ConfigureAwait(false); - if (messages?.Any() ?? false) + return messages switch { - if (messages.Count() > 1) - { - throw new InvalidOperationException($"Expected 1 message but received {messages.Count()} messages"); - } - - return messages.First(); - } - - return default; + [] => null, + [{ } first] => first, + _ => throw new InvalidOperationException($"Expected 1 message but received {messages.Count} messages") + }; } - /// - public async Task>> GetMessagesAsync( + public async Task>> GetMessagesAsync( int maxMessages, TimeSpan? visibilityTimeout, CancellationToken cancellationToken) { // Note: Why 32? That's the limit for Azure to pop at once. - if (maxMessages < 1 || - maxMessages > 32) + if (maxMessages is < 1 or > 32) { throw new ArgumentOutOfRangeException(nameof(maxMessages)); } @@ -186,73 +157,66 @@ public async Task>> GetMessagesAsync( _logger.LogDebug("About to receive queue message."); - var response = await _queueClient.ReceiveMessagesAsync(maxMessages, visibilityTimeout, cancellationToken); - - if (response == null || - response.Value == null) + var response = await _queueClient.ReceiveMessagesAsync(maxMessages, visibilityTimeout, cancellationToken).ConfigureAwait(false); + if (response?.Value is not { } messages) { _logger.LogDebug("Response was null or there were no Queue messages retrieved."); - - return Enumerable.Empty>(); + return Array.Empty>(); } - _logger.LogDebug("Received {} messages from queue.", response.Value.Length); - - var hybridMessageTasks = response.Value.Select(x => ParseMessageAsync(x, cancellationToken)); + _logger.LogDebug("Received {} messages from queue.", messages.Length); - var hybridMessages = await Task.WhenAll(hybridMessageTasks); + var hybridMessageTasks = messages.Select(x => ParseMessageAsync(x, cancellationToken)); + var hybridMessages = await Task.WhenAll(hybridMessageTasks).ConfigureAwait(false); return hybridMessages; } private async Task> ParseMessageAsync(QueueMessage queueMessage, CancellationToken cancellationToken) { - var message = queueMessage.Body?.ToString(); - - if (message == null) - { - return new HybridMessage(default, queueMessage.MessageId, queueMessage.PopReceipt, null); - } + var message = queueMessage.Body.ToString().AssumeNotNull(); if (Guid.TryParse(message, out var blobId)) { using var _ = _logger.BeginCustomScope((nameof(blobId), blobId)); - _logger.LogDebug("Retreiving item via Blob Storage."); + _logger.LogDebug("Retrieving item via Blob Storage."); // Lets grab the item from the Blob. var blobClient = _blobContainerClient.GetBlobClient(blobId.ToString()); - using var stream = await blobClient.OpenReadAsync(null, cancellationToken); + using var stream = await blobClient.OpenReadAsync(null, cancellationToken).ConfigureAwait(false); _logger.LogDebug("About to deserialize stream for a blob item from Blob Storage."); - var blobItem = await JsonSerializer.DeserializeAsync(stream, cancellationToken: cancellationToken)!; + var blobItem = await JsonSerializer.DeserializeAsync(stream, cancellationToken: cancellationToken).ConfigureAwait(false); _logger.LogDebug("Finished deserializing stream for a blob item from Blob Storage."); - var hybridMessage = new HybridMessage(blobItem, queueMessage.MessageId, queueMessage.PopReceipt, blobId); + if (blobItem is null) + { + throw new InvalidOperationException($"Could not deserialize blob '{blobId}' for message '{queueMessage.MessageId}'."); + } - return hybridMessage; + return new HybridMessage(blobItem, queueMessage.MessageId, queueMessage.PopReceipt, blobId); } else if (typeof(T).IsASimpleType()) { - _logger.LogDebug("Retreiving item: which is a simle type and not a guid/not in Blob Storage."); + _logger.LogDebug("Retrieving item: which is a simle type and not a guid/not in Blob Storage."); - // Do we have a GUID? Guid's are used to represent the blobId. + // Do we have a GUID? Guids are used to represent the blobId. var value = (T)Convert.ChangeType(message, typeof(T)); - var hybridMessage = new HybridMessage(value, queueMessage.MessageId, queueMessage.PopReceipt, null); - - return hybridMessage; + return new HybridMessage(value, queueMessage.MessageId, queueMessage.PopReceipt, null); } else { // Complex type, so lets assume it was serialized as Json ... so now we deserialize it. + _logger.LogDebug("Retrieving a complex item: assumed as json so deserializing it."); - _logger.LogDebug("Retreiving a complex item: assumed as json so deserializing it."); - - var item = JsonSerializer.Deserialize(message)!; - - var hybridMessage = new HybridMessage(item, queueMessage.MessageId, queueMessage.PopReceipt, null); + var item = JsonSerializer.Deserialize(message); + if (item is null) + { + throw new InvalidOperationException($"Could not deserialize complex type for message '{queueMessage.MessageId}'."); + } - return hybridMessage; + return new HybridMessage(item, queueMessage.MessageId, queueMessage.PopReceipt, null); } } } diff --git a/src/SimpleAzure.Storage.HybridQueue/IHybridQueue.cs b/src/SimpleAzure.Storage.HybridQueue/IHybridQueue.cs index 8b4dbd5..860c5ac 100644 --- a/src/SimpleAzure.Storage.HybridQueue/IHybridQueue.cs +++ b/src/SimpleAzure.Storage.HybridQueue/IHybridQueue.cs @@ -2,16 +2,6 @@ namespace WorldDomination.SimpleAzure.Storage.HybridQueues; public interface IHybridQueue { - /// - /// Initiates an asynchronous operation to add an item to the queue. - /// - /// Type of item. - /// An item to add to the queue. - /// A System.Threading.CancellationToken to observe while waiting for a task to complete. - /// A System.Threading.Tasks.Task object that represents the asynchronous operation. - /// If the item is a IsPrimitive (int, etc) or a string then it's stored -as is-. Otherwise, it is serialized to Json and then stored as Json.( - Task AddMessageAsync(T item, CancellationToken cancellationToken) => AddMessageAsync(item, null, cancellationToken); - /// /// Initiates an asynchronous operation to add an item to the queue. /// @@ -26,16 +16,6 @@ Task AddMessageAsync( TimeSpan? initialVisibilityDelay, CancellationToken cancellationToken); - /// - /// Initiates an asynchronous operation to add a batch messages to the queue. - /// - /// Type of item. - /// Collection of content to add to the queue. - /// A System.Threading.CancellationToken to observe while waiting for a task to complete. - /// A System.Threading.Tasks.Task object that represents the asynchronous operation. - /// If any item is a IsPrimitive (int, etc) or a string then it's stored -as is-. Otherwise, it is serialized to Json and then stored as Json.( - Task AddMessagesAsync(IEnumerable contents, CancellationToken cancellationToken) => - AddMessagesAsync(contents, null, 25, cancellationToken); /// /// Initiates an asynchronous operation to add a batch messages to the queue. @@ -61,15 +41,6 @@ Task AddMessagesAsync( /// A System.Threading.Tasks.Task object that represents the asynchronous operation. Task DeleteMessageAsync(HybridMessage hybridMessage, CancellationToken cancellationToken); - /// - /// Retrieves a message from a queue and wraps it in a simple Message class. - /// - /// Type of item. - /// A System.Threading.CancellationToken to observe while waiting for a task to complete. - /// A System.Threading.Tasks.Task object that represents the asynchronous operation. - /// The content of the message will attempt to be deserialized from Json. If the message is a Primitive type or a string, then the Json deserialization will be still run but no error should occur. - Task> GetMessageAsync(CancellationToken cancellationToken) => GetMessageAsync(null, cancellationToken); - /// /// Retrieves a message from a queue and wraps it in a simple Message class. /// @@ -78,17 +49,7 @@ Task AddMessagesAsync( /// A System.Threading.CancellationToken to observe while waiting for a task to complete. /// A System.Threading.Tasks.Task object that represents the asynchronous operation. /// The content of the message will attempt to be deserialized from Json. If the message is a Primitive type or a string, then the Json deserialization will be still run but no error should occur. - Task> GetMessageAsync(TimeSpan? visibilityTimeout, CancellationToken cancellationToken); - - /// - /// Retrieves a collection of messages from a queue and wraps each one in a simple Message class. - /// - /// Type of item. - /// A System.Threading.CancellationToken to observe while waiting for a task to complete. - /// A System.Threading.Tasks.Task object that represents the asynchronous operation. - /// The content of the message will attempt to be deserialized from Json. If the message is a Primitive type or a string, then the Json deserialization will be still run but no error should occur. - Task>> GetMessagesAsync(CancellationToken cancellationToken) => - GetMessagesAsync(32, null, cancellationToken); + Task?> GetMessageAsync(TimeSpan? visibilityTimeout, CancellationToken cancellationToken); /// /// Retrieves a collection of messages from a queue and wraps each one in a simple Message class. @@ -99,7 +60,7 @@ Task>> GetMessagesAsync(CancellationToken cancel /// A System.Threading.CancellationToken to observe while waiting for a task to complete. /// A System.Threading.Tasks.Task object that represents the asynchronous operation. /// The content of the message will attempt to be deserialized from Json. If the message is a Primitive type or a string, then the Json deserialization will be still run but no error should occur. - Task>> GetMessagesAsync( + Task>> GetMessagesAsync( int maxMessages, TimeSpan? visibilityTimeout, CancellationToken cancellationToken); diff --git a/src/SimpleAzure.Storage.HybridQueue/IHybridQueueExtensions.cs b/src/SimpleAzure.Storage.HybridQueue/IHybridQueueExtensions.cs new file mode 100644 index 0000000..3c9e741 --- /dev/null +++ b/src/SimpleAzure.Storage.HybridQueue/IHybridQueueExtensions.cs @@ -0,0 +1,50 @@ +namespace WorldDomination.SimpleAzure.Storage.HybridQueues; + +public static class IHybridQueueExtensions +{ + /// + /// Initiates an asynchronous operation to add an item to the queue. + /// + /// Type of item. + /// The queue to operate on + /// An item to add to the queue. + /// A System.Threading.CancellationToken to observe while waiting for a task to complete. + /// A System.Threading.Tasks.Task object that represents the asynchronous operation. + /// If the item is a IsPrimitive (int, etc) or a string then it's stored -as is-. Otherwise, it is serialized to Json and then stored as Json.( + public static Task AddMessageAsync(this IHybridQueue queue, T item, CancellationToken cancellationToken) => + queue.AddMessageAsync(item, null, cancellationToken); + + /// + /// Initiates an asynchronous operation to add a batch messages to the queue. + /// + /// Type of item. + /// The queue to operate on + /// Collection of content to add to the queue. + /// A System.Threading.CancellationToken to observe while waiting for a task to complete. + /// A System.Threading.Tasks.Task object that represents the asynchronous operation. + /// If any item is a IsPrimitive (int, etc) or a string then it's stored -as is-. Otherwise, it is serialized to Json and then stored as Json.( + public static Task AddMessagesAsync(this IHybridQueue queue, IEnumerable contents, CancellationToken cancellationToken) => + queue.AddMessagesAsync(contents, null, 25, cancellationToken); + + /// + /// Retrieves a message from a queue and wraps it in a simple Message class. + /// + /// Type of item. + /// The queue to operate on + /// A System.Threading.CancellationToken to observe while waiting for a task to complete. + /// A System.Threading.Tasks.Task object that represents the asynchronous operation. + /// The content of the message will attempt to be deserialized from Json. If the message is a Primitive type or a string, then the Json deserialization will be still run but no error should occur. + public static Task?> GetMessageAsync(this IHybridQueue queue, CancellationToken cancellationToken) => + queue.GetMessageAsync(null, cancellationToken); + + /// + /// Retrieves a collection of messages from a queue and wraps each one in a simple Message class. + /// + /// Type of item. + /// The queue to operate on + /// A System.Threading.CancellationToken to observe while waiting for a task to complete. + /// A System.Threading.Tasks.Task object that represents the asynchronous operation. + /// The content of the message will attempt to be deserialized from Json. If the message is a Primitive type or a string, then the Json deserialization will be still run but no error should occur. + public static Task>> GetMessagesAsync(this IHybridQueue queue, CancellationToken cancellationToken) => + queue.GetMessagesAsync(32, null, cancellationToken); +} diff --git a/src/SimpleAzure.Storage.HybridQueue/LoggingExtensions.cs b/src/SimpleAzure.Storage.HybridQueue/LoggingExtensions.cs index e5ccf58..0b2b0f1 100644 --- a/src/SimpleAzure.Storage.HybridQueue/LoggingExtensions.cs +++ b/src/SimpleAzure.Storage.HybridQueue/LoggingExtensions.cs @@ -2,23 +2,9 @@ namespace WorldDomination.SimpleAzure.Storage.HybridQueues; -public static class LoggerExtensions +internal static class LoggerExtensions { - public static IDisposable? BeginCustomScope(this ILogger logger, params (string Name, object? Value)[] scopeItems) - { - ArgumentNullException.ThrowIfNull(scopeItems); - - var scopeProps = new Dictionary(); - - foreach (var (name, value) in scopeItems) - { - scopeProps[name] = value; - } - - return logger.BeginScope(scopeProps); - } - - public static IDisposable? BeginCustomScope(this ILogger logger, params (string Name, object? Value)[] scopeItems) + internal static IDisposable? BeginCustomScope(this ILogger logger, params (string Name, object? Value)[] scopeItems) { ArgumentNullException.ThrowIfNull(scopeItems); diff --git a/src/SimpleAzure.Storage.HybridQueue/SimpleAzure.Storage.HybridQueue.csproj b/src/SimpleAzure.Storage.HybridQueue/SimpleAzure.Storage.HybridQueue.csproj index 9aa0c65..4464402 100644 --- a/src/SimpleAzure.Storage.HybridQueue/SimpleAzure.Storage.HybridQueue.csproj +++ b/src/SimpleAzure.Storage.HybridQueue/SimpleAzure.Storage.HybridQueue.csproj @@ -6,9 +6,9 @@ enable WorldDomination.$(MSBuildProjectName) WorldDomination.$(MSBuildProjectName.Replace(" ", "_")) + preview -