Skip to content

Commit

Permalink
Add additional Protobuf examples (#3787)
Browse files Browse the repository at this point in the history
  • Loading branch information
pepone authored Nov 22, 2023
1 parent 5b2b6f1 commit 64db293
Show file tree
Hide file tree
Showing 111 changed files with 2,789 additions and 34 deletions.
17 changes: 17 additions & 0 deletions examples/protobuf/Deadline/Client/Client.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<!-- Copy the PDBs from the NuGet packages to get file names and line numbers in stack traces. -->
<CopyDebugSymbolFilesFromPackages>true</CopyDebugSymbolFilesFromPackages>
</PropertyGroup>
<ItemGroup>
<ProtoFile Include="../proto/greeter.proto" />
<PackageReference Include="IceRpc.Protobuf.Tools" Version="$(Version)" PrivateAssets="All" />
<PackageReference Include="IceRpc.Protobuf" Version="$(Version)" />
<PackageReference Include="IceRpc.Deadline" Version="$(Version)" />
</ItemGroup>
</Project>
35 changes: 35 additions & 0 deletions examples/protobuf/Deadline/Client/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) ZeroC, Inc.

using IceRpc;
using IceRpc.Features;
using VisitorCenter;

await using var connection = new ClientConnection(new Uri("icerpc://localhost"));

// Create an invocation pipeline, that uses the deadline interceptor and has a default timeout of 500 ms.
Pipeline pipeline = new Pipeline()
.UseDeadline(defaultTimeout: TimeSpan.FromMilliseconds(500))
.Into(connection);

var greeter = new GreeterClient(pipeline);

// In this example, the implementation of the Greet operation takes about 1 second, and the deadline
// interceptor makes sure the invocation throws TimeoutException after 500 ms.
try
{
_ = await greeter.GreetAsync(new GreetRequest { Name = Environment.UserName });
}
catch (TimeoutException exception)
{
Console.WriteLine(exception.Message);
}

// The next invocation utilizes the deadline feature to customize the invocation deadline. This ensures that the
// invocation is not canceled before the SlowChatbot sends a response.
var features = new FeatureCollection();
features.Set<IDeadlineFeature>(DeadlineFeature.FromTimeout(TimeSpan.FromSeconds(10)));

GreetResponse response = await greeter.GreetAsync(new GreetRequest { Name = Environment.UserName }, features);
Console.WriteLine(response.Greeting);

await connection.ShutdownAsync();
36 changes: 36 additions & 0 deletions examples/protobuf/Deadline/Deadline.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33122.133
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{BBF1199A-46A4-4AE9-AFFE-4D8DD59EB874}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{527EEA4D-77B9-4252-A2CD-C641A25CAD53}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FBDAF448-665A-4595-98D3-4538C56A666D}"
ProjectSection(SolutionItems) = preProject
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BBF1199A-46A4-4AE9-AFFE-4D8DD59EB874}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BBF1199A-46A4-4AE9-AFFE-4D8DD59EB874}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BBF1199A-46A4-4AE9-AFFE-4D8DD59EB874}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BBF1199A-46A4-4AE9-AFFE-4D8DD59EB874}.Release|Any CPU.Build.0 = Release|Any CPU
{527EEA4D-77B9-4252-A2CD-C641A25CAD53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{527EEA4D-77B9-4252-A2CD-C641A25CAD53}.Debug|Any CPU.Build.0 = Debug|Any CPU
{527EEA4D-77B9-4252-A2CD-C641A25CAD53}.Release|Any CPU.ActiveCfg = Release|Any CPU
{527EEA4D-77B9-4252-A2CD-C641A25CAD53}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0B36F1E1-0592-4A15-9981-67BC4A653EC4}
EndGlobalSection
EndGlobal
25 changes: 25 additions & 0 deletions examples/protobuf/Deadline/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Deadline

The Deadline example illustrates how to use the deadline interceptor to add an invocation deadline and shows
how invocations that exceed the deadline fail with TimeoutException. It also demonstrates how the IDeadlineFeature
can be used to set the deadline for an invocation.

You can build the client and server applications with:

``` shell
dotnet build
```

First start the Server program:

```shell
cd Server
dotnet run
```

In a separate window, start the Client program:

```shell
cd Client
dotnet run
```
12 changes: 12 additions & 0 deletions examples/protobuf/Deadline/Server/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) ZeroC, Inc.

using DeadlineServer;
using IceRpc;

// Create a server that dispatches all requests to the same service, an instance of SlowChatbot.
await using var server = new Server(new SlowChatbot());
server.Listen();

// Wait until the console receives a Ctrl+C.
await CancelKeyPressed;
await server.ShutdownAsync();
18 changes: 18 additions & 0 deletions examples/protobuf/Deadline/Server/Server.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<!-- Copy the PDBs from the NuGet packages to get file names and line numbers in stack traces. -->
<CopyDebugSymbolFilesFromPackages>true</CopyDebugSymbolFilesFromPackages>
</PropertyGroup>
<ItemGroup>
<ProtoFile Include="../proto/greeter.proto" />
<PackageReference Include="IceRpc.Protobuf.Tools" Version="$(Version)" PrivateAssets="All" />
<PackageReference Include="IceRpc.Protobuf" Version="$(Version)" />
<PackageReference Include="IceRpc.Deadline" Version="$(Version)" />
<Compile Include="../../../common/Program.CancelKeyPressed.cs" Link="Program.CancelKeyPressed.cs" />
</ItemGroup>
</Project>
31 changes: 31 additions & 0 deletions examples/protobuf/Deadline/Server/SlowChatbot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) ZeroC, Inc.

using IceRpc.Features;
using IceRpc.Protobuf;
using VisitorCenter;

namespace DeadlineServer;

/// <summary>A SlowChatbot is an IceRPC service that implements Protobuf service 'Greeter'.</summary>
/// <remarks>The slow chatbot always delays its responses by 1 second.</remarks>
[ProtobufService]
internal partial class SlowChatbot : IGreeterService
{
public async ValueTask<GreetResponse> GreetAsync(
GreetRequest message,
IFeatureCollection features,
CancellationToken cancellationToken)
{
Console.WriteLine($"Dispatching Greet request {{ name = '{message.Name}' }}");
try
{
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
}
catch (OperationCanceledException exception)
{
Console.WriteLine($"Dispatch canceled: {exception.Message}");
throw;
}
return new GreetResponse { Greeting = $"Hello, {message.Name}!" };
}
}
22 changes: 22 additions & 0 deletions examples/protobuf/Deadline/proto/greeter.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) ZeroC, Inc.

syntax = "proto3";

package visitor_center;
option csharp_namespace = "VisitorCenter";

// Represents a simple greeter.
service Greeter {
// Creates a personalized greeting.
rpc Greet (GreetRequest) returns (GreetResponse);
}

// The request contains the name of the person to greet.
message GreetRequest {
string name = 1;
}

// The response contains the greeting.
message GreetResponse {
string greeting = 1;
}
9 changes: 4 additions & 5 deletions examples/protobuf/Greeter/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# GreeterProtobuf
# Greeter

The GreeterProtobuf example is a variation of the [Greeter](Greeter) example. It sends the same request and receives
the same response, except it uses [Protobuf][protobuf] instead of Slice to define the contract between the client and
the server.
The Greeter example illustrates how to send a request and wait for the response.

You can build the client and server applications with:

Expand All @@ -24,4 +22,5 @@ cd Client
dotnet run
```

[protobuf]: https://protobuf.dev/getting-started/csharptutorial/
> This is a concise example with minimal code. If you are looking for a more realistic example, see the
> [Logger](../Logger/README.md) example.
2 changes: 1 addition & 1 deletion examples/protobuf/Greeter/Server/Chatbot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using IceRpc.Protobuf;
using VisitorCenter;

namespace GreeterProtobufServer;
namespace GreeterServer;

/// <summary>A Chatbot is an IceRPC service that implements Protobuf service 'Greeter'.</summary>
[ProtobufService]
Expand Down
2 changes: 1 addition & 1 deletion examples/protobuf/Greeter/Server/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) ZeroC, Inc.

using GreeterProtobufServer;
using GreeterServer;
using IceRpc;

// Create a server that dispatches all requests to the same service, an instance of Chatbot.
Expand Down
2 changes: 1 addition & 1 deletion examples/protobuf/Greeter/proto/greeter.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ syntax = "proto3";
package visitor_center;
option csharp_namespace = "VisitorCenter";

// The protobuf equivalent of Slice interface Greeter in the Greeter example.
// Represents a simple greeter.
service Greeter {
// Creates a personalized greeting.
rpc Greet (GreetRequest) returns (GreetResponse);
Expand Down
19 changes: 19 additions & 0 deletions examples/protobuf/Logger/Client/Client.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<!-- Copy the PDBs from the NuGet packages to get file names and line numbers in stack traces. -->
<CopyDebugSymbolFilesFromPackages>true</CopyDebugSymbolFilesFromPackages>
</PropertyGroup>
<ItemGroup>
<ProtoFile Include="../proto/greeter.proto" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.*" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.*" />
<PackageReference Include="IceRpc.Protobuf.Tools" Version="$(Version)" PrivateAssets="All" />
<PackageReference Include="IceRpc.Protobuf" Version="$(Version)" />
<PackageReference Include="IceRpc.Logger" Version="$(Version)" />
</ItemGroup>
</Project>
32 changes: 32 additions & 0 deletions examples/protobuf/Logger/Client/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) ZeroC, Inc.

using IceRpc;
using Microsoft.Extensions.Logging;
using VisitorCenter;

// Create a simple console logger factory and configure the log level for category IceRpc.
using ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
builder
.AddSimpleConsole()
.AddFilter("IceRpc", LogLevel.Debug));

// Create a client connection that logs messages to a logger with category IceRpc.ClientConnection.
await using var connection = new ClientConnection(
new Uri("icerpc://localhost"),
logger: loggerFactory.CreateLogger<ClientConnection>());

// Create an invocation pipeline and install the logger interceptor. This interceptor logs invocations using category
// `IceRpc.Logger.LoggerInterceptor`.
Pipeline pipeline = new Pipeline()
.UseLogger(loggerFactory)
.Into(connection);

// Create a greeter client with this invocation pipeline.
var greeter = new GreeterClient(pipeline);

var request = new GreetRequest { Name = Environment.UserName };
GreetResponse response = await greeter.GreetAsync(request);

Console.WriteLine(response.Greeting);

await connection.ShutdownAsync();
36 changes: 36 additions & 0 deletions examples/protobuf/Logger/Logger.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33122.133
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{BBF1199A-46A4-4AE9-AFFE-4D8DD59EB874}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{527EEA4D-77B9-4252-A2CD-C641A25CAD53}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FBDAF448-665A-4595-98D3-4538C56A666D}"
ProjectSection(SolutionItems) = preProject
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BBF1199A-46A4-4AE9-AFFE-4D8DD59EB874}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BBF1199A-46A4-4AE9-AFFE-4D8DD59EB874}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BBF1199A-46A4-4AE9-AFFE-4D8DD59EB874}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BBF1199A-46A4-4AE9-AFFE-4D8DD59EB874}.Release|Any CPU.Build.0 = Release|Any CPU
{527EEA4D-77B9-4252-A2CD-C641A25CAD53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{527EEA4D-77B9-4252-A2CD-C641A25CAD53}.Debug|Any CPU.Build.0 = Debug|Any CPU
{527EEA4D-77B9-4252-A2CD-C641A25CAD53}.Release|Any CPU.ActiveCfg = Release|Any CPU
{527EEA4D-77B9-4252-A2CD-C641A25CAD53}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0B36F1E1-0592-4A15-9981-67BC4A653EC4}
EndGlobalSection
EndGlobal
33 changes: 33 additions & 0 deletions examples/protobuf/Logger/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# GreeterLog

This example augments [Greeter](../Greeter/README.md) with logging.

The client is a more typical client than Greeter's client because it creates an invocation pipeline and installs an
interceptor in this pipeline (the logger interceptor).

And the server is a more typical server than Greeter's server because it creates a router (dispatch pipeline) and
installs a middleware in this pipeline (the logger middleware).

You can build the client and server applications with:

``` shell
dotnet build
```

First start the Server program:

```shell
cd Server
dotnet run
```

In a separate window, start the Client program:

```shell
cd Client
dotnet run
```

You will notice the two logger categories in the output. The client shows log messages for `IceRpc.ClientConnection` and
`IceRpc.Logger.LoggerInterceptor`, while the server shows log messages for `IceRpc.Server` and
`IceRpc.Logger.LoggerMiddleware`.
21 changes: 21 additions & 0 deletions examples/protobuf/Logger/Server/Chatbot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) ZeroC, Inc.

using IceRpc.Features;
using IceRpc.Protobuf;
using VisitorCenter;

namespace GreeterLogServer;

/// <summary>A Chatbot is an IceRPC service that implements Protobuf service 'Greeter'.</summary>
[ProtobufService]
internal partial class Chatbot : IGreeterService
{
public ValueTask<GreetResponse> GreetAsync(
GreetRequest message,
IFeatureCollection features,
CancellationToken cancellationToken)
{
Console.WriteLine($"Dispatching Greet request {{ name = '{message.Name}' }}");
return new(new GreetResponse { Greeting = $"Hello, {message.Name}!" });
}
}
Loading

0 comments on commit 64db293

Please sign in to comment.