Example #1
0
            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));
            }
Example #2
0
        private static Error?ConvertError(Status error)
        {
            if (error == null)
            {
                return(null);
            }

            return(new Error(error.Code,
                             error.Message,
                             error.Details?.ToArray() ?? Array.Empty <object>()));
        }
Example #3
0
        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,
            });
        }
Example #5
0
        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);
        }
Example #6
0
 public static RpcException ToException(this Google.Rpc.Status status)
 => new RpcException(
     new Status((StatusCode)status.Code, status.Message),
     new Metadata {
     status
 });
Example #7
0
 public static T?GetDetail <T>(this Google.Rpc.Status status)
     where T : class, IMessage <T>, new() => status.Details?.GetMessage <T>();
Example #8
0
 /// <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);
Example #9
0
        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);
            }
        }
Example #10
0
            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);
                        }
                    }