Skip to content

ApricotFramework.Grpc

NuGet NuGet NuGet NuGet NuGet CI License

A gRPC hop that keeps the error. A service throws a classified error; its caller catches the same error, with the same kind, code and payload, as though the call had been local.

Everything is opt-in and separately installable — errors, discovery, credentials — so a client takes what it needs and nothing else. Only the server package requires ASP.NET Core.

Install

dotnet add package ApricotFramework.Grpc.Server                    # the server
dotnet add package ApricotFramework.Grpc.Client                    # the caller
dotnet add package ApricotFramework.Grpc.Client.DiscoveryClient    # ...addressed by service name
dotnet add package ApricotFramework.Grpc.Client.Authentication     # ...presenting its own token

Usage

// Server. AddGrpc stays gRPC's own; this says what happens when a call fails, asking the same
// exception mappers that already answer this service's HTTP requests.
builder.Services.AddGrpc();
builder.Services.AddGrpcErrorHandling();
// Anywhere in a service method. Nothing catches this; the caller receives it.
throw Err.NotFound("ORDER_NOT_FOUND", $"no order with id '{id}'",
    new Dictionary<string, object?> { ["orderId"] = id }).AsException();
// Caller. Each line is a capability, and any of them can be left out.
builder.Services.AddGrpcClientsCore(builder.Configuration);
builder.Services.AddGrpcErrorMapping();

builder.Services
    .AddDiscoveredGrpcClient<Orders.OrdersClient>("orders")
    .AddGrpcCallCredentials(credentials => credentials.Scopes = ["orders.read"]);
try
{
    var order = await client.GetOrderAsync(new GetOrderRequest { Id = id });
}
catch (ErrorDefinitionException failure) when (failure.HasKind(ErrorKinds.NotFound))
{
    // The kind, the code and the payload are the ones the orders service threw.
}

Note. Errors travel in a trailer, and a trailer too large for the peer fails the whole response. They are therefore trimmed to a byte budget — payloads first, then the errors after the first — with a flag on the wire saying so. The server's log always holds the full set.

The wire contract is apricot.errors.v1, packed into the contract package as protos/apricot/errors/v1/errors.proto so a service in another language can speak it.

Full documentation at projectapricot.dev/docs/grpc.

About

gRPC error handling for .NET: a service's classified errors survive the hop with their payloads intact, plus opt-in discovery and client credentials for the calls it makes.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages