Skip to content

Commit

Permalink
Merge pull request grpc#2815 from jtattermusch/introduce_call_options
Browse files Browse the repository at this point in the history
Introduce client-side CallOptions
  • Loading branch information
jtattermusch committed Aug 6, 2015
2 parents 7098b1b + 3cd76d6 commit 2ba9e5d
Show file tree
Hide file tree
Showing 15 changed files with 472 additions and 224 deletions.
82 changes: 70 additions & 12 deletions src/compiler/csharp_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) {
out->Indent();
out->Print("$methodtype$,\n", "methodtype",
GetCSharpMethodType(GetMethodType(method)));
out->Print("$servicenamefield$,\n", "servicenamefield",
GetServiceNameFieldName());
out->Print("\"$methodname$\",\n", "methodname", method->name());
out->Print("$requestmarshaller$,\n", "requestmarshaller",
GetMarshallerFieldName(method->input_type()));
Expand Down Expand Up @@ -273,6 +275,13 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));

// overload taking CallOptions as a param
out->Print(
"$response$ $methodname$($request$ request, CallOptions options);\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
}

std::string method_name = method->name();
Expand All @@ -284,6 +293,13 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));

// overload taking CallOptions as a param
out->Print(
"$returntype$ $methodname$($request_maybe$CallOptions options);\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
}
out->Outdent();
out->Print("}\n");
Expand Down Expand Up @@ -340,10 +356,23 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
GetClassName(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers, deadline);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request, cancellationToken);\n");
out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n",
"methodfield", GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request);\n");
out->Outdent();
out->Print("}\n");

// overload taking CallOptions as a param
out->Print(
"public $response$ $methodname$($request$ request, CallOptions options)\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, options);\n",
"methodfield", GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request);\n");
out->Outdent();
out->Print("}\n");
}
Expand All @@ -359,26 +388,55 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers, deadline);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method));
out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n",
"methodfield", GetMethodFieldName(method));
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
out->Print("return Calls.AsyncUnaryCall(call, request, cancellationToken);\n");
out->Print("return Calls.AsyncUnaryCall(call, request);\n");
break;
case METHODTYPE_CLIENT_STREAMING:
out->Print("return Calls.AsyncClientStreamingCall(call, cancellationToken);\n");
out->Print("return Calls.AsyncClientStreamingCall(call);\n");
break;
case METHODTYPE_SERVER_STREAMING:
out->Print(
"return Calls.AsyncServerStreamingCall(call, request, cancellationToken);\n");
"return Calls.AsyncServerStreamingCall(call, request);\n");
break;
case METHODTYPE_BIDI_STREAMING:
out->Print("return Calls.AsyncDuplexStreamingCall(call, cancellationToken);\n");
out->Print("return Calls.AsyncDuplexStreamingCall(call);\n");
break;
default:
GOOGLE_LOG(FATAL)<< "Can't get here.";
}
}
out->Outdent();
out->Print("}\n");

// overload taking CallOptions as a param
out->Print(
"public $returntype$ $methodname$($request_maybe$CallOptions options)\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, options);\n",
"methodfield", GetMethodFieldName(method));
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
out->Print("return Calls.AsyncUnaryCall(call, request);\n");
break;
case METHODTYPE_CLIENT_STREAMING:
out->Print("return Calls.AsyncClientStreamingCall(call);\n");
break;
case METHODTYPE_SERVER_STREAMING:
out->Print(
"return Calls.AsyncServerStreamingCall(call, request);\n");
break;
case METHODTYPE_BIDI_STREAMING:
out->Print("return Calls.AsyncDuplexStreamingCall(call);\n");
break;
default:
GOOGLE_LOG(FATAL)<< "Can't get here.";
}
out->Outdent();
out->Print("}\n");
}
Expand Down
74 changes: 38 additions & 36 deletions src/csharp/Grpc.Core.Tests/ClientServerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,26 @@ namespace Grpc.Core.Tests
public class ClientServerTest
{
const string Host = "127.0.0.1";
const string ServiceName = "/tests.Test";
const string ServiceName = "tests.Test";

static readonly Method<string, string> EchoMethod = new Method<string, string>(
MethodType.Unary,
"/tests.Test/Echo",
ServiceName,
"Echo",
Marshallers.StringMarshaller,
Marshallers.StringMarshaller);

static readonly Method<string, string> ConcatAndEchoMethod = new Method<string, string>(
MethodType.ClientStreaming,
"/tests.Test/ConcatAndEcho",
ServiceName,
"ConcatAndEcho",
Marshallers.StringMarshaller,
Marshallers.StringMarshaller);

static readonly Method<string, string> NonexistentMethod = new Method<string, string>(
MethodType.Unary,
"/tests.Test/NonexistentMethod",
ServiceName,
"NonexistentMethod",
Marshallers.StringMarshaller,
Marshallers.StringMarshaller);

Expand Down Expand Up @@ -102,17 +105,17 @@ public void CleanupClass()
[Test]
public void UnaryCall()
{
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
Assert.AreEqual("ABC", Calls.BlockingUnaryCall(internalCall, "ABC", CancellationToken.None));
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
Assert.AreEqual("ABC", Calls.BlockingUnaryCall(callDetails, "ABC"));
}

[Test]
public void UnaryCall_ServerHandlerThrows()
{
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try
{
Calls.BlockingUnaryCall(internalCall, "THROW", CancellationToken.None);
Calls.BlockingUnaryCall(callDetails, "THROW");
Assert.Fail();
}
catch (RpcException e)
Expand All @@ -124,10 +127,10 @@ public void UnaryCall_ServerHandlerThrows()
[Test]
public void UnaryCall_ServerHandlerThrowsRpcException()
{
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try
{
Calls.BlockingUnaryCall(internalCall, "THROW_UNAUTHENTICATED", CancellationToken.None);
Calls.BlockingUnaryCall(callDetails, "THROW_UNAUTHENTICATED");
Assert.Fail();
}
catch (RpcException e)
Expand All @@ -139,10 +142,10 @@ public void UnaryCall_ServerHandlerThrowsRpcException()
[Test]
public void UnaryCall_ServerHandlerSetsStatus()
{
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try
{
Calls.BlockingUnaryCall(internalCall, "SET_UNAUTHENTICATED", CancellationToken.None);
Calls.BlockingUnaryCall(callDetails, "SET_UNAUTHENTICATED");
Assert.Fail();
}
catch (RpcException e)
Expand All @@ -152,20 +155,20 @@ public void UnaryCall_ServerHandlerSetsStatus()
}

[Test]
public void AsyncUnaryCall()
public async Task AsyncUnaryCall()
{
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
var result = Calls.AsyncUnaryCall(internalCall, "ABC", CancellationToken.None).ResponseAsync.Result;
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
var result = await Calls.AsyncUnaryCall(callDetails, "ABC");
Assert.AreEqual("ABC", result);
}

[Test]
public async Task AsyncUnaryCall_ServerHandlerThrows()
{
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try
{
await Calls.AsyncUnaryCall(internalCall, "THROW", CancellationToken.None);
await Calls.AsyncUnaryCall(callDetails, "THROW");
Assert.Fail();
}
catch (RpcException e)
Expand All @@ -177,8 +180,8 @@ public async Task AsyncUnaryCall_ServerHandlerThrows()
[Test]
public async Task ClientStreamingCall()
{
var internalCall = new Call<string, string>(ServiceName, ConcatAndEchoMethod, channel, Metadata.Empty);
var call = Calls.AsyncClientStreamingCall(internalCall, CancellationToken.None);
var callDetails = new CallInvocationDetails<string, string>(channel, ConcatAndEchoMethod, new CallOptions());
var call = Calls.AsyncClientStreamingCall(callDetails);

await call.RequestStream.WriteAll(new string[] { "A", "B", "C" });
Assert.AreEqual("ABC", await call.ResponseAsync);
Expand All @@ -187,10 +190,9 @@ public async Task ClientStreamingCall()
[Test]
public async Task ClientStreamingCall_CancelAfterBegin()
{
var internalCall = new Call<string, string>(ServiceName, ConcatAndEchoMethod, channel, Metadata.Empty);

var cts = new CancellationTokenSource();
var call = Calls.AsyncClientStreamingCall(internalCall, cts.Token);
var callDetails = new CallInvocationDetails<string, string>(channel, ConcatAndEchoMethod, new CallOptions(cancellationToken: cts.Token));
var call = Calls.AsyncClientStreamingCall(callDetails);

// TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it.
await Task.Delay(1000);
Expand All @@ -214,8 +216,8 @@ public void AsyncUnaryCall_EchoMetadata()
new Metadata.Entry("ascii-header", "abcdefg"),
new Metadata.Entry("binary-header-bin", new byte[] { 1, 2, 3, 0, 0xff }),
};
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, headers);
var call = Calls.AsyncUnaryCall(internalCall, "ABC", CancellationToken.None);
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions(headers: headers));
var call = Calls.AsyncUnaryCall(callDetails, "ABC");

Assert.AreEqual("ABC", call.ResponseAsync.Result);

Expand All @@ -235,25 +237,25 @@ public void UnaryCall_DisposedChannel()
{
channel.Dispose();

var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
Assert.Throws(typeof(ObjectDisposedException), () => Calls.BlockingUnaryCall(internalCall, "ABC", CancellationToken.None));
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
Assert.Throws(typeof(ObjectDisposedException), () => Calls.BlockingUnaryCall(callDetails, "ABC"));
}

[Test]
public void UnaryCallPerformance()
{
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
BenchmarkUtil.RunBenchmark(100, 100,
() => { Calls.BlockingUnaryCall(internalCall, "ABC", default(CancellationToken)); });
() => { Calls.BlockingUnaryCall(callDetails, "ABC"); });
}

[Test]
public void UnknownMethodHandler()
{
var internalCall = new Call<string, string>(ServiceName, NonexistentMethod, channel, Metadata.Empty);
var callDetails = new CallInvocationDetails<string, string>(channel, NonexistentMethod, new CallOptions());
try
{
Calls.BlockingUnaryCall(internalCall, "ABC", default(CancellationToken));
Calls.BlockingUnaryCall(callDetails, "ABC");
Assert.Fail();
}
catch (RpcException e)
Expand All @@ -265,16 +267,16 @@ public void UnknownMethodHandler()
[Test]
public void UserAgentStringPresent()
{
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
string userAgent = Calls.BlockingUnaryCall(internalCall, "RETURN-USER-AGENT", CancellationToken.None);
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
string userAgent = Calls.BlockingUnaryCall(callDetails, "RETURN-USER-AGENT");
Assert.IsTrue(userAgent.StartsWith("grpc-csharp/"));
}

[Test]
public void PeerInfoPresent()
{
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
string peer = Calls.BlockingUnaryCall(internalCall, "RETURN-PEER", CancellationToken.None);
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
string peer = Calls.BlockingUnaryCall(callDetails, "RETURN-PEER");
Assert.IsTrue(peer.Contains(Host));
}

Expand All @@ -286,8 +288,8 @@ public async Task Channel_WaitForStateChangedAsync()

var stateChangedTask = channel.WaitForStateChangedAsync(channel.State);

var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
await Calls.AsyncUnaryCall(internalCall, "abc", CancellationToken.None);
var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
await Calls.AsyncUnaryCall(callDetails, "abc");

await stateChangedTask;
Assert.AreEqual(ChannelState.Ready, channel.State);
Expand Down
Loading

0 comments on commit 2ba9e5d

Please sign in to comment.