From 88c740ae41f64ef446e597efb08bbfd07859023e Mon Sep 17 00:00:00 2001 From: inikulshin Date: Thu, 21 Dec 2023 14:33:23 +0200 Subject: [PATCH 1/3] JsonExtensionData --- .../ManagementClientTests.cs | 125 ++++++++++++------ .../Model/OverviewSerializationTests.cs | 39 ++++-- .../IManagementClient.cs | 33 ++++- .../ManagementClient.cs | 15 +++ .../Model/Listener.cs | 22 ++- .../Model/Overview.cs | 19 ++- .../Model/PageCriteria.cs | 12 ++ .../Model/ParameterShovelValue.cs | 84 +++++++++--- .../Model/PolicyDefinition.cs | 10 +- .../EasyNetQ.Management.Client/Model/Queue.cs | 11 +- .../Model/SocketOpts.cs | 25 ++++ .../JsonExtensionDataExtensions.cs | 46 +++++++ 12 files changed, 363 insertions(+), 78 deletions(-) create mode 100644 Source/EasyNetQ.Management.Client/Model/SocketOpts.cs create mode 100644 Source/EasyNetQ.Management.Client/Serialization/JsonExtensionDataExtensions.cs diff --git a/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs b/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs index ab65405b..17742315 100644 --- a/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs +++ b/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs @@ -1,7 +1,10 @@ using EasyNetQ.Management.Client.Model; +using System.Text.Json; namespace EasyNetQ.Management.Client.IntegrationTests; +using JsonSerializer = System.Text.Json.JsonSerializer; + [Collection("RabbitMQ")] public class ManagementClientTests { @@ -747,9 +750,9 @@ public async Task Should_be_able_to_get_a_list_of_bindings_between_an_exchange_a var exchange = await EnsureExchangeExists(TestExchange); - var bindings = (await fixture.ManagementClient.GetQueueBindingsAsync(exchange, queue)).ToArray(); + var bindings = await fixture.ManagementClient.GetQueueBindingsAsync(exchange, queue); - bindings.Length.Should().Be(0); + bindings.Should().BeEmpty(); } [Fact] @@ -760,7 +763,7 @@ public async Task Should_be_able_to_get_a_list_of_bindings_between_an_exchange_a var bindings = await fixture.ManagementClient.GetExchangeBindingsAsync(exchange1, exchange2); - bindings.Count.Should().Be(0); + bindings.Should().BeEmpty(); } [Fact] @@ -787,9 +790,9 @@ public async Task Should_be_able_to_get_a_queue_by_name_with_all_detailed_inform ); queue.Name.Should().Be(TestQueue); - queue.MessagesDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesReadyDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesUnacknowledgedDetails.Samples.Count.Should().BeGreaterThan(0); + queue.MessagesDetails.Samples.Should().NotBeNullOrEmpty(); + queue.MessagesReadyDetails.Samples.Should().NotBeNullOrEmpty(); + queue.MessagesUnacknowledgedDetails.Samples.Should().NotBeNullOrEmpty(); } [Fact] @@ -803,9 +806,9 @@ public async Task Should_be_able_to_get_a_queue_by_name_with_detailed_length_inf var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue, new LengthsCriteria(age, increment)); queue.Name.Should().Be(TestQueue); - queue.MessagesDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesReadyDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesUnacknowledgedDetails.Samples.Count.Should().BeGreaterThan(0); + queue.MessagesDetails.Samples.Should().NotBeNullOrEmpty(); + queue.MessagesReadyDetails.Samples.Should().NotBeNullOrEmpty(); + queue.MessagesUnacknowledgedDetails.Samples.Should().NotBeNullOrEmpty(); } [Fact] @@ -1148,7 +1151,7 @@ public async Task Should_get_exchanges_with_pagination() { var page = await fixture.ManagementClient.GetExchangesByPageAsync(new PageCriteria(1, 7, "amq")); - page.Items.Count.Should().BeGreaterThan(0); + page.Items.Should().NotBeNullOrEmpty(); } [Fact(Skip = "Requires at least an active federation")] @@ -1222,6 +1225,33 @@ public async Task Should_get_queues() } } + [Fact] + public async Task Should_get_queues_with_pagination() + { + foreach (var queue in await fixture.ManagementClient.GetQueuesAsync()) + await fixture.ManagementClient.DeleteQueueAsync(queue); + + await CreateTestQueue("1"); + await CreateTestQueue("2"); + + var firstPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(1, 1)); + firstPage.Items.Count.Should().Be(1); + + var secondPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(2, 1)); + secondPage.Items.Count.Should().Be(1); + } + + [Fact] + public async Task Should_get_queues_by_vhost() + { + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + vhost.Name.Should().Be(TestVHost); + + await CreateTestQueueInVhost($"{TestVHost}_{TestQueue}", vhost); + (await fixture.ManagementClient.GetQueuesAsync(vhost)).Should().NotBeNullOrEmpty(); + } + [Fact] public async Task Should_get_queues_without_stats() { @@ -1230,9 +1260,8 @@ public async Task Should_get_queues_without_stats() queues.Should().NotBeNullOrEmpty(); } - [Fact] - public async Task Should_get_queues_with_pagination() + public async Task Should_get_queues_without_stats_with_pagination() { foreach (var queue in await fixture.ManagementClient.GetQueuesAsync()) await fixture.ManagementClient.DeleteQueueAsync(queue); @@ -1240,22 +1269,22 @@ public async Task Should_get_queues_with_pagination() await CreateTestQueue("1"); await CreateTestQueue("2"); - var firstPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(1, 1)); + var firstPage = await fixture.ManagementClient.GetQueuesWithoutStatsByPageAsync(new PageCriteria(1, 1)); firstPage.Items.Count.Should().Be(1); - var secondPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(2, 1)); + var secondPage = await fixture.ManagementClient.GetQueuesWithoutStatsByPageAsync(new PageCriteria(2, 1)); secondPage.Items.Count.Should().Be(1); } [Fact] - public async Task Should_get_queues_by_vhost() + public async Task Should_get_queues_without_stats_by_vhost() { await fixture.ManagementClient.CreateVhostAsync(TestVHost); var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); vhost.Name.Should().Be(TestVHost); await CreateTestQueueInVhost($"{TestVHost}_{TestQueue}", vhost); - (await fixture.ManagementClient.GetQueuesAsync(vhost)).Count.Should().BeGreaterThan(0); + (await fixture.ManagementClient.GetQueuesWithoutStatsAsync(vhost)).Should().NotBeNullOrEmpty(); } [Fact] @@ -1301,30 +1330,39 @@ public async Task Should_be_able_to_create_shovel_parameter_on_queue() var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); var shovelName = "queue-shovel"; - - await fixture.ManagementClient.CreateShovelAsync( - vhostName: Vhost.Name, - shovelName, - new ParameterShovelValue + var parameterShovelValue = new ParameterShovelValue ( SrcProtocol: AmqpProtocol.AMQP091, SrcUri: srcUri.ToString(), SrcQueue: "test-queue-src", - SrcExchange: null, - SrcExchangeKey: null, + SrcQueueArguments: new Dictionary { { "x-queue-mode", "lazy" } }, SrcDeleteAfter: "never", + SrcPrefetchCount: 10, DestProtocol: AmqpProtocol.AMQP091, DestUri: destUri.ToString(), DestQueue: "test-queue-dest", - DestExchange: null, + DestQueueArguments: new Dictionary { { "x-queue-mode", "lazy" } }, + DestAddForwardHeaders: false, + DestAddTimestampHeader: false, AckMode: "on-confirm", - AddForwardHeaders: false - ) + ReconnectDelay: 10 + ); + + await fixture.ManagementClient.CreateShovelAsync( + vhostName: Vhost.Name, + shovelName, + parameterShovelValue ); var parameter = await fixture.ManagementClient.GetShovelAsync(Vhost.Name, shovelName); Assert.Equal(shovelName, parameter.Name); + parameter.Value.Should().BeOfType(); + if (parameter.Value is JsonElement jsonElement) + { + var actualParameterShovelValue = JsonSerializer.Deserialize(jsonElement.GetRawText()); + actualParameterShovelValue.Should().BeEquivalentTo(parameterShovelValue); + } } [Fact] @@ -1334,30 +1372,39 @@ public async Task Should_be_able_to_create_shovel_parameter_on_exchange() var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); var shovelName = "exchange-shovel"; - - await fixture.ManagementClient.CreateShovelAsync( - vhostName: Vhost.Name, - shovelName, - new ParameterShovelValue + var parameterShovelValue = new ParameterShovelValue ( SrcProtocol: AmqpProtocol.AMQP091, SrcUri: srcUri.ToString(), SrcExchange: "test-exchange-src", - SrcExchangeKey: null, - SrcQueue: null, + SrcExchangeKey: "aaa", SrcDeleteAfter: "never", + SrcPrefetchCount: 10, DestProtocol: AmqpProtocol.AMQP091, DestUri: destUri.ToString(), DestExchange: "test-exchange-dest", - DestQueue: null, + DestExchangeKey: "bbb", + DestAddForwardHeaders: false, + DestAddTimestampHeader: false, AckMode: "on-confirm", - AddForwardHeaders: false - ) + ReconnectDelay: 10 + ); + + await fixture.ManagementClient.CreateShovelAsync( + vhostName: Vhost.Name, + shovelName, + parameterShovelValue ); - var parameters = await fixture.ManagementClient.GetParametersAsync(); + var parameter = await fixture.ManagementClient.GetShovelAsync(Vhost.Name, shovelName); - Assert.Contains(parameters, p => p.Name == shovelName); + Assert.Equal(shovelName, parameter.Name); + parameter.Value.Should().BeOfType(); + if (parameter.Value is JsonElement jsonElement) + { + var actualParameterShovelValue = JsonSerializer.Deserialize(jsonElement.GetRawText()); + actualParameterShovelValue.Should().BeEquivalentTo(parameterShovelValue); + } } [Fact] @@ -1391,7 +1438,7 @@ await fixture.ManagementClient.CreateShovelAsync( DestExchange: "test-exchange-dest", DestQueue: null, AckMode: "on-confirm", - AddForwardHeaders: false + DestAddForwardHeaders: false ) ); diff --git a/Source/EasyNetQ.Management.Client.Tests/Model/OverviewSerializationTests.cs b/Source/EasyNetQ.Management.Client.Tests/Model/OverviewSerializationTests.cs index 9b35c695..a17dec3d 100755 --- a/Source/EasyNetQ.Management.Client.Tests/Model/OverviewSerializationTests.cs +++ b/Source/EasyNetQ.Management.Client.Tests/Model/OverviewSerializationTests.cs @@ -60,7 +60,8 @@ public void Should_deserialize() Node: "rabbit@localhost", Protocol: "amqp", IpAddress: "127.0.0.1", - Port: 5672 + Port: 5672, + SocketOpts: new SocketOpts(Backlog: 128, Nodelay: true, ExitOnClose: false) ), new( Node: "rabbit@localhost", @@ -72,25 +73,29 @@ public void Should_deserialize() Node: "rabbit@localhost", Protocol: "http", IpAddress: "::", - Port: 15672 + Port: 15672, + SocketOpts: new SocketOpts() ), new( Node: "rabbit@localhost", Protocol: "mqtt", IpAddress: "::", - Port: 1883 + Port: 1883, + SocketOpts: new SocketOpts(Backlog: 128, Nodelay: true) ), new( Node: "rabbit@localhost", Protocol: "stomp", IpAddress: "::", - Port: 61613 + Port: 61613, + SocketOpts: new SocketOpts(Backlog: 128, Nodelay: true) ), new( Node: "rabbit@localhost", Protocol: "stream", IpAddress: "::", - Port: 5552 + Port: 5552, + SocketOpts: new SocketOpts(Backlog: 128, Nodelay: true) ) }, Contexts: Array.Empty() @@ -138,7 +143,8 @@ public void Should_deserialize() Node: "rabbit@localhost", Protocol: "amqp", IpAddress: "127.0.0.1", - Port: 5672 + Port: 5672, + SocketOpts: new SocketOpts(Backlog: 128, Nodelay: true, ExitOnClose: false) ), new( Node: "rabbit@localhost", @@ -150,25 +156,29 @@ public void Should_deserialize() Node: "rabbit@localhost", Protocol: "http", IpAddress: "::", - Port: 15672 + Port: 15672, + SocketOpts: new SocketOpts() ), new( Node: "rabbit@localhost", Protocol: "mqtt", IpAddress: "::", - Port: 1883 + Port: 1883, + SocketOpts: new SocketOpts(Backlog: 128, Nodelay: true) ), new( Node: "rabbit@localhost", Protocol: "stomp", IpAddress: "::", - Port: 61613 + Port: 61613, + SocketOpts: new SocketOpts(Backlog: 128, Nodelay: true) ), new( Node: "rabbit@localhost", Protocol: "stream", IpAddress: "::", - Port: 5552 + Port: 5552, + SocketOpts: new SocketOpts(Backlog: 128, Nodelay: true) ) }, Contexts: new Context[] @@ -181,7 +191,14 @@ public void Should_deserialize() ) } ) - } + }, + options => options + .Excluding(o => o.ExtensionData) + .Excluding(o => o.JsonExtensionData) + .For(o => o.Listeners).Exclude(l => l.ExtensionData) + .For(o => o.Listeners).Exclude(l => l.JsonExtensionData) + .For(o => o.Listeners).Exclude(l => l.SocketOpts.ExtensionData) + .For(o => o.Listeners).Exclude(l => l.SocketOpts.JsonExtensionData) ); } } diff --git a/Source/EasyNetQ.Management.Client/IManagementClient.cs b/Source/EasyNetQ.Management.Client/IManagementClient.cs index dad5582e..bd066f73 100755 --- a/Source/EasyNetQ.Management.Client/IManagementClient.cs +++ b/Source/EasyNetQ.Management.Client/IManagementClient.cs @@ -148,12 +148,37 @@ Task GetChannelAsync( Task> GetQueuesByPageAsync(string vhostName, PageCriteria pageCriteria, CancellationToken cancellationToken = default); /// - /// A list of all queues. + /// A list of all queues without stats. /// /// /// Task> GetQueuesWithoutStatsAsync(CancellationToken cancellationToken = default); + /// + /// A list of queues for a page. + /// + /// + /// + /// + Task> GetQueuesWithoutStatsByPageAsync(PageCriteria pageCriteria, CancellationToken cancellationToken = default); + + /// + /// A list of all queues for a virtual host. + /// + /// + /// + /// + Task> GetQueuesWithoutStatsAsync(string vhostName, CancellationToken cancellationToken = default); + + /// + /// A list of queues for a page for a virtual host. + /// + /// + /// + /// + /// + Task> GetQueuesWithoutStatsByPageAsync(string vhostName, PageCriteria pageCriteria, CancellationToken cancellationToken = default); + /// /// A list of all bindings. /// @@ -443,13 +468,13 @@ Task DeleteQueueBindingAsync( /// /// /// - /// + /// /// /// Task DeleteExchangeBindingAsync( string vhostName, string fromExchangeName, - string sourceExchangeName, + string toExchangeName, string propertiesKey, CancellationToken cancellationToken = default ); @@ -562,7 +587,7 @@ Task DeleteTopicPermissionAsync( /// /// Declares a test queue, then publishes and consumes a message. Intended for use /// by monitoring tools. If everything is working correctly, will return true. - /// Note: the test queue will not be deleted (to to prevent queue churn if this + /// Note: the test queue will not be deleted (to prevent queue churn if this /// is repeatedly pinged). /// /// diff --git a/Source/EasyNetQ.Management.Client/ManagementClient.cs b/Source/EasyNetQ.Management.Client/ManagementClient.cs index 7c43d9dc..20f836f8 100644 --- a/Source/EasyNetQ.Management.Client/ManagementClient.cs +++ b/Source/EasyNetQ.Management.Client/ManagementClient.cs @@ -323,6 +323,21 @@ public Task> GetQueuesWithoutStatsAsync(Cancell return GetAsync>(Queues, GetQueuesWithoutStatsQueryParameters, cancellationToken); } + public Task> GetQueuesWithoutStatsByPageAsync(PageCriteria pageCriteria, CancellationToken cancellationToken = default) + { + return GetAsync>(Queues, pageCriteria.ToQueryParameters(GetQueuesWithoutStatsQueryParameters), cancellationToken); + } + + public Task> GetQueuesWithoutStatsAsync(string vhostName, CancellationToken cancellationToken = default) + { + return GetAsync>(Queues / vhostName, GetQueuesWithoutStatsQueryParameters, cancellationToken); + } + + public Task> GetQueuesWithoutStatsByPageAsync(string vhostName, PageCriteria pageCriteria, CancellationToken cancellationToken = default) + { + return GetAsync>(Queues / vhostName, pageCriteria.ToQueryParameters(GetQueuesWithoutStatsQueryParameters), cancellationToken); + } + public Task CreateQueueAsync( string vhostName, QueueInfo queueInfo, diff --git a/Source/EasyNetQ.Management.Client/Model/Listener.cs b/Source/EasyNetQ.Management.Client/Model/Listener.cs index 9cfba744..0cee75f2 100755 --- a/Source/EasyNetQ.Management.Client/Model/Listener.cs +++ b/Source/EasyNetQ.Management.Client/Model/Listener.cs @@ -1,8 +1,26 @@ +using EasyNetQ.Management.Client.Serialization; +using System.Text.Json; +using System.Text.Json.Serialization; + namespace EasyNetQ.Management.Client.Model; public record Listener( string Node, string Protocol, string IpAddress, - int Port -); + int Port, + [property: JsonConverter(typeof(EmptyArrayAsDefaultConverter))] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + SocketOpts? SocketOpts = null +) +{ + [JsonExtensionData()] + public IDictionary? JsonExtensionData { get; set; } + + [JsonIgnore()] + public IReadOnlyDictionary? ExtensionData + { + get { return JsonExtensionDataExtensions.ToExtensionData(JsonExtensionData); } + set { JsonExtensionData = JsonExtensionDataExtensions.ToJsonExtensionData(value); } + } +}; diff --git a/Source/EasyNetQ.Management.Client/Model/Overview.cs b/Source/EasyNetQ.Management.Client/Model/Overview.cs index 2893245a..13639860 100755 --- a/Source/EasyNetQ.Management.Client/Model/Overview.cs +++ b/Source/EasyNetQ.Management.Client/Model/Overview.cs @@ -1,4 +1,8 @@ -namespace EasyNetQ.Management.Client.Model; +using EasyNetQ.Management.Client.Serialization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace EasyNetQ.Management.Client.Model; public record Overview( string ManagementVersion, @@ -11,7 +15,18 @@ public record Overview( string Node, IReadOnlyList Listeners, IReadOnlyList Contexts -); +) +{ + [JsonExtensionData()] + public IDictionary? JsonExtensionData { get; set; } + + [JsonIgnore()] + public IReadOnlyDictionary? ExtensionData + { + get { return JsonExtensionDataExtensions.ToExtensionData(JsonExtensionData); } + set { JsonExtensionData = JsonExtensionDataExtensions.ToJsonExtensionData(value); } + } +}; public record ObjectTotals( int Consumers, diff --git a/Source/EasyNetQ.Management.Client/Model/PageCriteria.cs b/Source/EasyNetQ.Management.Client/Model/PageCriteria.cs index 4758bdcf..724e5f1d 100644 --- a/Source/EasyNetQ.Management.Client/Model/PageCriteria.cs +++ b/Source/EasyNetQ.Management.Client/Model/PageCriteria.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; + namespace EasyNetQ.Management.Client.Model; public record PageCriteria(int Page, int PageSize, string? Name = null, bool UseRegex = false) @@ -13,4 +15,14 @@ public IReadOnlyDictionary ToQueryParameters() { "pagination", "true" } }; } + + public IReadOnlyDictionary ToQueryParameters(IReadOnlyDictionary queryParameters) + { + var result = ToQueryParameters() as Dictionary; + foreach (var queryParameter in queryParameters) + { + result!.Add(queryParameter.Key, queryParameter.Value); + } + return result!; + } } diff --git a/Source/EasyNetQ.Management.Client/Model/ParameterShovelValue.cs b/Source/EasyNetQ.Management.Client/Model/ParameterShovelValue.cs index c9c4f924..c15f0f6f 100644 --- a/Source/EasyNetQ.Management.Client/Model/ParameterShovelValue.cs +++ b/Source/EasyNetQ.Management.Client/Model/ParameterShovelValue.cs @@ -1,4 +1,6 @@ -using System.Text.Json.Serialization; +using EasyNetQ.Management.Client.Serialization; +using System.Text.Json; +using System.Text.Json.Serialization; namespace EasyNetQ.Management.Client.Model; @@ -6,28 +8,74 @@ namespace EasyNetQ.Management.Client.Model; /// About shovel parameters: https://www.rabbitmq.com/shovel-dynamic.html /// public record ParameterShovelValue( - [property: JsonPropertyName("src-protocol")] - string SrcProtocol, [property: JsonPropertyName("src-uri")] string SrcUri, + [property: JsonPropertyName("dest-uri")] + string DestUri, + + [property: JsonPropertyName("src-protocol")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? SrcProtocol = null, // Either amqp091 or amqp10. If omitted it will default to amqp091. + [property: JsonPropertyName("src-queue")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? SrcQueue = null, + [property: JsonPropertyName("src-queue-args")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [property: JsonConverter(typeof(StringObjectReadOnlyDictionaryConverter))] + IReadOnlyDictionary? SrcQueueArguments = null, [property: JsonPropertyName("src-exchange")] - string? SrcExchange, + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? SrcExchange = null, [property: JsonPropertyName("src-exchange-key")] - string? SrcExchangeKey, - [property: JsonPropertyName("src-queue")] - string? SrcQueue, + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? SrcExchangeKey = null, + [property: JsonPropertyName("src-delete-after")] - string SrcDeleteAfter, + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? SrcDeleteAfter = null, + [property: JsonPropertyName("src-prefetch-count")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + int? SrcPrefetchCount = null, + [property: JsonPropertyName("dest-protocol")] - string DestProtocol, - [property: JsonPropertyName("dest-uri")] - string DestUri, - [property: JsonPropertyName("dest-exchange")] - string? DestExchange, + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? DestProtocol = null, // Either amqp091 or amqp10. If omitted it will default to amqp091. [property: JsonPropertyName("dest-queue")] - string? DestQueue, + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? DestQueue = null, + [property: JsonPropertyName("dest-queue-args")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [property: JsonConverter(typeof(StringObjectReadOnlyDictionaryConverter))] + IReadOnlyDictionary? DestQueueArguments = null, + [property: JsonPropertyName("dest-exchange")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? DestExchange = null, + [property: JsonPropertyName("dest-exchange-key")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? DestExchangeKey = null, + + [property: JsonPropertyName("dest-add-forward-headers")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + bool? DestAddForwardHeaders = null, + [property: JsonPropertyName("dest-add-timestamp-header")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + bool? DestAddTimestampHeader = null, + [property: JsonPropertyName("ack-mode")] - string AckMode, - [property: JsonPropertyName("add-forward-headers")] - bool AddForwardHeaders -); + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? AckMode = null, + [property: JsonPropertyName("reconnect-delay")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + int? ReconnectDelay = null +) +{ + [JsonExtensionData()] + public IDictionary? JsonExtensionData { get; set; } + + [JsonIgnore()] + public IReadOnlyDictionary? ExtensionData + { + get { return JsonExtensionDataExtensions.ToExtensionData(JsonExtensionData); } + set { JsonExtensionData = JsonExtensionDataExtensions.ToJsonExtensionData(value); } + } +}; diff --git a/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs b/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs index 52c7d51e..fb0a62fa 100644 --- a/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs +++ b/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs @@ -1,4 +1,5 @@ using EasyNetQ.Management.Client.Serialization; +using System.Text.Json; using System.Text.Json.Serialization; namespace EasyNetQ.Management.Client.Model; @@ -70,5 +71,12 @@ public record PolicyDefinition ) { [JsonExtensionData()] - public Dictionary? ExtensionData { get; set; } + public IDictionary? JsonExtensionData { get; set; } + + [JsonIgnore()] + public IReadOnlyDictionary? ExtensionData + { + get { return JsonExtensionDataExtensions.ToExtensionData(JsonExtensionData); } + set { JsonExtensionData = JsonExtensionDataExtensions.ToJsonExtensionData(value); } + } }; diff --git a/Source/EasyNetQ.Management.Client/Model/Queue.cs b/Source/EasyNetQ.Management.Client/Model/Queue.cs index cd5240f5..b7f6d672 100755 --- a/Source/EasyNetQ.Management.Client/Model/Queue.cs +++ b/Source/EasyNetQ.Management.Client/Model/Queue.cs @@ -1,3 +1,5 @@ +using EasyNetQ.Management.Client.Serialization; +using System.Text.Json; using System.Text.Json.Serialization; namespace EasyNetQ.Management.Client.Model; @@ -35,5 +37,12 @@ public record Queue( ) : QueueWithoutStats(Name, Vhost, Type, Node, State, Arguments, Durable, Exclusive, AutoDelete, MessagesReady, MessagesUnacknowledged, Messages) { [JsonExtensionData()] - public Dictionary? ExtensionData { get; set; } + public IDictionary? JsonExtensionData { get; set; } + + [JsonIgnore()] + public IReadOnlyDictionary? ExtensionData + { + get { return JsonExtensionDataExtensions.ToExtensionData(JsonExtensionData); } + set { JsonExtensionData = JsonExtensionDataExtensions.ToJsonExtensionData(value); } + } }; diff --git a/Source/EasyNetQ.Management.Client/Model/SocketOpts.cs b/Source/EasyNetQ.Management.Client/Model/SocketOpts.cs new file mode 100644 index 00000000..4c5d5fed --- /dev/null +++ b/Source/EasyNetQ.Management.Client/Model/SocketOpts.cs @@ -0,0 +1,25 @@ +using EasyNetQ.Management.Client.Serialization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace EasyNetQ.Management.Client.Model; + +public record SocketOpts( + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + int? Backlog = null, + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + bool? Nodelay = null, + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + bool? ExitOnClose = null +) +{ + [JsonExtensionData()] + public IDictionary? JsonExtensionData { get; set; } + + [JsonIgnore()] + public IReadOnlyDictionary? ExtensionData + { + get { return JsonExtensionDataExtensions.ToExtensionData(JsonExtensionData); } + set { JsonExtensionData = JsonExtensionDataExtensions.ToJsonExtensionData(value); } + } +}; diff --git a/Source/EasyNetQ.Management.Client/Serialization/JsonExtensionDataExtensions.cs b/Source/EasyNetQ.Management.Client/Serialization/JsonExtensionDataExtensions.cs new file mode 100644 index 00000000..6721a226 --- /dev/null +++ b/Source/EasyNetQ.Management.Client/Serialization/JsonExtensionDataExtensions.cs @@ -0,0 +1,46 @@ +using System.Text.Json; + +namespace EasyNetQ.Management.Client.Serialization; + +public static class JsonExtensionDataExtensions +{ + public static IReadOnlyDictionary? ToExtensionData(IDictionary? jsonExtensionData) + { + Dictionary? dictionary; + if (jsonExtensionData == null) + { + dictionary = null; + } + else + { + dictionary = new Dictionary(); + foreach (var property in jsonExtensionData) + { + dictionary.Add(property.Key, property.Value.GetObjectValue()); + } + } + return dictionary; + } + public static IDictionary? ToJsonExtensionData(IReadOnlyDictionary? extensionData) + { + IDictionary? dictionary; + if (extensionData == null) + { + dictionary = null; + } + else + { + dictionary = new Dictionary(); + foreach (var property in extensionData) + { +#if NET6_0_OR_GREATER + dictionary.Add(property.Key, JsonSerializer.SerializeToElement(property.Value)); +#else + var bytes = JsonSerializer.SerializeToUtf8Bytes(property.Value); + dictionary.Add(property.Key, JsonDocument.Parse(bytes).RootElement.Clone()); +#endif + } + } + return dictionary; + } +} From d5278f64c0d6bd164da12c227cde9d4ec474e78b Mon Sep 17 00:00:00 2001 From: inikulshin Date: Thu, 21 Dec 2023 14:49:55 +0200 Subject: [PATCH 2/3] Fix --- .../ManagementClientTests.cs | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs b/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs index 17742315..d2117c88 100644 --- a/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs +++ b/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs @@ -1252,6 +1252,26 @@ public async Task Should_get_queues_by_vhost() (await fixture.ManagementClient.GetQueuesAsync(vhost)).Should().NotBeNullOrEmpty(); } + [Fact] + public async Task Should_get_queues_with_pagination_by_vhost() + { + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + vhost.Name.Should().Be(TestVHost); + + foreach (var queue in await fixture.ManagementClient.GetQueuesAsync(TestVHost)) + await fixture.ManagementClient.DeleteQueueAsync(queue); + + await CreateTestQueueInVhost($"{TestVHost}_{TestQueue}_1", vhost); + await CreateTestQueueInVhost($"{TestVHost}_{TestQueue}_2", vhost); + + var firstPage = await fixture.ManagementClient.GetQueuesByPageAsync(vhost, new PageCriteria(1, 1)); + firstPage.Items.Count.Should().Be(1); + + var secondPage = await fixture.ManagementClient.GetQueuesByPageAsync(vhost, new PageCriteria(2, 1)); + secondPage.Items.Count.Should().Be(1); + } + [Fact] public async Task Should_get_queues_without_stats() { @@ -1284,7 +1304,27 @@ public async Task Should_get_queues_without_stats_by_vhost() vhost.Name.Should().Be(TestVHost); await CreateTestQueueInVhost($"{TestVHost}_{TestQueue}", vhost); - (await fixture.ManagementClient.GetQueuesWithoutStatsAsync(vhost)).Should().NotBeNullOrEmpty(); + (await fixture.ManagementClient.GetQueuesWithoutStatsAsync(vhost.Name)).Should().NotBeNullOrEmpty(); + } + + [Fact] + public async Task Should_get_queues_without_stats_with_pagination_by_vhost() + { + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + vhost.Name.Should().Be(TestVHost); + + foreach (var queue in await fixture.ManagementClient.GetQueuesAsync(TestVHost)) + await fixture.ManagementClient.DeleteQueueAsync(queue); + + await CreateTestQueueInVhost($"{TestVHost}_{TestQueue}_1", vhost); + await CreateTestQueueInVhost($"{TestVHost}_{TestQueue}_2", vhost); + + var firstPage = await fixture.ManagementClient.GetQueuesWithoutStatsByPageAsync(vhost.Name, new PageCriteria(1, 1)); + firstPage.Items.Count.Should().Be(1); + + var secondPage = await fixture.ManagementClient.GetQueuesWithoutStatsByPageAsync(vhost.Name, new PageCriteria(2, 1)); + secondPage.Items.Count.Should().Be(1); } [Fact] From 2504a3a7c813d9e7d043b51d13b25c958732a298 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Thu, 21 Dec 2023 19:51:26 +0200 Subject: [PATCH 3/3] Fixes --- .github/workflows/ci.yml | 2 +- .../EasyNetQ.Management.Client.approved.txt | 110 ++++++++++++++++-- .../Model/SocketOpts.cs | 50 ++++---- .../JsonExtensionDataExtensions.cs | 92 +++++++-------- 4 files changed, 171 insertions(+), 83 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 62552d20..1f558bf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,7 +49,7 @@ jobs: strategy: max-parallel: 3 matrix: - rabbitmq: ['3.10', '3.11'] + rabbitmq: ['3.10', '3.11', '3.12'] fail-fast: true steps: - name: Checkout diff --git a/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt b/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt index ddc6b260..a180273e 100644 --- a/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt +++ b/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt @@ -15,7 +15,7 @@ namespace EasyNetQ.Management.Client System.Threading.Tasks.Task CreateUserAsync(EasyNetQ.Management.Client.Model.UserInfo userInfo, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task CreateVhostAsync(string vhostName, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task DeleteExchangeAsync(string vhostName, string exchangeName, System.Threading.CancellationToken cancellationToken = default); - System.Threading.Tasks.Task DeleteExchangeBindingAsync(string vhostName, string fromExchangeName, string sourceExchangeName, string propertiesKey, System.Threading.CancellationToken cancellationToken = default); + System.Threading.Tasks.Task DeleteExchangeBindingAsync(string vhostName, string fromExchangeName, string toExchangeName, string propertiesKey, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task DeleteParameterAsync(string componentName, string vhostName, string name, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task DeletePermissionAsync(string vhostName, string userName, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task DeletePolicyAsync(string vhostName, string policyName, System.Threading.CancellationToken cancellationToken = default); @@ -60,6 +60,9 @@ namespace EasyNetQ.Management.Client System.Threading.Tasks.Task> GetQueuesByPageAsync(EasyNetQ.Management.Client.Model.PageCriteria pageCriteria, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task> GetQueuesByPageAsync(string vhostName, EasyNetQ.Management.Client.Model.PageCriteria pageCriteria, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task> GetQueuesWithoutStatsAsync(System.Threading.CancellationToken cancellationToken = default); + System.Threading.Tasks.Task> GetQueuesWithoutStatsAsync(string vhostName, System.Threading.CancellationToken cancellationToken = default); + System.Threading.Tasks.Task> GetQueuesWithoutStatsByPageAsync(EasyNetQ.Management.Client.Model.PageCriteria pageCriteria, System.Threading.CancellationToken cancellationToken = default); + System.Threading.Tasks.Task> GetQueuesWithoutStatsByPageAsync(string vhostName, EasyNetQ.Management.Client.Model.PageCriteria pageCriteria, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task> GetTopicPermissionsAsync(System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task GetUserAsync(string userName, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task> GetUsersAsync(System.Threading.CancellationToken cancellationToken = default); @@ -139,6 +142,9 @@ namespace EasyNetQ.Management.Client public System.Threading.Tasks.Task> GetQueuesByPageAsync(EasyNetQ.Management.Client.Model.PageCriteria pageCriteria, System.Threading.CancellationToken cancellationToken = default) { } public System.Threading.Tasks.Task> GetQueuesByPageAsync(string vhostName, EasyNetQ.Management.Client.Model.PageCriteria pageCriteria, System.Threading.CancellationToken cancellationToken = default) { } public System.Threading.Tasks.Task> GetQueuesWithoutStatsAsync(System.Threading.CancellationToken cancellationToken = default) { } + public System.Threading.Tasks.Task> GetQueuesWithoutStatsAsync(string vhostName, System.Threading.CancellationToken cancellationToken = default) { } + public System.Threading.Tasks.Task> GetQueuesWithoutStatsByPageAsync(EasyNetQ.Management.Client.Model.PageCriteria pageCriteria, System.Threading.CancellationToken cancellationToken = default) { } + public System.Threading.Tasks.Task> GetQueuesWithoutStatsByPageAsync(string vhostName, EasyNetQ.Management.Client.Model.PageCriteria pageCriteria, System.Threading.CancellationToken cancellationToken = default) { } public System.Threading.Tasks.Task> GetTopicPermissionsAsync(System.Threading.CancellationToken cancellationToken = default) { } public System.Threading.Tasks.Task GetUserAsync(string userName, System.Threading.CancellationToken cancellationToken = default) { } public System.Threading.Tasks.Task> GetUsersAsync(System.Threading.CancellationToken cancellationToken = default) { } @@ -676,11 +682,18 @@ namespace EasyNetQ.Management.Client.Model } public class Listener : System.IEquatable { - public Listener(string Node, string Protocol, string IpAddress, int Port) { } + public Listener(string Node, string Protocol, string IpAddress, int Port, EasyNetQ.Management.Client.Model.SocketOpts? SocketOpts = null) { } + [System.Text.Json.Serialization.JsonIgnore] + public System.Collections.Generic.IReadOnlyDictionary? ExtensionData { get; set; } + [System.Text.Json.Serialization.JsonExtensionData] + public System.Collections.Generic.IDictionary? JsonExtensionData { get; set; } public string IpAddress { get; init; } public string Node { get; init; } public int Port { get; init; } public string Protocol { get; init; } + [System.Text.Json.Serialization.JsonConverter(typeof(EasyNetQ.Management.Client.Serialization.EmptyArrayAsDefaultConverter))] + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] + public EasyNetQ.Management.Client.Model.SocketOpts? SocketOpts { get; init; } } public class Message : System.IEquatable { @@ -847,6 +860,10 @@ namespace EasyNetQ.Management.Client.Model public class Overview : System.IEquatable { public Overview(string ManagementVersion, System.Collections.Generic.IReadOnlyList ExchangeTypes, string RabbitmqVersion, string ErlangVersion, EasyNetQ.Management.Client.Model.MessageStats MessageStats, EasyNetQ.Management.Client.Model.QueueTotals QueueTotals, EasyNetQ.Management.Client.Model.ObjectTotals ObjectTotals, string Node, System.Collections.Generic.IReadOnlyList Listeners, System.Collections.Generic.IReadOnlyList Contexts) { } + [System.Text.Json.Serialization.JsonIgnore] + public System.Collections.Generic.IReadOnlyDictionary? ExtensionData { get; set; } + [System.Text.Json.Serialization.JsonExtensionData] + public System.Collections.Generic.IDictionary? JsonExtensionData { get; set; } public System.Collections.Generic.IReadOnlyList Contexts { get; init; } public string ErlangVersion { get; init; } public System.Collections.Generic.IReadOnlyList ExchangeTypes { get; init; } @@ -866,6 +883,7 @@ namespace EasyNetQ.Management.Client.Model public int Page { get; init; } public bool UseRegex { get; init; } public System.Collections.Generic.IReadOnlyDictionary ToQueryParameters() { } + public System.Collections.Generic.IReadOnlyDictionary ToQueryParameters(System.Collections.Generic.IReadOnlyDictionary queryParameters) { } } public class PageResult : System.IEquatable> { @@ -895,27 +913,79 @@ namespace EasyNetQ.Management.Client.Model } public class ParameterShovelValue : System.IEquatable { - public ParameterShovelValue(string SrcProtocol, string SrcUri, string? SrcExchange, string? SrcExchangeKey, string? SrcQueue, string SrcDeleteAfter, string DestProtocol, string DestUri, string? DestExchange, string? DestQueue, string AckMode, bool AddForwardHeaders) { } + public ParameterShovelValue( + string SrcUri, + string DestUri, + string? SrcProtocol = null, + string? SrcQueue = null, + System.Collections.Generic.IReadOnlyDictionary? SrcQueueArguments = null, + string? SrcExchange = null, + string? SrcExchangeKey = null, + string? SrcDeleteAfter = null, + int? SrcPrefetchCount = default, + string? DestProtocol = null, + string? DestQueue = null, + System.Collections.Generic.IReadOnlyDictionary? DestQueueArguments = null, + string? DestExchange = null, + string? DestExchangeKey = null, + bool? DestAddForwardHeaders = default, + bool? DestAddTimestampHeader = default, + string? AckMode = null, + int? ReconnectDelay = default) { } + [System.Text.Json.Serialization.JsonIgnore] + public System.Collections.Generic.IReadOnlyDictionary? ExtensionData { get; set; } + [System.Text.Json.Serialization.JsonExtensionData] + public System.Collections.Generic.IDictionary? JsonExtensionData { get; set; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] [System.Text.Json.Serialization.JsonPropertyName("ack-mode")] - public string AckMode { get; init; } - [System.Text.Json.Serialization.JsonPropertyName("add-forward-headers")] - public bool AddForwardHeaders { get; init; } + public string? AckMode { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] + [System.Text.Json.Serialization.JsonPropertyName("dest-add-forward-headers")] + public bool? DestAddForwardHeaders { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] + [System.Text.Json.Serialization.JsonPropertyName("dest-add-timestamp-header")] + public bool? DestAddTimestampHeader { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] + [System.Text.Json.Serialization.JsonPropertyName("dest-exchange-key")] + public string? DestExchangeKey { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] [System.Text.Json.Serialization.JsonPropertyName("dest-exchange")] public string? DestExchange { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] [System.Text.Json.Serialization.JsonPropertyName("dest-protocol")] - public string DestProtocol { get; init; } + public string? DestProtocol { get; init; } + [System.Text.Json.Serialization.JsonConverter(typeof(EasyNetQ.Management.Client.Serialization.StringObjectReadOnlyDictionaryConverter?))] + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] + [System.Text.Json.Serialization.JsonPropertyName("dest-queue-args")] + public System.Collections.Generic.IReadOnlyDictionary? DestQueueArguments { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] [System.Text.Json.Serialization.JsonPropertyName("dest-queue")] public string? DestQueue { get; init; } [System.Text.Json.Serialization.JsonPropertyName("dest-uri")] public string DestUri { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] + [System.Text.Json.Serialization.JsonPropertyName("reconnect-delay")] + public int? ReconnectDelay { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] [System.Text.Json.Serialization.JsonPropertyName("src-delete-after")] - public string SrcDeleteAfter { get; init; } + public string? SrcDeleteAfter { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] [System.Text.Json.Serialization.JsonPropertyName("src-exchange-key")] public string? SrcExchangeKey { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] [System.Text.Json.Serialization.JsonPropertyName("src-exchange")] public string? SrcExchange { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] + [System.Text.Json.Serialization.JsonPropertyName("src-prefetch-count")] + public int? SrcPrefetchCount { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] [System.Text.Json.Serialization.JsonPropertyName("src-protocol")] - public string SrcProtocol { get; init; } + public string? SrcProtocol { get; init; } + [System.Text.Json.Serialization.JsonConverter(typeof(EasyNetQ.Management.Client.Serialization.StringObjectReadOnlyDictionaryConverter?))] + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] + [System.Text.Json.Serialization.JsonPropertyName("src-queue-args")] + public System.Collections.Generic.IReadOnlyDictionary? SrcQueueArguments { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] [System.Text.Json.Serialization.JsonPropertyName("src-queue")] public string? SrcQueue { get; init; } [System.Text.Json.Serialization.JsonPropertyName("src-uri")] @@ -988,8 +1058,10 @@ namespace EasyNetQ.Management.Client.Model string? FederationUpstream = null, string? FederationUpstreamSet = null, string? QueueMode = null) { } + [System.Text.Json.Serialization.JsonIgnore] + public System.Collections.Generic.IReadOnlyDictionary? ExtensionData { get; set; } [System.Text.Json.Serialization.JsonExtensionData] - public System.Collections.Generic.Dictionary? ExtensionData { get; set; } + public System.Collections.Generic.IDictionary? JsonExtensionData { get; set; } [System.Text.Json.Serialization.JsonPropertyName("alternate-exchange")] public string? AlternateExchange { get; init; } [System.Text.Json.Serialization.JsonPropertyName("consumer-timeout")] @@ -1103,8 +1175,10 @@ namespace EasyNetQ.Management.Client.Model EasyNetQ.Management.Client.Model.LengthsDetails? MessagesReadyDetails, EasyNetQ.Management.Client.Model.LengthsDetails? MessagesUnacknowledgedDetails, EasyNetQ.Management.Client.Model.MessageStats? MessageStats) { } + [System.Text.Json.Serialization.JsonIgnore] + public System.Collections.Generic.IReadOnlyDictionary? ExtensionData { get; set; } [System.Text.Json.Serialization.JsonExtensionData] - public System.Collections.Generic.Dictionary? ExtensionData { get; set; } + public System.Collections.Generic.IDictionary? JsonExtensionData { get; set; } public long ActiveConsumers { get; init; } public EasyNetQ.Management.Client.Model.BackingQueueStatus? BackingQueueStatus { get; init; } public System.Collections.Generic.IReadOnlyList? ConsumerDetails { get; init; } @@ -1187,6 +1261,20 @@ namespace EasyNetQ.Management.Client.Model public int MsgRatesIncr { get; init; } public System.Collections.Generic.IReadOnlyDictionary ToQueryParameters() { } } + public class SocketOpts : System.IEquatable + { + public SocketOpts(int? Backlog = default, bool? Nodelay = default, bool? ExitOnClose = default) { } + [System.Text.Json.Serialization.JsonIgnore] + public System.Collections.Generic.IReadOnlyDictionary? ExtensionData { get; set; } + [System.Text.Json.Serialization.JsonExtensionData] + public System.Collections.Generic.IDictionary? JsonExtensionData { get; set; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] + public int? Backlog { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] + public bool? ExitOnClose { get; init; } + [System.Text.Json.Serialization.JsonIgnore(Condition=System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)] + public bool? Nodelay { get; init; } + } public class TopicPermission : System.IEquatable { public TopicPermission(string User, string Vhost, string Exchange, string Write, string Read) { } diff --git a/Source/EasyNetQ.Management.Client/Model/SocketOpts.cs b/Source/EasyNetQ.Management.Client/Model/SocketOpts.cs index 4c5d5fed..091be210 100644 --- a/Source/EasyNetQ.Management.Client/Model/SocketOpts.cs +++ b/Source/EasyNetQ.Management.Client/Model/SocketOpts.cs @@ -1,25 +1,25 @@ -using EasyNetQ.Management.Client.Serialization; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace EasyNetQ.Management.Client.Model; - -public record SocketOpts( - [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - int? Backlog = null, - [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - bool? Nodelay = null, - [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - bool? ExitOnClose = null -) -{ - [JsonExtensionData()] - public IDictionary? JsonExtensionData { get; set; } - - [JsonIgnore()] - public IReadOnlyDictionary? ExtensionData - { - get { return JsonExtensionDataExtensions.ToExtensionData(JsonExtensionData); } - set { JsonExtensionData = JsonExtensionDataExtensions.ToJsonExtensionData(value); } - } -}; +using EasyNetQ.Management.Client.Serialization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace EasyNetQ.Management.Client.Model; + +public record SocketOpts( + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + int? Backlog = null, + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + bool? Nodelay = null, + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + bool? ExitOnClose = null +) +{ + [JsonExtensionData()] + public IDictionary? JsonExtensionData { get; set; } + + [JsonIgnore()] + public IReadOnlyDictionary? ExtensionData + { + get { return JsonExtensionDataExtensions.ToExtensionData(JsonExtensionData); } + set { JsonExtensionData = JsonExtensionDataExtensions.ToJsonExtensionData(value); } + } +}; diff --git a/Source/EasyNetQ.Management.Client/Serialization/JsonExtensionDataExtensions.cs b/Source/EasyNetQ.Management.Client/Serialization/JsonExtensionDataExtensions.cs index 6721a226..6fb544fe 100644 --- a/Source/EasyNetQ.Management.Client/Serialization/JsonExtensionDataExtensions.cs +++ b/Source/EasyNetQ.Management.Client/Serialization/JsonExtensionDataExtensions.cs @@ -1,46 +1,46 @@ -using System.Text.Json; - -namespace EasyNetQ.Management.Client.Serialization; - -public static class JsonExtensionDataExtensions -{ - public static IReadOnlyDictionary? ToExtensionData(IDictionary? jsonExtensionData) - { - Dictionary? dictionary; - if (jsonExtensionData == null) - { - dictionary = null; - } - else - { - dictionary = new Dictionary(); - foreach (var property in jsonExtensionData) - { - dictionary.Add(property.Key, property.Value.GetObjectValue()); - } - } - return dictionary; - } - public static IDictionary? ToJsonExtensionData(IReadOnlyDictionary? extensionData) - { - IDictionary? dictionary; - if (extensionData == null) - { - dictionary = null; - } - else - { - dictionary = new Dictionary(); - foreach (var property in extensionData) - { -#if NET6_0_OR_GREATER - dictionary.Add(property.Key, JsonSerializer.SerializeToElement(property.Value)); -#else - var bytes = JsonSerializer.SerializeToUtf8Bytes(property.Value); - dictionary.Add(property.Key, JsonDocument.Parse(bytes).RootElement.Clone()); -#endif - } - } - return dictionary; - } -} +using System.Text.Json; + +namespace EasyNetQ.Management.Client.Serialization; + +internal static class JsonExtensionDataExtensions +{ + public static IReadOnlyDictionary? ToExtensionData(IDictionary? jsonExtensionData) + { + Dictionary? dictionary; + if (jsonExtensionData == null) + { + dictionary = null; + } + else + { + dictionary = new Dictionary(); + foreach (var property in jsonExtensionData) + { + dictionary.Add(property.Key, property.Value.GetObjectValue()); + } + } + return dictionary; + } + public static IDictionary? ToJsonExtensionData(IReadOnlyDictionary? extensionData) + { + IDictionary? dictionary; + if (extensionData == null) + { + dictionary = null; + } + else + { + dictionary = new Dictionary(); + foreach (var property in extensionData) + { +#if NET6_0_OR_GREATER + dictionary.Add(property.Key, JsonSerializer.SerializeToElement(property.Value)); +#else + var bytes = JsonSerializer.SerializeToUtf8Bytes(property.Value); + dictionary.Add(property.Key, JsonDocument.Parse(bytes).RootElement.Clone()); +#endif + } + } + return dictionary; + } +}