Skip to content

Commit d36a7b4

Browse files
committed
Use EasyNetQ.Management.Client
* Allow specifying `MaxFrameSize` for a connection. * Move HTTP API interaction to `EasyNetQ.Management.Client` * No need to start toxiproxy yet * Use `uint.MinValue` to mean `unlimited` for max frame size * Implement the Environment class to manage the connections (#36) * Implement the Environment Closes #35 --------- Signed-off-by: Gabriele Santomaggio <[email protected]> Use `EasyNetQ.Management.Client` * Allow specifying `MaxFrameSize` for a connection. * Move HTTP API interaction to `EasyNetQ.Management.Client` * No need to start toxiproxy yet * Use `uint.MinValue` to mean `unlimited` for max frame size * * Add to public API Continue migrating to EasyNetQ.Management.Client
1 parent 955c730 commit d36a7b4

File tree

12 files changed

+160
-96
lines changed

12 files changed

+160
-96
lines changed

.ci/ubuntu/gha-setup.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,18 @@ else
4646
readonly docker_pull_args=''
4747
fi
4848

49-
set -o nounset
50-
51-
declare -r rabbitmq_docker_name="$docker_name_prefix-rabbitmq"
52-
declare -r toxiproxy_docker_name="$docker_name_prefix-toxiproxy"
53-
5449
if [[ $1 == 'stop' ]]
5550
then
5651
docker stop "$rabbitmq_docker_name"
5752
docker stop "$toxiproxy_docker_name"
5853
exit 0
5954
fi
6055

56+
set -o nounset
57+
58+
declare -r rabbitmq_docker_name="$docker_name_prefix-rabbitmq"
59+
declare -r toxiproxy_docker_name="$docker_name_prefix-toxiproxy"
60+
6161
function start_toxiproxy
6262
{
6363
if [[ $run_toxiproxy == 'true' ]]

.github/workflows/build-test.yaml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,17 @@ jobs:
2626
run: dotnet format ${{ github.workspace }}/Build.csproj --no-restore --verify-no-changes
2727
- name: Start RabbitMQ
2828
id: start-rabbitmq
29-
run: ${{ github.workspace }}/.ci/ubuntu/gha-setup.sh toxiproxy
29+
# Note: not using toxiproxy yet
30+
# run: ${{ github.workspace }}/.ci/ubuntu/gha-setup.sh toxiproxy
31+
run: ${{ github.workspace }}/.ci/ubuntu/gha-setup.sh
3032
- name: Test
3133
run: dotnet test ${{ github.workspace }}/Build.csproj --no-restore --no-build --logger "console;verbosity=detailed" /p:AltCover=true /p:AltCoverStrongNameKey=${{github.workspace}}/rabbit.snk
3234
- name: Check for errors in RabbitMQ logs
3335
run: ${{ github.workspace}}/.ci/ubuntu/gha-log-check.sh
34-
- name: Maybe collect toxiproxy logs
35-
if: failure()
36-
run: docker logs rabbitmq-amqp-dotnet-client-toxiproxy > ${{ github.workspace }}/.ci/ubuntu/log/toxiproxy.log
36+
# Note: not using toxiproxy yet
37+
# - name: Maybe collect toxiproxy logs
38+
# if: failure()
39+
# run: docker logs rabbitmq-amqp-dotnet-client-toxiproxy > ${{ github.workspace }}/.ci/ubuntu/log/toxiproxy.log
3740
- name: Maybe upload RabbitMQ logs
3841
if: failure()
3942
uses: actions/upload-artifact@v4

RabbitMQ.AMQP.Client/IConnectionSettings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public interface IConnectionSettings : IEquatable<IConnectionSettings>
1515
string ConnectionName { get; }
1616
string Path { get; }
1717
bool UseSsl { get; }
18+
uint MaxFrameSize { get; }
1819
SaslMechanism SaslMechanism { get; }
1920
ITlsSettings? TlsSettings { get; }
2021

RabbitMQ.AMQP.Client/Impl/AmqpConnection.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,18 @@ private async Task EnsureConnection()
182182
var open = new Open
183183
{
184184
HostName = $"vhost:{_connectionSettings.VirtualHost}",
185-
Properties = new Fields() { [new Symbol("connection_name")] = _connectionSettings.ConnectionName, }
185+
Properties = new Fields()
186+
{
187+
[new Symbol("connection_name")] = _connectionSettings.ConnectionName,
188+
}
186189
};
187190

191+
if (_connectionSettings.MaxFrameSize > uint.MinValue)
192+
{
193+
// Note: when set here, there is no need to set cf.AMQP.MaxFrameSize
194+
open.MaxFrameSize = _connectionSettings.MaxFrameSize;
195+
}
196+
188197
void onOpened(Amqp.IConnection connection, Open open1)
189198
{
190199
Trace.WriteLine(TraceLevel.Verbose, $"Connection opened. Info: {ToString()}");

RabbitMQ.AMQP.Client/Impl/ConnectionSettings.cs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public class ConnectionSettingBuilder
1515
private string _scheme = "AMQP";
1616
private string _connectionName = "AMQP.NET";
1717
private string _virtualHost = "/";
18+
private uint _maxFrameSize = Consts.DefaultMaxFrameSize;
1819
private SaslMechanism _saslMechanism = Client.SaslMechanism.Plain;
1920
private IRecoveryConfiguration _recoveryConfiguration = Impl.RecoveryConfiguration.Create();
2021

@@ -69,6 +70,17 @@ public ConnectionSettingBuilder VirtualHost(string virtualHost)
6970
return this;
7071
}
7172

73+
public ConnectionSettingBuilder MaxFrameSize(uint maxFrameSize)
74+
{
75+
_maxFrameSize = maxFrameSize;
76+
if (_maxFrameSize != uint.MinValue && _maxFrameSize < 512)
77+
{
78+
throw new ArgumentOutOfRangeException(nameof(maxFrameSize),
79+
"maxFrameSize must be greater or equal to 512");
80+
}
81+
return this;
82+
}
83+
7284
public ConnectionSettingBuilder SaslMechanism(SaslMechanism saslMechanism)
7385
{
7486
_saslMechanism = saslMechanism;
@@ -89,9 +101,9 @@ public ConnectionSettingBuilder RecoveryConfiguration(IRecoveryConfiguration rec
89101

90102
public ConnectionSettings Build()
91103
{
92-
var c = new ConnectionSettings(_host, _port, _user,
104+
var c = new ConnectionSettings(_scheme, _host, _port, _user,
93105
_password, _virtualHost,
94-
_scheme, _connectionName, _saslMechanism)
106+
_connectionName, _saslMechanism, _maxFrameSize)
95107
{
96108
Recovery = (RecoveryConfiguration)_recoveryConfiguration
97109
};
@@ -106,8 +118,9 @@ public ConnectionSettings Build()
106118
public class ConnectionSettings : IConnectionSettings
107119
{
108120
private readonly Address _address;
109-
private readonly string _connectionName = "";
110121
private readonly string _virtualHost = "/";
122+
private readonly string _connectionName = "";
123+
private readonly uint _maxFrameSize = Consts.DefaultMaxFrameSize;
111124
private readonly ITlsSettings? _tlsSettings;
112125
private readonly SaslMechanism _saslMechanism = SaslMechanism.Plain;
113126

@@ -122,17 +135,27 @@ public ConnectionSettings(string address, ITlsSettings? tlsSettings = null)
122135
}
123136
}
124137

125-
public ConnectionSettings(string host, int port,
138+
public ConnectionSettings(string scheme, string host, int port,
126139
string? user, string? password,
127-
string virtualHost, string scheme, string connectionName,
128-
SaslMechanism saslMechanism, ITlsSettings? tlsSettings = null)
140+
string virtualHost, string connectionName,
141+
SaslMechanism saslMechanism,
142+
uint maxFrameSize = Consts.DefaultMaxFrameSize,
143+
ITlsSettings? tlsSettings = null)
129144
{
130145
_address = new Address(host: host, port: port,
131146
user: user, password: password,
132147
path: "/", scheme: scheme);
133148
_connectionName = connectionName;
134149
_virtualHost = virtualHost;
135150
_saslMechanism = saslMechanism;
151+
152+
_maxFrameSize = maxFrameSize;
153+
if (_maxFrameSize != uint.MinValue && _maxFrameSize < 512)
154+
{
155+
throw new ArgumentOutOfRangeException(nameof(maxFrameSize),
156+
"maxFrameSize must be greater or equal to 512");
157+
}
158+
136159
_tlsSettings = tlsSettings;
137160

138161
if (_address.UseSsl && _tlsSettings == null)
@@ -150,8 +173,8 @@ public ConnectionSettings(string host, int port,
150173
public string ConnectionName => _connectionName;
151174
public string Path => _address.Path;
152175
public bool UseSsl => _address.UseSsl;
176+
public uint MaxFrameSize => _maxFrameSize;
153177
public SaslMechanism SaslMechanism => _saslMechanism;
154-
155178
public ITlsSettings? TlsSettings => _tlsSettings;
156179
public IRecoveryConfiguration Recovery { get; init; } = RecoveryConfiguration.Create();
157180

RabbitMQ.AMQP.Client/Impl/Consts.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,8 @@ public class Consts
77
public const string Queues = "queues";
88
public const string Bindings = "bindings";
99

10+
/// <summary>
11+
/// <code>uint.MinValue</code> means "no limit"
12+
/// </summary>
13+
public const uint DefaultMaxFrameSize = uint.MinValue; // NOTE: Azure/amqpnetlite uses 256 * 1024
1014
}

RabbitMQ.AMQP.Client/PublicAPI.Unshipped.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#nullable enable
22
abstract RabbitMQ.AMQP.Client.Impl.AbstractLifeCycle.CloseAsync() -> System.Threading.Tasks.Task!
33
const RabbitMQ.AMQP.Client.Impl.Consts.Bindings = "bindings" -> string!
4+
const RabbitMQ.AMQP.Client.Impl.Consts.DefaultMaxFrameSize = 0 -> uint
45
const RabbitMQ.AMQP.Client.Impl.Consts.Exchanges = "exchanges" -> string!
56
const RabbitMQ.AMQP.Client.Impl.Consts.Key = "key" -> string!
67
const RabbitMQ.AMQP.Client.Impl.Consts.Queues = "queues" -> string!
@@ -80,6 +81,7 @@ RabbitMQ.AMQP.Client.IConnection.PublisherBuilder() -> RabbitMQ.AMQP.Client.IPub
8081
RabbitMQ.AMQP.Client.IConnectionSettings
8182
RabbitMQ.AMQP.Client.IConnectionSettings.ConnectionName.get -> string!
8283
RabbitMQ.AMQP.Client.IConnectionSettings.Host.get -> string!
84+
RabbitMQ.AMQP.Client.IConnectionSettings.MaxFrameSize.get -> uint
8385
RabbitMQ.AMQP.Client.IConnectionSettings.Password.get -> string?
8486
RabbitMQ.AMQP.Client.IConnectionSettings.Path.get -> string!
8587
RabbitMQ.AMQP.Client.IConnectionSettings.Port.get -> int
@@ -328,6 +330,7 @@ RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder
328330
RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder.Build() -> RabbitMQ.AMQP.Client.Impl.ConnectionSettings!
329331
RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder.ConnectionName(string! connectionName) -> RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder!
330332
RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder.Host(string! host) -> RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder!
333+
RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder.MaxFrameSize(uint maxFrameSize) -> RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder!
331334
RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder.Password(string! password) -> RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder!
332335
RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder.Port(int port) -> RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder!
333336
RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder.RecoveryConfiguration(RabbitMQ.AMQP.Client.IRecoveryConfiguration! recoveryConfiguration) -> RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder!
@@ -338,10 +341,11 @@ RabbitMQ.AMQP.Client.Impl.ConnectionSettingBuilder.VirtualHost(string! virtualHo
338341
RabbitMQ.AMQP.Client.Impl.ConnectionSettings
339342
RabbitMQ.AMQP.Client.Impl.ConnectionSettings.ConnectionName.get -> string!
340343
RabbitMQ.AMQP.Client.Impl.ConnectionSettings.ConnectionSettings(string! address, RabbitMQ.AMQP.Client.ITlsSettings? tlsSettings = null) -> void
341-
RabbitMQ.AMQP.Client.Impl.ConnectionSettings.ConnectionSettings(string! host, int port, string? user, string? password, string! virtualHost, string! scheme, string! connectionName, RabbitMQ.AMQP.Client.SaslMechanism! saslMechanism, RabbitMQ.AMQP.Client.ITlsSettings? tlsSettings = null) -> void
344+
RabbitMQ.AMQP.Client.Impl.ConnectionSettings.ConnectionSettings(string! scheme, string! host, int port, string? user, string? password, string! virtualHost, string! connectionName, RabbitMQ.AMQP.Client.SaslMechanism! saslMechanism, uint maxFrameSize = 0, RabbitMQ.AMQP.Client.ITlsSettings? tlsSettings = null) -> void
342345
RabbitMQ.AMQP.Client.Impl.ConnectionSettings.Equals(RabbitMQ.AMQP.Client.IConnectionSettings? other) -> bool
343346
RabbitMQ.AMQP.Client.Impl.ConnectionSettings.Equals(RabbitMQ.AMQP.Client.Impl.ConnectionSettings! other) -> bool
344347
RabbitMQ.AMQP.Client.Impl.ConnectionSettings.Host.get -> string!
348+
RabbitMQ.AMQP.Client.Impl.ConnectionSettings.MaxFrameSize.get -> uint
345349
RabbitMQ.AMQP.Client.Impl.ConnectionSettings.Password.get -> string?
346350
RabbitMQ.AMQP.Client.Impl.ConnectionSettings.Path.get -> string!
347351
RabbitMQ.AMQP.Client.Impl.ConnectionSettings.Port.get -> int

Tests/BindingsTests.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ await management.Binding().SourceExchange(sourceExchange).DestinationQueue(queue
3838
await management.QueueDeletion().Delete(queueDestination);
3939
await connection.CloseAsync();
4040
SystemUtils.WaitUntil(() => !SystemUtils.ExchangeExists(sourceExchange));
41-
SystemUtils.WaitUntil(() => !SystemUtils.QueueExists(queueDestination));
41+
42+
await SystemUtils.WaitUntilQueueDeletedAsync(queueDestination);
4243
}
4344

4445
[Fact]
@@ -75,8 +76,9 @@ await management.Binding().SourceExchange("exchange_bind_two_times").Destination
7576

7677
await management.QueueDeletion().Delete("queue_bind_two_times");
7778
await connection.CloseAsync();
79+
7880
SystemUtils.WaitUntil(() => !SystemUtils.ExchangeExists("exchange_bind_two_times"));
79-
SystemUtils.WaitUntil(() => !SystemUtils.QueueExists("queue_bind_two_times"));
81+
await SystemUtils.WaitUntilQueueDeletedAsync("queue_bind_two_times");
8082
}
8183

8284

@@ -154,8 +156,9 @@ await management.Binding().SourceExchange("exchange_bindings_with_arguments")
154156
await management.ExchangeDeletion().Delete("exchange_bindings_with_arguments");
155157
await management.QueueDeletion().Delete("queue_bindings_with_arguments");
156158
await connection.CloseAsync();
159+
157160
SystemUtils.WaitUntil(() => !SystemUtils.ExchangeExists("exchange_bindings_with_arguments"));
158-
SystemUtils.WaitUntil(() => !SystemUtils.QueueExists("queue_bindings_with_arguments"));
161+
await SystemUtils.WaitUntilQueueDeletedAsync("queue_bindings_with_arguments");
159162
}
160163

161164
// TODO: test with multi-bindings with parameters with list as value

Tests/ConnectionRecoveryTests.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,13 @@ public async Task RecoveryTopologyShouldRecoverTheTempQueues()
232232
await SystemUtils.WaitUntilConnectionIsKilled(connectionName);
233233
await completion.Task.WaitAsync(TimeSpan.FromSeconds(10));
234234
SystemUtils.WaitUntil(() => recoveryEvents == 2);
235-
SystemUtils.WaitUntil(() => SystemUtils.QueueExists(queueName));
235+
236+
await SystemUtils.WaitUntilQueueExistsAsync(queueName);
236237

237238
await connection.CloseAsync();
238-
SystemUtils.WaitUntil(() => !SystemUtils.QueueExists(queueName));
239+
240+
await SystemUtils.WaitUntilQueueDeletedAsync(queueName);
241+
239242
TestOutputHelper.WriteLine(
240243
$"Recover: Queue count: {management.TopologyListener().QueueCount()} , events: {recoveryEvents}");
241244
Assert.Equal(0, management.TopologyListener().QueueCount());
@@ -277,7 +280,9 @@ public async Task RecoveryTopologyShouldNotRecoverTheTempQueues()
277280

278281
await SystemUtils.WaitUntilConnectionIsKilled(connectionName);
279282
await completion.Task.WaitAsync(TimeSpan.FromSeconds(10));
280-
SystemUtils.WaitUntil(() => SystemUtils.QueueExists(queueName) == false);
283+
284+
await SystemUtils.WaitUntilQueueDeletedAsync(queueName);
285+
281286
await connection.CloseAsync();
282287
Assert.Equal(0, management.TopologyListener().QueueCount());
283288
TestOutputHelper.WriteLine(

Tests/ConnectionTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ public class ConnectionTests(ITestOutputHelper output)
1313
[Fact]
1414
public void ValidateAddress()
1515
{
16-
ConnectionSettings connectionSettings = new("localhost", 5672, "guest-user",
17-
"guest-password", "vhost_1", "amqp1", "connection_name", SaslMechanism.External);
16+
ConnectionSettings connectionSettings = new("amqp1", "localhost", 5672, "guest-user",
17+
"guest-password", "vhost_1", "connection_name", SaslMechanism.External);
1818
Assert.Equal("localhost", connectionSettings.Host);
1919
Assert.Equal(5672, connectionSettings.Port);
2020
Assert.Equal("guest-user", connectionSettings.User);
@@ -23,13 +23,13 @@ public void ValidateAddress()
2323
Assert.Equal("amqp1", connectionSettings.Scheme);
2424
Assert.Equal(SaslMechanism.External, connectionSettings.SaslMechanism);
2525

26-
ConnectionSettings second = new("localhost", 5672, "guest-user",
27-
"guest-password", "path/", "amqp1", "connection_name", SaslMechanism.External);
26+
ConnectionSettings second = new("amqp1", "localhost", 5672, "guest-user",
27+
"guest-password", "path/", "connection_name", SaslMechanism.External);
2828

2929
Assert.Equal(connectionSettings, second);
3030

31-
ConnectionSettings third = new("localhost", 5672, "guest-user",
32-
"guest-password", "path/", "amqp2", "connection_name", SaslMechanism.Plain);
31+
ConnectionSettings third = new("amqp2", "localhost", 5672, "guest-user",
32+
"guest-password", "path/", "connection_name", SaslMechanism.Plain);
3333

3434
Assert.NotEqual(connectionSettings, third);
3535
}

0 commit comments

Comments
 (0)