Compare commits

...

2 Commits

Author SHA1 Message Date
James Newton-King a57f1e506b
Fix using disposed token in connect and resulting status (#1873) 2022-09-01 21:34:06 +08:00
Jan Tattermusch 09641160f9
Update version to 2.49.0-pre1 (on v2.49.x branch) (#1866)
* Update version.props

* Update VersionInfo.cs
2022-09-01 15:24:39 +02:00
8 changed files with 50 additions and 5 deletions

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<!-- package version of grpc-dotnet -->
<GrpcDotnetVersion>2.49.0-dev</GrpcDotnetVersion>
<GrpcDotnetVersion>2.49.0-pre1</GrpcDotnetVersion>
<!-- assembly version of grpc-dotnet -->
<GrpcDotnetAssemblyVersion>2.0.0.0</GrpcDotnetAssemblyVersion>

View File

@ -41,6 +41,6 @@ namespace Grpc.Core
/// <summary>
/// Current version of gRPC C#
/// </summary>
public const string CurrentVersion = "2.49.0-dev";
public const string CurrentVersion = "2.49.0-pre1";
}
}

View File

@ -18,6 +18,7 @@
#if SUPPORT_LOAD_BALANCING
using System;
using System.Diagnostics;
using Grpc.Core;
namespace Grpc.Net.Client.Balancer.Internal
@ -28,6 +29,7 @@ namespace Grpc.Net.Client.Balancer.Internal
public ErrorPicker(Status status)
{
Debug.Assert(status.StatusCode != StatusCode.OK, "Error status code must not be OK.");
_status = status;
}

View File

@ -46,6 +46,7 @@ namespace Grpc.Net.Client.Balancer.Internal
internal sealed class ConnectContext
{
private readonly CancellationTokenSource _cts;
private readonly CancellationToken _token;
private bool _disposed;
// This flag allows the transport to determine why the cancellation token was canceled.
@ -53,11 +54,14 @@ namespace Grpc.Net.Client.Balancer.Internal
// - Connection timeout, e.g. SocketsHttpHandler.ConnectTimeout was exceeded.
public bool IsConnectCanceled { get; private set; }
public CancellationToken CancellationToken => _cts.Token;
public CancellationToken CancellationToken => _token;
public ConnectContext(TimeSpan connectTimeout)
{
_cts = new CancellationTokenSource(connectTimeout);
// Take a copy of the token to avoid ObjectDisposedException when accessing _cts.Token after CTS is disposed.
_token = _cts.Token;
}
public void CancelConnect()

View File

@ -313,7 +313,7 @@ namespace Grpc.Net.Client.Balancer
{
SubchannelLog.ConnectError(_logger, Id, ex);
UpdateConnectivityState(ConnectivityState.TransientFailure, "Error connecting to subchannel.");
UpdateConnectivityState(ConnectivityState.TransientFailure, new Status(StatusCode.Unavailable, "Error connecting to subchannel.", ex));
}
finally
{

View File

@ -144,6 +144,43 @@ namespace Grpc.Net.Client.Tests.Balancer
Assert.AreEqual(StatusCode.DataLoss, ex.StatusCode);
}
[Test]
public async Task PickAsync_ErrorConnectingToSubchannel_ThrowsError()
{
// Arrange
var services = new ServiceCollection();
services.AddNUnitLogger();
var serviceProvider = services.BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
var resolver = new TestResolver(loggerFactory);
resolver.UpdateAddresses(new List<BalancerAddress>
{
new BalancerAddress("localhost", 80)
});
var transportFactory = new TestSubchannelTransportFactory((s, c) =>
{
return Task.FromException<ConnectivityState>(new Exception("Test error!"));
});
var clientChannel = CreateConnectionManager(loggerFactory, resolver, transportFactory);
clientChannel.ConfigureBalancer(c => new PickFirstBalancer(c, loggerFactory));
// Act
_ = clientChannel.ConnectAsync(waitForReady: false, CancellationToken.None).ConfigureAwait(false);
var pickTask = clientChannel.PickAsync(
new PickContext { Request = new HttpRequestMessage() },
waitForReady: false,
CancellationToken.None).AsTask();
// Assert
var ex = await ExceptionAssert.ThrowsAsync<RpcException>(() => pickTask).DefaultTimeout();
Assert.AreEqual(StatusCode.Unavailable, ex.StatusCode);
Assert.AreEqual("Error connecting to subchannel.", ex.Status.Detail);
Assert.AreEqual("Test error!", ex.Status.DebugException?.Message);
}
[Test]
public async Task PickAsync_RetryWithDrop_ThrowsError()
{

View File

@ -626,6 +626,7 @@ namespace Grpc.Net.Client.Tests
var currentConnectivityState = ConnectivityState.TransientFailure;
var services = new ServiceCollection();
services.AddNUnitLogger();
services.AddSingleton<ResolverFactory, ChannelTestResolverFactory>();
services.AddSingleton<ISubchannelTransportFactory>(new TestSubchannelTransportFactory(async (s, c) =>
{

View File

@ -81,7 +81,8 @@ namespace Grpc.Net.Client.Tests.Infrastructure.Balancer
var newState = await (_onTryConnect?.Invoke(context.CancellationToken) ?? Task.FromResult(ConnectivityState.Ready));
CurrentAddress = Subchannel._addresses[0];
Subchannel.UpdateConnectivityState(newState, Status.DefaultSuccess);
var newStatus = newState == ConnectivityState.TransientFailure ? new Status(StatusCode.Internal, "") : Status.DefaultSuccess;
Subchannel.UpdateConnectivityState(newState, newStatus);
_connectTcs.TrySetResult(null);