Skip to content

Commit d5c971f

Browse files
committed
* Use ConnectionSettingsViaUris when specifying a set of Uri instances to which to connect.
1 parent ebce43d commit d5c971f

File tree

3 files changed

+107
-111
lines changed

3 files changed

+107
-111
lines changed

RabbitMQ.AMQP.Client/ConnectionSettings.cs

Lines changed: 98 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public ConnectionSettings Build()
159159
}
160160
else if (_uris is not null)
161161
{
162-
return new ConnectionSettings(_uris,
162+
return new ConnectionSettingsViaUris(_uris,
163163
_uriSelector,
164164
_containerId, _saslMechanism,
165165
_recoveryConfiguration,
@@ -191,11 +191,8 @@ private void ValidateUris()
191191
// </summary>
192192
public class ConnectionSettings : IEquatable<ConnectionSettings>
193193
{
194-
private readonly Address _address = new("amqp://localhost:5672");
195-
private readonly List<Uri>? _uris;
196-
private readonly Dictionary<Uri, Address>? _uriToAddress;
197-
private readonly IUriSelector _uriSelector = new RandomUriSelector();
198-
private readonly string _virtualHost = Consts.DefaultVirtualHost;
194+
protected Address _address = new("amqp://localhost:5672");
195+
protected string _virtualHost = Consts.DefaultVirtualHost;
199196
private readonly string _containerId = string.Empty;
200197
private readonly uint _maxFrameSize = Consts.DefaultMaxFrameSize;
201198
private readonly TlsSettings? _tlsSettings;
@@ -227,66 +224,6 @@ public ConnectionSettings(Uri uri,
227224
}
228225
}
229226

230-
public ConnectionSettings(IEnumerable<Uri> uris,
231-
IUriSelector? uriSelector = null,
232-
string? containerId = null,
233-
SaslMechanism? saslMechanism = null,
234-
IRecoveryConfiguration? recoveryConfiguration = null,
235-
uint? maxFrameSize = null,
236-
TlsSettings? tlsSettings = null)
237-
: this(containerId, saslMechanism, recoveryConfiguration, maxFrameSize, tlsSettings)
238-
{
239-
_uris = uris.ToList();
240-
241-
if (uriSelector is not null)
242-
{
243-
_uriSelector = uriSelector;
244-
}
245-
246-
_uriToAddress = new(_uris.Count);
247-
248-
string? tmpVirtualHost = null;
249-
250-
bool first = true;
251-
foreach (Uri uri in _uris)
252-
{
253-
(string? user, string? password) = ProcessUserInfo(uri);
254-
255-
if (tmpVirtualHost is null)
256-
{
257-
tmpVirtualHost = ProcessUriSegmentsForVirtualHost(uri);
258-
}
259-
else
260-
{
261-
string thisVirtualHost = ProcessUriSegmentsForVirtualHost(uri);
262-
if (false == thisVirtualHost.Equals(tmpVirtualHost, StringComparison.InvariantCultureIgnoreCase))
263-
{
264-
throw new ArgumentException($"All AMQP URIs must use the same virtual host. Expected '{tmpVirtualHost}', got '{thisVirtualHost}'");
265-
}
266-
}
267-
268-
var address = new Address(host: uri.Host,
269-
port: uri.Port,
270-
user: user,
271-
password: password,
272-
path: "/",
273-
scheme: uri.Scheme);
274-
275-
_uriToAddress[uri] = address;
276-
277-
if (first)
278-
{
279-
_address = address;
280-
first = false;
281-
}
282-
}
283-
284-
if (tmpVirtualHost is not null)
285-
{
286-
_virtualHost = tmpVirtualHost;
287-
}
288-
}
289-
290227
public ConnectionSettings(string scheme,
291228
string host,
292229
int port,
@@ -315,7 +252,7 @@ public ConnectionSettings(string scheme,
315252
}
316253
}
317254

318-
private ConnectionSettings(
255+
protected ConnectionSettings(
319256
string? containerId = null,
320257
SaslMechanism? saslMechanism = null,
321258
IRecoveryConfiguration? recoveryConfiguration = null,
@@ -364,38 +301,9 @@ private ConnectionSettings(
364301
public TlsSettings? TlsSettings => _tlsSettings;
365302
public IRecoveryConfiguration Recovery => _recoveryConfiguration;
366303

367-
internal Address Address
368-
{
369-
get
370-
{
371-
if (_uris is not null &&
372-
_uriSelector is not null &&
373-
_uriToAddress is not null)
374-
{
375-
Uri uri = _uriSelector.Select(_uris);
376-
return _uriToAddress[uri];
377-
}
378-
else
379-
{
380-
return _address;
381-
}
382-
}
383-
}
304+
internal virtual Address Address => _address;
384305

385-
internal List<Address>? Addresses
386-
{
387-
get
388-
{
389-
if (_uriToAddress is not null)
390-
{
391-
return _uriToAddress.Values.ToList();
392-
}
393-
else
394-
{
395-
return null;
396-
}
397-
}
398-
}
306+
internal virtual IList<Address> Addresses => new[] { _address };
399307

400308
public override string ToString()
401309
{
@@ -456,15 +364,7 @@ public override int GetHashCode()
456364
_address.Scheme, _containerId, _address.Path);
457365
}
458366

459-
///<summary>
460-
/// Unescape a string, protecting '+'.
461-
/// </summary>
462-
private static string UriDecode(string str)
463-
{
464-
return Uri.UnescapeDataString(str.Replace("+", "%2B"));
465-
}
466-
467-
private static (string? user, string? password) ProcessUserInfo(Uri uri)
367+
protected static (string? user, string? password) ProcessUserInfo(Uri uri)
468368
{
469369
string? user = null;
470370
string? password = null;
@@ -487,7 +387,7 @@ private static (string? user, string? password) ProcessUserInfo(Uri uri)
487387
return (user, password);
488388
}
489389

490-
private static string ProcessUriSegmentsForVirtualHost(Uri uri)
390+
protected static string ProcessUriSegmentsForVirtualHost(Uri uri)
491391
{
492392
// C# automatically changes URIs into a canonical form
493393
// that has at least the path segment "/"
@@ -505,6 +405,96 @@ private static string ProcessUriSegmentsForVirtualHost(Uri uri)
505405
return Consts.DefaultVirtualHost;
506406
}
507407
}
408+
409+
///<summary>
410+
/// Unescape a string, protecting '+'.
411+
/// </summary>
412+
private static string UriDecode(string str)
413+
{
414+
return Uri.UnescapeDataString(str.Replace("+", "%2B"));
415+
}
416+
}
417+
418+
public class ConnectionSettingsViaUris : ConnectionSettings
419+
{
420+
private readonly List<Uri> _uris;
421+
private readonly Dictionary<Uri, Address> _uriToAddress;
422+
private readonly IUriSelector _uriSelector = new RandomUriSelector();
423+
424+
public ConnectionSettingsViaUris(IEnumerable<Uri> uris,
425+
IUriSelector? uriSelector = null,
426+
string? containerId = null,
427+
SaslMechanism? saslMechanism = null,
428+
IRecoveryConfiguration? recoveryConfiguration = null,
429+
uint? maxFrameSize = null,
430+
TlsSettings? tlsSettings = null)
431+
: base(containerId, saslMechanism, recoveryConfiguration, maxFrameSize, tlsSettings)
432+
{
433+
_uris = uris.ToList();
434+
if (_uris.Count == 0)
435+
{
436+
throw new ArgumentOutOfRangeException(nameof(uris), "At least one Uri is required.");
437+
}
438+
439+
_uriToAddress = new(_uris.Count);
440+
441+
if (uriSelector is not null)
442+
{
443+
_uriSelector = uriSelector;
444+
}
445+
446+
string? tmpVirtualHost = null;
447+
448+
bool first = true;
449+
foreach (Uri uri in _uris)
450+
{
451+
(string? user, string? password) = ProcessUserInfo(uri);
452+
453+
if (tmpVirtualHost is null)
454+
{
455+
tmpVirtualHost = ProcessUriSegmentsForVirtualHost(uri);
456+
}
457+
else
458+
{
459+
string thisVirtualHost = ProcessUriSegmentsForVirtualHost(uri);
460+
if (false == thisVirtualHost.Equals(tmpVirtualHost, StringComparison.InvariantCultureIgnoreCase))
461+
{
462+
throw new ArgumentException($"All AMQP URIs must use the same virtual host. Expected '{tmpVirtualHost}', got '{thisVirtualHost}'");
463+
}
464+
}
465+
466+
var address = new Address(host: uri.Host,
467+
port: uri.Port,
468+
user: user,
469+
password: password,
470+
path: "/",
471+
scheme: uri.Scheme);
472+
473+
_uriToAddress[uri] = address;
474+
475+
if (first)
476+
{
477+
_address = address;
478+
first = false;
479+
}
480+
}
481+
482+
if (tmpVirtualHost is not null)
483+
{
484+
_virtualHost = tmpVirtualHost;
485+
}
486+
}
487+
488+
internal override Address Address
489+
{
490+
get
491+
{
492+
Uri uri = _uriSelector.Select(_uris);
493+
return _uriToAddress[uri];
494+
}
495+
}
496+
497+
internal override IList<Address> Addresses => _uriToAddress.Values.ToList();
508498
}
509499

510500
public class TlsSettings

RabbitMQ.AMQP.Client/PublicAPI.Unshipped.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ RabbitMQ.AMQP.Client.ConnectionException.ConnectionException(string! message) ->
5959
RabbitMQ.AMQP.Client.ConnectionException.ConnectionException(string! message, System.Exception! innerException) -> void
6060
RabbitMQ.AMQP.Client.ConnectionSettings
6161
RabbitMQ.AMQP.Client.ConnectionSettings.ConnectionSettings(string! scheme, string! host, int port, string? user = null, string? password = null, string? virtualHost = null, string! containerId = "", RabbitMQ.AMQP.Client.SaslMechanism? saslMechanism = null, RabbitMQ.AMQP.Client.IRecoveryConfiguration? recoveryConfiguration = null, uint? maxFrameSize = null, RabbitMQ.AMQP.Client.TlsSettings? tlsSettings = null) -> void
62-
RabbitMQ.AMQP.Client.ConnectionSettings.ConnectionSettings(System.Collections.Generic.IEnumerable<System.Uri!>! uris, RabbitMQ.AMQP.Client.IUriSelector? uriSelector = null, string? containerId = null, RabbitMQ.AMQP.Client.SaslMechanism? saslMechanism = null, RabbitMQ.AMQP.Client.IRecoveryConfiguration? recoveryConfiguration = null, uint? maxFrameSize = null, RabbitMQ.AMQP.Client.TlsSettings? tlsSettings = null) -> void
62+
RabbitMQ.AMQP.Client.ConnectionSettings.ConnectionSettings(string? containerId = null, RabbitMQ.AMQP.Client.SaslMechanism? saslMechanism = null, RabbitMQ.AMQP.Client.IRecoveryConfiguration? recoveryConfiguration = null, uint? maxFrameSize = null, RabbitMQ.AMQP.Client.TlsSettings? tlsSettings = null) -> void
6363
RabbitMQ.AMQP.Client.ConnectionSettings.ConnectionSettings(System.Uri! uri, string? containerId = null, RabbitMQ.AMQP.Client.SaslMechanism? saslMechanism = null, RabbitMQ.AMQP.Client.IRecoveryConfiguration? recoveryConfiguration = null, uint? maxFrameSize = null, RabbitMQ.AMQP.Client.TlsSettings? tlsSettings = null) -> void
6464
RabbitMQ.AMQP.Client.ConnectionSettings.ContainerId.get -> string!
6565
RabbitMQ.AMQP.Client.ConnectionSettings.Host.get -> string!
@@ -74,6 +74,8 @@ RabbitMQ.AMQP.Client.ConnectionSettings.TlsSettings.get -> RabbitMQ.AMQP.Client.
7474
RabbitMQ.AMQP.Client.ConnectionSettings.User.get -> string?
7575
RabbitMQ.AMQP.Client.ConnectionSettings.UseSsl.get -> bool
7676
RabbitMQ.AMQP.Client.ConnectionSettings.VirtualHost.get -> string!
77+
RabbitMQ.AMQP.Client.ConnectionSettings._address -> Amqp.Address!
78+
RabbitMQ.AMQP.Client.ConnectionSettings._virtualHost -> string!
7779
RabbitMQ.AMQP.Client.ConnectionSettingsBuilder
7880
RabbitMQ.AMQP.Client.ConnectionSettingsBuilder.Build() -> RabbitMQ.AMQP.Client.ConnectionSettings!
7981
RabbitMQ.AMQP.Client.ConnectionSettingsBuilder.ConnectionSettingsBuilder() -> void
@@ -91,6 +93,8 @@ RabbitMQ.AMQP.Client.ConnectionSettingsBuilder.Uris(System.Collections.Generic.I
9193
RabbitMQ.AMQP.Client.ConnectionSettingsBuilder.UriSelector(RabbitMQ.AMQP.Client.IUriSelector! uriSelector) -> RabbitMQ.AMQP.Client.ConnectionSettingsBuilder!
9294
RabbitMQ.AMQP.Client.ConnectionSettingsBuilder.User(string! user) -> RabbitMQ.AMQP.Client.ConnectionSettingsBuilder!
9395
RabbitMQ.AMQP.Client.ConnectionSettingsBuilder.VirtualHost(string! virtualHost) -> RabbitMQ.AMQP.Client.ConnectionSettingsBuilder!
96+
RabbitMQ.AMQP.Client.ConnectionSettingsViaUris
97+
RabbitMQ.AMQP.Client.ConnectionSettingsViaUris.ConnectionSettingsViaUris(System.Collections.Generic.IEnumerable<System.Uri!>! uris, RabbitMQ.AMQP.Client.IUriSelector? uriSelector = null, string? containerId = null, RabbitMQ.AMQP.Client.SaslMechanism? saslMechanism = null, RabbitMQ.AMQP.Client.IRecoveryConfiguration? recoveryConfiguration = null, uint? maxFrameSize = null, RabbitMQ.AMQP.Client.TlsSettings? tlsSettings = null) -> void
9498
RabbitMQ.AMQP.Client.Consts
9599
RabbitMQ.AMQP.Client.ConsumerException
96100
RabbitMQ.AMQP.Client.ConsumerException.ConsumerException(string! message) -> void
@@ -761,6 +765,8 @@ static RabbitMQ.AMQP.Client.ByteCapacity.Gb(long gigabytes) -> RabbitMQ.AMQP.Cli
761765
static RabbitMQ.AMQP.Client.ByteCapacity.Kb(long megabytes) -> RabbitMQ.AMQP.Client.ByteCapacity!
762766
static RabbitMQ.AMQP.Client.ByteCapacity.Mb(long megabytes) -> RabbitMQ.AMQP.Client.ByteCapacity!
763767
static RabbitMQ.AMQP.Client.ByteCapacity.Tb(long terabytes) -> RabbitMQ.AMQP.Client.ByteCapacity!
768+
static RabbitMQ.AMQP.Client.ConnectionSettings.ProcessUriSegmentsForVirtualHost(System.Uri! uri) -> string!
769+
static RabbitMQ.AMQP.Client.ConnectionSettings.ProcessUserInfo(System.Uri! uri) -> (string? user, string? password)
764770
static RabbitMQ.AMQP.Client.ConnectionSettingsBuilder.Create() -> RabbitMQ.AMQP.Client.ConnectionSettingsBuilder!
765771
static RabbitMQ.AMQP.Client.Impl.AddressBuilderHelper.AddressBuilder() -> RabbitMQ.AMQP.Client.Impl.AddressBuilder!
766772
static RabbitMQ.AMQP.Client.Impl.AmqpConnection.CreateAsync(RabbitMQ.AMQP.Client.ConnectionSettings! connectionSettings, RabbitMQ.AMQP.Client.IMetricsReporter? metricsReporter = null) -> System.Threading.Tasks.Task<RabbitMQ.AMQP.Client.IConnection!>!

Tests/ConnectionTests/ConnectionSettingsTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public void ConnectionSettingsViaUris()
121121
var uri2 = new Uri($"{scheme}://{user}:{pass}@{host}:5691/%2Ffrazzle");
122122

123123
List<Uri> uris = [uri0, uri1, uri2];
124-
var connectionSettings = new ConnectionSettings(uris);
124+
var connectionSettings = new ConnectionSettingsViaUris(uris);
125125

126126
Assert.True(connectionSettings.UseSsl);
127127
Assert.Equal(host, connectionSettings.Host);
@@ -233,7 +233,7 @@ public void ConnectionSettingsViaUrisThrowsWithDifferentVirtualHosts()
233233
var uri2 = new Uri($"{scheme}://{user}:{pass}@{host}:5691/foo");
234234

235235
List<Uri> uris = [uri0, uri1, uri2];
236-
Assert.ThrowsAny<ArgumentException>(() => new ConnectionSettings(uris));
236+
Assert.ThrowsAny<ArgumentException>(() => new ConnectionSettingsViaUris(uris));
237237
}
238238

239239
[Fact]

0 commit comments

Comments
 (0)