Skip to content
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
5 changes: 2 additions & 3 deletions extensions/Worker.Extensions.Rpc/release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
- My change description (#PR/#issue)
-->

### Microsoft.Azure.Functions.Worker.Extensions.Rpc 1.0.0
### Microsoft.Azure.Functions.Worker.Extensions.Rpc 1.0.1

- Initial public release
- Adds API for getting a `CallInvoker` pre-configured for communication with Functions host.
- Set max message send and receive length on gRPC `CallInvoker`.
11 changes: 11 additions & 0 deletions extensions/Worker.Extensions.Rpc/src/ConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,16 @@ public static Uri GetFunctionsHostGrpcUri(this IConfiguration configuration)

return grpcUri;
}

/// <summary>
/// Gets the maximum message length for the functions host gRPC channel.
/// </summary>
/// <param name="configuration">The configuration to retrieve values from.</param>
/// <returns>The maximum message length if available. </returns>
public static int? GetFunctionsHostMaxMessageLength(this IConfiguration configuration)
{
return configuration.GetValue<int?>("Functions:Worker:GrpcMaxMessageLength", null)
?? configuration.GetValue<int?>("grpcMaxMessageLength", null);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,18 @@ public static IHttpClientBuilder ConfigureForFunctionsHostGrpc(this IHttpClientB

ValidateGrpcClient(builder);
builder.Services.AddOptions<GrpcClientFactoryOptions>(builder.Name)
.Configure<IConfiguration>((options, config) => options.Address = config.GetFunctionsHostGrpcUri());
.Configure<IConfiguration>((options, config) =>
{
options.Address = config.GetFunctionsHostGrpcUri();
if (config.GetFunctionsHostMaxMessageLength() is int length)
{
options.ChannelOptionsActions.Add(o =>
{
o.MaxReceiveMessageSize = length;
o.MaxSendMessageSize = length;
});
}
});

return builder;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

#if !NETSTANDARD
Expand All @@ -19,8 +19,7 @@ private static void ConfigureCallInvoker(IServiceCollection services)
{
// Instead of building the GrpcChannel/CallInvoker ourselves, we use Grpc.Net.ClientFactory to
// construct and configure the CallInvoker for us, then we attach that to our options.
services.AddGrpcClient<CallInvokerExtractor>(_ => { })
.ConfigureForFunctionsHostGrpc();
services.AddGrpcClient<CallInvokerExtractor>(_ => { }).ConfigureForFunctionsHostGrpc();
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<FunctionsGrpcOptions>, ConfigureOptions>());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

#if NETSTANDARD
using System;
using System.Collections.Generic;
using System.Linq;
using Grpc.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -33,8 +35,18 @@ public ConfigureOptions(IConfiguration configuration)

public void Configure(FunctionsGrpcOptions options)
{
IEnumerable<ChannelOption> channelOptions = _configuration.GetFunctionsHostMaxMessageLength() switch
{
int maxMessageLength => new[]
{
new ChannelOption(ChannelOptions.MaxReceiveMessageLength, maxMessageLength),
new ChannelOption(ChannelOptions.MaxSendMessageLength, maxMessageLength),
},
_ => Enumerable.Empty<ChannelOption>(),
};

Uri address = _configuration.GetFunctionsHostGrpcUri();
Channel c = new Channel(address.Host, address.Port, ChannelCredentials.Insecure);
Channel c = new Channel(address.Host, address.Port, ChannelCredentials.Insecure, channelOptions);
options.CallInvoker = c.CreateCallInvoker();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<AssemblyName>Microsoft.Azure.Functions.Worker.Extensions.Rpc</AssemblyName>
<RootNamespace>Microsoft.Azure.Functions.Worker.Extensions.Rpc</RootNamespace>
<Description>Contains types to facilitate RPC communication between a worker extension and the functions host.</Description>
<VersionPrefix>1.0.0</VersionPrefix>
<VersionPrefix>1.0.1</VersionPrefix>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#if NET6_0_OR_GREATER

using Grpc.Core;
using Grpc.Net.Client;
using Grpc.Net.ClientFactory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -23,14 +24,19 @@ public void ConfigureForFunctionsHostGrpc_Configure_SetsUri()
public void ConfigureForFunctionsHostGrpc_SetsUri()
=> ConfigureForFunctionsHostGrpc(s => s.AddGrpcClient<CallInvokerExtractor>());

private void ConfigureForFunctionsHostGrpc(Func<IServiceCollection, IHttpClientBuilder> configure)
[Fact]
public void ConfigureForFunctionsHostGrpc_SetsMessageSize()
=> ConfigureForFunctionsHostGrpc(s => s.AddGrpcClient<CallInvokerExtractor>(), Random.Shared.Next(4098, 10000));

private void ConfigureForFunctionsHostGrpc(Func<IServiceCollection, IHttpClientBuilder> configure, int? maxMessageLength = null)
{
int port = 21584; // random enough.
ConfigurationBuilder configBuilder = new();
configBuilder.AddInMemoryCollection(new Dictionary<string, string>()
{
["HOST"] = "localhost",
["PORT"] = port.ToString(),
["grpcMaxMessageLength"] = maxMessageLength?.ToString(),
});

ServiceCollection services = new();
Expand All @@ -55,10 +61,22 @@ private void ConfigureForFunctionsHostGrpc(Func<IServiceCollection, IHttpClientB
Assert.NotNull(extractor.CallInvoker);

IOptionsMonitor<GrpcClientFactoryOptions> monitor = sp.GetService<IOptionsMonitor<GrpcClientFactoryOptions>>();
GrpcClientFactoryOptions options = monitor.Get(builder.Name);
GrpcClientFactoryOptions factoryOptions = monitor.Get(builder.Name);

Assert.Equal(new Uri($"http://localhost:{port}"), options.Address);
Assert.Equal(new Uri($"http://localhost:{port}"), factoryOptions.Address);
Assert.Null(handler);

if (maxMessageLength is int expectedLength)
{
GrpcChannelOptions channelOptions = new();
foreach (Action<GrpcChannelOptions> action in factoryOptions.ChannelOptionsActions)
{
action(channelOptions);
}

Assert.Equal(expectedLength, channelOptions.MaxReceiveMessageSize);
Assert.Equal(expectedLength, channelOptions.MaxSendMessageSize);
}
}

private class CallInvokerExtractor
Expand Down
Loading