public void AddFailedOperation <T>(string name, DateTime completionTime, ProtoStatus error) where T : IMessage <T> { var operation = new Operation { Done = true, Name = name, Error = error }; operations.Add(name, Tuple.Create(completionTime, operation)); }
private static Error?ConvertError(Status error) { if (error == null) { return(null); } return(new Error(error.Code, error.Message, error.Details?.ToArray() ?? Array.Empty <object>())); }
private static Operation <StringValue> ForError(string name, ProtoStatus error, OperationsClient client) { var operation = new Operation { Done = true, Name = name, Error = error }; return(new Operation <StringValue>(operation, client)); }
private Abstractions.Status ToStatus(Google.Rpc.Status status) { if (status == null) { return(null); } return(new Abstractions.Status { Code = status.Code, Message = status.Message, }); }
private static void FailWithDetails(StatusCode code, string topLevelMessage, IEnumerable <IMessage> details) { var status = new Google.Rpc.Status { Code = (int)code, Message = topLevelMessage, }; status.Details.AddRange(details.Select(d => Any.Pack(d))); var failureMetadata = new Metadata(); failureMetadata.Add(StatusDetailsTrailerName, status.ToByteArray()); throw new RpcException( new Status(code, topLevelMessage), failureMetadata); }
public static RpcException ToException(this Google.Rpc.Status status) => new RpcException( new Status((StatusCode)status.Code, status.Message), new Metadata { status });
public static T?GetDetail <T>(this Google.Rpc.Status status) where T : class, IMessage <T>, new() => status.Details?.GetMessage <T>();
/// <summary> /// Adds a rich error model to the headers. /// </summary> public static void Add(this Metadata metadata, Google.Rpc.Status status) => metadata.Add(RichStatusHeaderKey, status);
public async Task InvokeMethodAsync_CanInvokeRawMethodWithResponse_HttpServerReturnsNonSuccessResponse() { var client = new MockClient(); var data = new Response() { Name = "Look, I was invoked!" }; var invokeResponse = new InvokeResponse { Data = TypeConverters.ToAny(data) }; var response = client.Call <InvokeResponse>() .SetResponse(invokeResponse) .AddHeader("dapr-status-header", "200") .Build(); var trailers = new Metadata(); const string grpcErrorInfoReason = "Insufficient permissions"; const int grpcErrorInfoDetailHttpCode = 500; const string grpcErrorInfoDetailHttpErrorMsg = "no permissions"; int grpcStatusCode = Convert.ToInt32(StatusCode.PermissionDenied); const string grpcStatusMessage = "Bad permissions"; var details = new Google.Rpc.Status { Code = grpcStatusCode, Message = grpcStatusMessage, }; var errorInfo = new Google.Rpc.ErrorInfo { Reason = grpcErrorInfoReason, Domain = "dapr.io", }; errorInfo.Metadata.Add("http.code", grpcErrorInfoDetailHttpCode.ToString()); errorInfo.Metadata.Add("http.error_message", grpcErrorInfoDetailHttpErrorMsg); details.Details.Add(Google.Protobuf.WellKnownTypes.Any.Pack(errorInfo)); var entry = new Metadata.Entry("grpc-status-details-bin", Google.Protobuf.MessageExtensions.ToByteArray(details)); trailers.Add(entry); const string rpcExceptionMessage = "No access to app"; const StatusCode rpcStatusCode = StatusCode.PermissionDenied; const string rpcStatusDetail = "Insufficient permissions"; var rpcException = new RpcException(new Status(rpcStatusCode, rpcStatusDetail), trailers, rpcExceptionMessage); // Setup the mock client to throw an Rpc Exception with the expected details info client.Mock .Setup(m => m.InvokeServiceAsync(It.IsAny <Autogen.Grpc.v1.InvokeServiceRequest>(), It.IsAny <CallOptions>())) .Throws(rpcException); try { var body = new Request() { RequestParameter = "Hello " }; var bytes = JsonSerializer.SerializeToUtf8Bytes(body); await client.DaprClient.InvokeMethodRawAsync("test", "testMethod", bytes); Assert.False(true); } catch (InvocationException ex) { ex.Message.Should().Be("Exception while invoking testMethod on appId:test"); ex.InnerException.Message.Should().Be(rpcExceptionMessage); ex.Response.GrpcStatusInfo.Should().BeNull(); Encoding.UTF8.GetString(ex.Response.Body).Should().Be(grpcErrorInfoDetailHttpErrorMsg); ex.Response.HttpStatusCode.Should().Be(grpcErrorInfoDetailHttpCode); } }
private async Task Receive(ChannelWriter <BatchAppendResp> writer, ClaimsPrincipal user, bool requiresLeader, CancellationToken cancellationToken) { var pendingWrites = new ConcurrentDictionary <Guid, ClientWriteRequest>(); try { await foreach (var request in _requestStream.ReadAllAsync(cancellationToken)) { try { var correlationId = Uuid.FromDto(request.CorrelationId).ToGuid(); if (request.Options != null) { TimeSpan timeout = Min(GetRequestedTimeout(request.Options), _writeTimeout); if (!await _authorizationProvider.CheckAccessAsync(user, WriteOperation.WithParameter( Plugins.Authorization.Operations.Streams.Parameters.StreamId( request.Options.StreamIdentifier)), cancellationToken).ConfigureAwait(false)) { await writer.WriteAsync(new BatchAppendResp { CorrelationId = request.CorrelationId, StreamIdentifier = request.Options.StreamIdentifier, Error = Status.AccessDenied }, cancellationToken).ConfigureAwait(false); continue; } if (request.Options.StreamIdentifier == null) { await writer.WriteAsync(new BatchAppendResp { CorrelationId = request.CorrelationId, StreamIdentifier = request.Options.StreamIdentifier, Error = Status.BadRequest( $"Required field {nameof(request.Options.StreamIdentifier)} not set.") }, cancellationToken).ConfigureAwait(false); continue; } if (Max(timeout, TimeSpan.Zero) == TimeSpan.Zero) { await writer.WriteAsync(new BatchAppendResp { CorrelationId = request.CorrelationId, StreamIdentifier = request.Options.StreamIdentifier, Error = Status.Timeout }, cancellationToken).ConfigureAwait(false); continue; } pendingWrites.AddOrUpdate(correlationId, c => FromOptions(c, request.Options, timeout, cancellationToken), (_, writeRequest) => writeRequest); } if (!pendingWrites.TryGetValue(correlationId, out var clientWriteRequest)) { continue; } clientWriteRequest.AddEvents(request.ProposedMessages.Select(FromProposedMessage)); if (clientWriteRequest.Size > _maxAppendSize) { pendingWrites.TryRemove(correlationId, out _); await writer.WriteAsync(new BatchAppendResp { CorrelationId = request.CorrelationId, StreamIdentifier = clientWriteRequest.StreamId, Error = Status.MaximumAppendSizeExceeded((uint)_maxAppendSize) }, cancellationToken).ConfigureAwait(false); } if (!request.IsFinal) { continue; } if (!pendingWrites.TryRemove(correlationId, out _)) { continue; } Interlocked.Increment(ref _pending); _publisher.Publish(ToInternalMessage(clientWriteRequest, new CallbackEnvelope(message => { try { writer.TryWrite(ConvertMessage(message)); } catch (Exception ex) { writer.TryComplete(ex); } }), requiresLeader, user, cancellationToken)); BatchAppendResp ConvertMessage(Message message) { var batchAppendResp = message switch { ClientMessage.NotHandled notHandled => new BatchAppendResp { Error = new Status { Details = Any.Pack(new Empty()), Message = (notHandled.Reason, notHandled.AdditionalInfo) switch { (NotHandledReason.NotReady, _) => "Server Is Not Ready", (NotHandledReason.TooBusy, _) => "Server Is Busy", (NotHandledReason.NotLeader or NotHandledReason.IsReadOnly, LeaderInfo leaderInfo) => throw RpcExceptions.LeaderInfo(leaderInfo.HttpAddress, leaderInfo.HttpPort), (NotHandledReason.NotLeader or NotHandledReason.IsReadOnly, _) => "No leader info available in response", _ => $"Unknown {nameof(NotHandledReason)} ({(int)notHandled.Reason})" } } }, ClientMessage.WriteEventsCompleted completed => completed.Result switch { OperationResult.Success => new BatchAppendResp { Success = BatchAppendResp.Types.Success.Completed(completed.CommitPosition, completed.PreparePosition, completed.LastEventNumber), }, OperationResult.WrongExpectedVersion => new BatchAppendResp { Error = Status.WrongExpectedVersion( StreamRevision.FromInt64(completed.CurrentVersion), clientWriteRequest.ExpectedVersion) }, OperationResult.AccessDenied => new BatchAppendResp { Error = Status.AccessDenied }, OperationResult.StreamDeleted => new BatchAppendResp { Error = Status.StreamDeleted(clientWriteRequest.StreamId) }, OperationResult.CommitTimeout or OperationResult.ForwardTimeout or OperationResult.PrepareTimeout => new BatchAppendResp { Error = Status.Timeout }, _ => new BatchAppendResp { Error = Status.Unknown } }, _ => new BatchAppendResp { Error = new Status { Details = Any.Pack(new Empty()), Message = $"Envelope callback expected either {nameof(ClientMessage.WriteEventsCompleted)} or {nameof(ClientMessage.NotHandled)}, received {message.GetType().Name} instead" } } }; batchAppendResp.CorrelationId = Uuid.FromGuid(correlationId).ToDto(); batchAppendResp.StreamIdentifier = new StreamIdentifier { StreamName = ByteString.CopyFromUtf8(clientWriteRequest.StreamId) }; return(batchAppendResp); } } catch (Exception ex) { await writer.WriteAsync(new BatchAppendResp { CorrelationId = request.CorrelationId, StreamIdentifier = request.Options.StreamIdentifier, Error = Status.BadRequest(ex.Message) }, cancellationToken).ConfigureAwait(false); } }