Skip to content

Commit c3f2168

Browse files
authored
Merge branch 'main' into otel-integration-package
2 parents 582bd5c + f8087b6 commit c3f2168

23 files changed

+524
-150
lines changed

projects/RabbitMQ.Client/FrameworkExtension/DictionaryExtension.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ namespace RabbitMQ
3737
#if NETSTANDARD
3838
internal static class DictionaryExtension
3939
{
40-
public static bool Remove<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, out TValue value)
40+
public static bool Remove<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, out TValue value)
4141
{
4242
return dictionary.TryGetValue(key, out value) && dictionary.Remove(key);
4343
}

projects/RabbitMQ.Client/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,9 +952,9 @@ virtual RabbitMQ.Client.TcpClientAdapter.ReceiveTimeout.set -> void
952952
~static RabbitMQ.Client.IConnectionExtensions.AbortAsync(this RabbitMQ.Client.IConnection connection, System.TimeSpan timeout) -> System.Threading.Tasks.Task
953953
~static RabbitMQ.Client.IConnectionExtensions.AbortAsync(this RabbitMQ.Client.IConnection connection, ushort reasonCode, string reasonText) -> System.Threading.Tasks.Task
954954
~static RabbitMQ.Client.IConnectionExtensions.AbortAsync(this RabbitMQ.Client.IConnection connection, ushort reasonCode, string reasonText, System.TimeSpan timeout) -> System.Threading.Tasks.Task
955-
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection) -> System.Threading.Tasks.Task
955+
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task
956956
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection, System.TimeSpan timeout) -> System.Threading.Tasks.Task
957-
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection, ushort reasonCode, string reasonText) -> System.Threading.Tasks.Task
957+
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection, ushort reasonCode, string reasonText, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task
958958
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection, ushort reasonCode, string reasonText, System.TimeSpan timeout) -> System.Threading.Tasks.Task
959959
~static RabbitMQ.Client.RabbitMQActivitySource.ContextExtractor.get -> System.Func<RabbitMQ.Client.IReadOnlyBasicProperties, System.Diagnostics.ActivityContext>
960960
~static RabbitMQ.Client.RabbitMQActivitySource.ContextExtractor.set -> void

projects/RabbitMQ.Client/client/api/ConnectionFactory.cs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ public sealed class ConnectionFactory : ConnectionFactoryBase, IConnectionFactor
197197

198198
// just here to hold the value that was set through the setter
199199
private Uri _uri;
200+
private string _clientProvidedName;
200201

201202
/// <summary>
202203
/// Amount of time protocol handshake operations are allowed to take before
@@ -367,7 +368,14 @@ public Uri Uri
367368
/// <summary>
368369
/// Default client provided name to be used for connections.
369370
/// </summary>
370-
public string ClientProvidedName { get; set; }
371+
public string ClientProvidedName
372+
{
373+
get => _clientProvidedName;
374+
set
375+
{
376+
_clientProvidedName = EnsureClientProvidedNameLength(value);
377+
}
378+
}
371379

372380
/// <summary>
373381
/// Given a list of mechanism names supported by the server, select a preferred mechanism,
@@ -593,7 +601,7 @@ private ConnectionConfig CreateConfig(string clientProvidedName)
593601
CredentialsRefresher,
594602
AuthMechanisms,
595603
ClientProperties,
596-
clientProvidedName,
604+
EnsureClientProvidedNameLength(clientProvidedName),
597605
RequestedChannelMax,
598606
RequestedFrameMax,
599607
MaxInboundMessageBodySize,
@@ -712,5 +720,18 @@ private List<AmqpTcpEndpoint> LocalEndpoints()
712720
{
713721
return new List<AmqpTcpEndpoint> { Endpoint };
714722
}
723+
724+
private static string EnsureClientProvidedNameLength(string clientProvidedName)
725+
{
726+
if (clientProvidedName != null)
727+
{
728+
if (clientProvidedName.Length > InternalConstants.DefaultRabbitMqMaxClientProvideNameLength)
729+
{
730+
return clientProvidedName.Substring(0, InternalConstants.DefaultRabbitMqMaxClientProvideNameLength);
731+
}
732+
}
733+
734+
return clientProvidedName;
735+
}
715736
}
716737
}

projects/RabbitMQ.Client/client/api/IConnectionExtensions.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ public static class IConnectionExtensions
1818
/// (or closing), then this method will do nothing.
1919
/// It can also throw <see cref="IOException"/> when socket was closed unexpectedly.
2020
/// </remarks>
21-
public static Task CloseAsync(this IConnection connection)
21+
public static Task CloseAsync(this IConnection connection, CancellationToken cancellationToken = default)
2222
{
2323
return connection.CloseAsync(Constants.ReplySuccess, "Goodbye", InternalConstants.DefaultConnectionCloseTimeout, false,
24-
CancellationToken.None);
24+
cancellationToken);
2525
}
2626

2727
/// <summary>
2828
/// Asynchronously close this connection and all its channels.
2929
/// </summary>
3030
/// <remarks>
31-
/// The method behaves in the same way as <see cref="CloseAsync(IConnection)"/>, with the only
31+
/// The method behaves in the same way as <see cref="CloseAsync(IConnection, CancellationToken)"/>, with the only
3232
/// difference that the connection is closed with the given connection close code and message.
3333
/// <para>
3434
/// The close code (See under "Reply Codes" in the AMQP specification).
@@ -37,10 +37,11 @@ public static Task CloseAsync(this IConnection connection)
3737
/// A message indicating the reason for closing the connection.
3838
/// </para>
3939
/// </remarks>
40-
public static Task CloseAsync(this IConnection connection, ushort reasonCode, string reasonText)
40+
public static Task CloseAsync(this IConnection connection, ushort reasonCode, string reasonText,
41+
CancellationToken cancellationToken = default)
4142
{
4243
return connection.CloseAsync(reasonCode, reasonText, InternalConstants.DefaultConnectionCloseTimeout, false,
43-
CancellationToken.None);
44+
cancellationToken);
4445
}
4546

4647
/// <summary>
@@ -92,7 +93,7 @@ public static Task CloseAsync(this IConnection connection, ushort reasonCode, st
9293
/// </summary>
9394
/// <remarks>
9495
/// Note that all active channels and sessions will be closed if this method is called.
95-
/// In comparison to normal <see cref="CloseAsync(IConnection)"/> method, <see cref="AbortAsync(IConnection)"/> will not throw
96+
/// In comparison to normal <see cref="CloseAsync(IConnection, CancellationToken)"/> method, <see cref="AbortAsync(IConnection)"/> will not throw
9697
/// <see cref="IOException"/> during closing connection.
9798
///This method waits infinitely for the in-progress close operation to complete.
9899
/// </remarks>

projects/RabbitMQ.Client/client/api/InternalConstants.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,12 @@ internal static class InternalConstants
4444
/// configures the largest message size which should be lower than this maximum of 128MiB.
4545
/// </summary>
4646
internal const uint DefaultRabbitMqMaxInboundMessageBodySize = 1_048_576 * 128;
47+
48+
/// <summary>
49+
/// Largest client provide name, in characters, allowed in RabbitMQ.
50+
/// This is not configurable, but was discovered while working on this issue:
51+
/// https://github.com/rabbitmq/rabbitmq-dotnet-client/issues/980
52+
/// </summary>
53+
internal const int DefaultRabbitMqMaxClientProvideNameLength = 3000;
4754
}
4855
}

projects/RabbitMQ.Client/client/impl/AsyncEventingWrapper.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Linq;
32
using System.Threading.Tasks;
43
using RabbitMQ.Client.Events;
54

@@ -55,7 +54,7 @@ public Task InvokeAsync(object sender, T parameter)
5554

5655
private readonly async Task InternalInvoke(Delegate[] handlers, object sender, T parameter)
5756
{
58-
foreach (AsyncEventHandler<T> action in handlers.Cast<AsyncEventHandler<T>>())
57+
foreach (AsyncEventHandler<T> action in handlers)
5958
{
6059
try
6160
{

projects/RabbitMQ.Client/client/impl/AutorecoveringChannel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ public async Task<string> BasicConsumeAsync(string queue, bool autoAck, string c
279279
{
280280
string resultConsumerTag = await InnerChannel.BasicConsumeAsync(queue, autoAck, consumerTag, noLocal,
281281
exclusive, arguments, consumer, cancellationToken)
282-
.ConfigureAwait(false);
282+
.ConfigureAwait(false) ?? throw new InvalidOperationException("basic.consume returned null consumer tag");
283283
var rc = new RecordedConsumer(channel: this, consumer: consumer, consumerTag: resultConsumerTag,
284284
queue: queue, autoAck: autoAck, exclusive: exclusive, arguments: arguments);
285285
await _connection.RecordConsumerAsync(rc, recordedEntitiesSemaphoreHeld: false)

projects/RabbitMQ.Client/client/impl/AutorecoveringConnection.Recording.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
// Copyright (c) 2007-2020 VMware, Inc. All rights reserved.
3030
//---------------------------------------------------------------------------
3131

32+
using System;
3233
using System.Collections.Generic;
3334
using System.Linq;
3435
using System.Threading;
@@ -400,6 +401,11 @@ await _recordedEntitiesSemaphore.WaitAsync()
400401

401402
private void DoDeleteRecordedConsumer(string consumerTag)
402403
{
404+
if (consumerTag is null)
405+
{
406+
throw new ArgumentNullException(nameof(consumerTag));
407+
}
408+
403409
if (_recordedConsumers.Remove(consumerTag, out RecordedConsumer recordedConsumer))
404410
{
405411
DeleteAutoDeleteQueue(recordedConsumer.Queue);

projects/RabbitMQ.Client/client/impl/AutorecoveringConnection.Recovery.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,23 @@ static bool ShouldTriggerConnectionRecovery(ShutdownEventArgs args)
7171
}
7272
}
7373

74-
// happens when EOF is reached, e.g. due to RabbitMQ node
75-
// connectivity loss or abrupt shutdown
7674
if (args.Initiator == ShutdownInitiator.Library)
7775
{
78-
return true;
76+
/*
77+
* https://github.com/rabbitmq/rabbitmq-dotnet-client/issues/826
78+
* Happens when an AppDomain is unloaded
79+
*/
80+
if (args.Exception is ThreadAbortException &&
81+
args.ReplyCode == Constants.InternalError)
82+
{
83+
return false;
84+
}
85+
else
86+
{
87+
// happens when EOF is reached, e.g. due to RabbitMQ node
88+
// connectivity loss or abrupt shutdown
89+
return true;
90+
}
7991
}
8092

8193
return false;

projects/RabbitMQ.Client/client/impl/Connection.Receive.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,19 @@ private async Task MainLoop()
5353
await ReceiveLoopAsync(mainLoopToken)
5454
.ConfigureAwait(false);
5555
}
56+
#if NETSTANDARD
57+
catch (ThreadAbortException taex)
58+
{
59+
/*
60+
* https://github.com/rabbitmq/rabbitmq-dotnet-client/issues/826
61+
*/
62+
var ea = new ShutdownEventArgs(ShutdownInitiator.Library,
63+
Constants.InternalError,
64+
"Thread aborted (AppDomain unloaded?)",
65+
exception: taex);
66+
HandleMainLoopException(ea);
67+
}
68+
#endif
5669
catch (EndOfStreamException eose)
5770
{
5871
// Possible heartbeat exception

0 commit comments

Comments
 (0)