Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add netstandard2.0 to Grpc.Net.ClientFactory #1248

Merged
merged 2 commits into from
Mar 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Grpc.Net.Client/Grpc.Net.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
<Compile Include="..\Shared\HttpHandlerFactory.cs" Link="Internal\Http\HttpHandlerFactory.cs" />
<Compile Include="..\Shared\TelemetryHeaderHandler.cs" Link="Internal\Http\TelemetryHeaderHandler.cs" />
<Compile Include="..\Shared\TrailingHeadersHelpers.cs" Link="Internal\Http\TrailingHeadersHelpers.cs" />
<Compile Include="..\Shared\CompatibilityHelpers.cs" Link="Internal\CompatibilityHelpers.cs" />
<Compile Include="..\Shared\NullableAttributes.cs" Link="Internal\NullableAttributes.cs" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Grpc.Net.Client/GrpcChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ internal void RemoveFromRetryBuffer(long messageSize)

internal int GetRandomNumber(int minValue, int maxValue)
{
CompatibilityExtensions.Assert(_random != null);
CompatibilityHelpers.Assert(_random != null);

lock (_lock)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Grpc.Net.Client/Internal/GrpcCall.NonGeneric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ protected bool TryGetTrailers([NotNullWhen(true)] out Metadata? trailers)
return false;
}

CompatibilityExtensions.Assert(HttpResponse != null);
CompatibilityHelpers.Assert(HttpResponse != null);
Trailers = GrpcProtocolHelpers.BuildMetadata(HttpResponse.TrailingHeaders());
}

Expand Down
8 changes: 4 additions & 4 deletions src/Grpc.Net.Client/Internal/GrpcCall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ public Task<Metadata> GetResponseHeadersAsync()

private async Task<Metadata> GetResponseHeadersCoreAsync()
{
CompatibilityExtensions.Assert(_httpResponseTask != null);
CompatibilityHelpers.Assert(_httpResponseTask != null);

try
{
Expand Down Expand Up @@ -332,7 +332,7 @@ public Status GetStatus()

public Task<TResponse> GetResponseAsync()
{
CompatibilityExtensions.Assert(_responseTcs != null);
CompatibilityHelpers.Assert(_responseTcs != null);
return _responseTcs.Task;
}

Expand Down Expand Up @@ -556,7 +556,7 @@ private async Task RunCall(HttpRequestMessage request, TimeSpan? timeout)
else
{
// Duplex or server streaming call
CompatibilityExtensions.Assert(ClientStreamReader != null);
CompatibilityHelpers.Assert(ClientStreamReader != null);
ClientStreamReader.HttpResponseTcs.TrySetResult((HttpResponse, status));

// Wait until the response has been read and status read from trailers.
Expand Down Expand Up @@ -628,7 +628,7 @@ internal bool ResolveException(string summary, Exception ex, [NotNull] out Statu

private void SetFailedResult(Status status)
{
CompatibilityExtensions.Assert(_responseTcs != null);
CompatibilityHelpers.Assert(_responseTcs != null);

if (Channel.ThrowOperationCanceledOnCancellation && status.StatusCode == StatusCode.DeadlineExceeded)
{
Expand Down
9 changes: 5 additions & 4 deletions src/Grpc.Net.Client/Internal/GrpcCallSerializationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
using System.Runtime.InteropServices;
using Grpc.Core;
using Grpc.Net.Compression;
using Grpc.Shared;

namespace Grpc.Net.Client.Internal
{
Expand Down Expand Up @@ -108,7 +109,7 @@ public ReadOnlyMemory<byte> GetWrittenPayload()

private ICompressionProvider? ResolveCompressionProvider()
{
CompatibilityExtensions.Assert(
CompatibilityHelpers.Assert(
_call.RequestGrpcEncoding != null,
"Response encoding should have been calculated at this point.");

Expand Down Expand Up @@ -177,7 +178,7 @@ public override IBufferWriter<byte> GetBufferWriter()
// When writing directly to the buffer the header with message size needs to be written first
if (DirectSerializationSupported)
{
CompatibilityExtensions.Assert(_payloadLength != null, "A payload length is required for direct serialization.");
CompatibilityHelpers.Assert(_payloadLength != null, "A payload length is required for direct serialization.");

EnsureMessageSizeAllowed(_payloadLength.Value);

Expand Down Expand Up @@ -239,7 +240,7 @@ public override void Complete()

if (!DirectSerializationSupported)
{
CompatibilityExtensions.Assert(_bufferWriter != null, "Buffer writer has been set to get to this state.");
CompatibilityHelpers.Assert(_bufferWriter != null, "Buffer writer has been set to get to this state.");

var data = _bufferWriter.WrittenSpan;

Expand Down Expand Up @@ -277,7 +278,7 @@ private void WriteMessage(ReadOnlySpan<byte> data)

private ReadOnlySpan<byte> CompressMessage(ReadOnlySpan<byte> messageData)
{
CompatibilityExtensions.Assert(_compressionProvider != null, "Compression provider is not null to get here.");
CompatibilityHelpers.Assert(_compressionProvider != null, "Compression provider is not null to get here.");

GrpcCallLog.CompressingMessage(_call.Logger, _compressionProvider.EncodingName);

Expand Down
1 change: 1 addition & 0 deletions src/Grpc.Net.Client/Internal/Http/PushUnaryContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Grpc.Shared;

#if NETSTANDARD2_0
using ValueTask = System.Threading.Tasks.Task;
Expand Down
1 change: 1 addition & 0 deletions src/Grpc.Net.Client/Internal/Http/WinHttpUnaryContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#endregion

using Grpc.Core;
using Grpc.Shared;
using System;
using System.Buffers;
using System.IO;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Shared;
using Microsoft.Extensions.Logging;

namespace Grpc.Net.Client.Internal
Expand Down Expand Up @@ -160,7 +161,7 @@ private async Task<bool> MoveNextCore(CancellationToken cancellationToken)
}
}

CompatibilityExtensions.Assert(_grpcEncoding != null, "Encoding should have been calculated from response.");
CompatibilityHelpers.Assert(_grpcEncoding != null, "Encoding should have been calculated from response.");

Current = await _call.ReadMessageAsync(
_responseStream,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using System.IO;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Shared;

#if NETSTANDARD2_0
using ValueTask = System.Threading.Tasks.Task;
Expand Down
9 changes: 5 additions & 4 deletions src/Grpc.Net.Client/Internal/Retry/HedgingCall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Shared;

namespace Grpc.Net.Client.Internal.Retry
{
Expand Down Expand Up @@ -85,7 +86,7 @@ private async Task StartCall(Action<GrpcCall<TRequest, TResponse>> startCallFunc
{
call.CancellationToken.ThrowIfCancellationRequested();

CompatibilityExtensions.Assert(call._httpResponseTask != null, "Request should have been made if call is not preemptively cancelled.");
CompatibilityHelpers.Assert(call._httpResponseTask != null, "Request should have been made if call is not preemptively cancelled.");
httpResponse = await call._httpResponseTask.ConfigureAwait(false);

responseStatus = GrpcCall.ValidateHeaders(httpResponse, out _);
Expand Down Expand Up @@ -291,12 +292,12 @@ private async Task CreateHedgingCalls(Action<GrpcCall<TRequest, TResponse>> star

private async Task HedgingDelayAsync(TimeSpan hedgingDelay)
{
CompatibilityExtensions.Assert(_hedgingDelayCts != null);
CompatibilityExtensions.Assert(_delayInterruptTcs != null);
CompatibilityHelpers.Assert(_hedgingDelayCts != null);
CompatibilityHelpers.Assert(_delayInterruptTcs != null);

while (true)
{
CompatibilityExtensions.Assert(_hedgingDelayCts != null);
CompatibilityHelpers.Assert(_hedgingDelayCts != null);

var completedTask = await Task.WhenAny(Task.Delay(hedgingDelay, _hedgingDelayCts.Token), _delayInterruptTcs.Task).ConfigureAwait(false);
if (completedTask != _delayInterruptTcs.Task)
Expand Down
5 changes: 3 additions & 2 deletions src/Grpc.Net.Client/Internal/Retry/RetryCall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Shared;

namespace Grpc.Net.Client.Internal.Retry
{
Expand Down Expand Up @@ -129,7 +130,7 @@ private async Task StartRetry(Action<GrpcCall<TRequest, TResponse>> startCallFun
{
currentCall.CancellationToken.ThrowIfCancellationRequested();

CompatibilityExtensions.Assert(currentCall._httpResponseTask != null, "Request should have been made if call is not preemptively cancelled.");
CompatibilityHelpers.Assert(currentCall._httpResponseTask != null, "Request should have been made if call is not preemptively cancelled.");
httpResponse = await currentCall._httpResponseTask.ConfigureAwait(false);

responseStatus = GrpcCall.ValidateHeaders(httpResponse, out _);
Expand Down Expand Up @@ -266,7 +267,7 @@ public override Task ClientStreamWriteAsync(TRequest message)
// The retry client stream writer prevents multiple threads from reaching here.
return DoClientStreamActionAsync(async call =>
{
CompatibilityExtensions.Assert(call.ClientStreamWriter != null);
CompatibilityHelpers.Assert(call.ClientStreamWriter != null);

if (ClientStreamWriteOptions != null)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Grpc.Net.Client/Internal/Retry/RetryCallBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ Task IGrpcCall<TRequest, TResponse>.WriteClientStreamAsync<TState>(Func<GrpcCall

protected async Task<IGrpcCall<TRequest, TResponse>?> GetActiveCallUnsynchronizedAsync(IGrpcCall<TRequest, TResponse>? previousCall)
{
CompatibilityExtensions.Assert(NewActiveCallTcs != null);
CompatibilityHelpers.Assert(NewActiveCallTcs != null);

var call = await NewActiveCallTcs.Task.ConfigureAwait(false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Shared;

namespace Grpc.Net.Client.Internal.Retry
{
Expand Down
4 changes: 3 additions & 1 deletion src/Grpc.Net.ClientFactory/Grpc.Net.ClientFactory.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@

<IsGrpcPublishedPackage>true</IsGrpcPublishedPackage>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<TargetFrameworks>netstandard2.1;net5.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netstandard2.1;net5.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Shared\HttpHandlerFactory.cs" Link="Internal\HttpHandlerFactory.cs" />
<Compile Include="..\Shared\TelemetryHeaderHandler.cs" Link="Internal\TelemetryHeaderHandler.cs" />
<Compile Include="..\Shared\CompatibilityHelpers.cs" Link="Internal\CompatibilityHelpers.cs" />
<Compile Include="..\Shared\NullableAttributes.cs" Link="Internal\NullableAttributes.cs" />
</ItemGroup>

<ItemGroup>
Expand Down
27 changes: 23 additions & 4 deletions src/Grpc.Net.ClientFactory/GrpcClientServiceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
using Grpc.Net.ClientFactory.Internal;
using Grpc.Shared;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.Options;

namespace Microsoft.Extensions.DependencyInjection
Expand Down Expand Up @@ -321,12 +322,30 @@ private static IHttpClientBuilder AddGrpcHttpClient<TClient>(this IServiceCollec
.AddHttpClient(name)
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = HttpHandlerFactory.CreatePrimaryHandler();
// Set PrimaryHandler to null so we can track whether the user
// set a value or not. If they didn't set their own handler then
// one will be created by PostConfigure.
return null;
});

services.PostConfigure<HttpClientFactoryOptions>(name, options =>
{
options.HttpMessageHandlerBuilderActions.Add(static builder =>
{
if (builder.PrimaryHandler == null)
{
// This will throw in .NET Standard 2.0 with a prompt that a user must set a handler.
// Because it throws it should only be called in PostConfigure if no handler has been set.
var handler = HttpHandlerFactory.CreatePrimaryHandler();
#if NET5_0
handler = HttpHandlerFactory.EnsureTelemetryHandler(handler);
handler = HttpHandlerFactory.EnsureTelemetryHandler(handler);
#endif
return handler;

builder.PrimaryHandler = handler;
}
});
});


var builder = new DefaultHttpClientBuilder(services, name);

Expand Down Expand Up @@ -357,7 +376,7 @@ public DefaultHttpClientBuilder(IServiceCollection services, string name)
private static void ReserveClient(IHttpClientBuilder builder, Type type, string name)
{
var registry = (GrpcClientMappingRegistry)builder.Services.Single(sd => sd.ServiceType == typeof(GrpcClientMappingRegistry)).ImplementationInstance;
Debug.Assert(registry != null);
CompatibilityHelpers.Assert(registry != null);

// Check for same name registered to two different types. This won't work because we rely on named options for the configuration.
if (registry.NamedClientRegistrations.TryGetValue(name, out var otherType) && type != otherType)
Expand Down
5 changes: 5 additions & 0 deletions src/Grpc.Net.ClientFactory/Internal/TypeNameHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,12 @@ private static void ProcessGenericType(StringBuilder builder, Type type, Type[]
}
}

#if NETSTANDARD2_0
var genericPartIndex = type.Name.IndexOf('`');
#else
var genericPartIndex = type.Name.IndexOf('`', StringComparison.Ordinal);
#endif

if (genericPartIndex <= 0)
{
builder.Append(type.Name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace Grpc.Net.Client.Internal
namespace Grpc.Shared
{
internal static class CompatibilityExtensions
internal static class CompatibilityHelpers
{
[Conditional("DEBUG")]
public static void Assert([DoesNotReturnIf(false)] bool condition, string? message = null)
Expand Down
10 changes: 5 additions & 5 deletions test/Grpc.Net.Client.Tests/CompressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,12 @@ public async Task AsyncUnaryCall_CompressMetadataSentWithRequest_RequestMessageC
Assert.IsNotNull(response);
Assert.AreEqual("Hello world", response.Message);

CompatibilityExtensions.Assert(httpRequestMessage != null);
CompatibilityHelpers.Assert(httpRequestMessage != null);
Assert.AreEqual("identity,gzip,test", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageAcceptEncodingHeader).Single());
Assert.AreEqual("gzip", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageEncodingHeader).Single());
Assert.AreEqual(false, httpRequestMessage.Headers.Contains(GrpcProtocolConstants.CompressionRequestAlgorithmHeader));

CompatibilityExtensions.Assert(helloRequest != null);
CompatibilityHelpers.Assert(helloRequest != null);
Assert.AreEqual("Hello", helloRequest.Name);

Assert.AreEqual(compressionDisabledOnOptions, isRequestNotCompressed);
Expand Down Expand Up @@ -324,14 +324,14 @@ await call.RequestStream.WriteAsync(new HelloRequest
Assert.IsNotNull(response);
Assert.AreEqual("Hello world", response.Message);

CompatibilityExtensions.Assert(httpRequestMessage != null);
CompatibilityHelpers.Assert(httpRequestMessage != null);
Assert.AreEqual("identity,gzip,test", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageAcceptEncodingHeader).Single());
Assert.AreEqual("gzip", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageEncodingHeader).Single());
Assert.AreEqual(false, httpRequestMessage.Headers.Contains(GrpcProtocolConstants.CompressionRequestAlgorithmHeader));

CompatibilityExtensions.Assert(helloRequest1 != null);
CompatibilityHelpers.Assert(helloRequest1 != null);
Assert.AreEqual("Hello One", helloRequest1.Name);
CompatibilityExtensions.Assert(helloRequest2 != null);
CompatibilityHelpers.Assert(helloRequest2 != null);
Assert.AreEqual("Hello Two", helloRequest2.Name);

Assert.IsTrue(isRequestCompressed1);
Expand Down
5 changes: 3 additions & 2 deletions test/Grpc.Net.Client.Tests/Retry/HedgingCallTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
using Grpc.Net.Client.Internal.Http;
using Grpc.Net.Client.Internal.Retry;
using Grpc.Net.Client.Tests.Infrastructure;
using Grpc.Shared;
using Grpc.Tests.Shared;
using NUnit.Framework;

Expand Down Expand Up @@ -299,10 +300,10 @@ public async Task RetryThrottling_BecomesActiveDuringDelay_CancelFailure()
// Assert
await TestHelpers.AssertIsTrueRetryAsync(() => hedgingCall._activeCalls.Count == 0, "Wait for all calls to fail.").DefaultTimeout();

CompatibilityExtensions.Assert(invoker.Channel.RetryThrottling != null);
CompatibilityHelpers.Assert(invoker.Channel.RetryThrottling != null);
invoker.Channel.RetryThrottling.CallFailure();
invoker.Channel.RetryThrottling.CallFailure();
CompatibilityExtensions.Assert(invoker.Channel.RetryThrottling.IsRetryThrottlingActive());
CompatibilityHelpers.Assert(invoker.Channel.RetryThrottling.IsRetryThrottlingActive());

var ex = await ExceptionAssert.ThrowsAsync<RpcException>(() => hedgingCall.GetResponseAsync()).DefaultTimeout();
Assert.AreEqual(1, callCount);
Expand Down
Loading