Пример #1
0
        private TcpPackage WrapNotHandled(ClientMessage.NotHandled msg)
        {
            var dto = new TcpClientMessageDto.NotHandled(msg.Reason,
                                                         msg.AdditionalInfo == null ? null : msg.AdditionalInfo.SerializeToArray());

            return(new TcpPackage(TcpCommand.NotHandled, msg.CorrelationId, dto.Serialize()));
        }
Пример #2
0
        private static ResponseConfiguration HandleNotHandled(Uri requestedUri, ClientMessage.NotHandled notHandled)
        {
            switch (notHandled.Reason)
            {
            case TcpClientMessageDto.NotHandled.NotHandledReason.NotReady:
                return(ServiceUnavailable("Server Is Not Ready"));

            case TcpClientMessageDto.NotHandled.NotHandledReason.TooBusy:
                return(ServiceUnavailable("Server Is Too Busy"));

            case TcpClientMessageDto.NotHandled.NotHandledReason.NotLeader: {
                var leaderInfo = notHandled.AdditionalInfo as TcpClientMessageDto.NotHandled.LeaderInfo;
                if (leaderInfo == null)
                {
                    return(InternalServerError("No leader info available in response"));
                }
                return(TemporaryRedirect(requestedUri, leaderInfo.HttpAddress, leaderInfo.HttpPort));
            }

            case TcpClientMessageDto.NotHandled.NotHandledReason.IsReadOnly: {
                var leaderInfo = notHandled.AdditionalInfo as TcpClientMessageDto.NotHandled.LeaderInfo;
                if (leaderInfo == null)
                {
                    return(InternalServerError("No leader info available in response"));
                }
                return(DenyRequestBecauseReadOnly(requestedUri, leaderInfo.HttpAddress, leaderInfo.HttpPort));
            }

            default:
                return(InternalServerError(string.Format("Unknown not handled reason: {0}", notHandled.Reason)));
            }
        }
Пример #3
0
        public static bool TryHandleNotHandled(ClientMessage.NotHandled notHandled, out Exception exception)
        {
            exception = null;
            switch (notHandled.Reason)
            {
            case TcpClientMessageDto.NotHandled.NotHandledReason.NotReady:
                exception = ServerNotReady();
                return(true);

            case TcpClientMessageDto.NotHandled.NotHandledReason.TooBusy:
                exception = ServerBusy();
                return(true);

            case TcpClientMessageDto.NotHandled.NotHandledReason.NotMaster:
            case TcpClientMessageDto.NotHandled.NotHandledReason.IsReadOnly:
                switch (notHandled.AdditionalInfo)
                {
                case TcpClientMessageDto.NotHandled.MasterInfo _:
                    return(false);

                default:
                    exception = NoMasterInfo();
                    return(true);
                }

            default:
                return(false);
            }
        }
Пример #4
0
        public static bool TryHandleNotHandled(ClientMessage.NotHandled notHandled, out Exception exception)
        {
            exception = null;
            switch (notHandled.Reason)
            {
            case TcpClientMessageDto.NotHandled.NotHandledReason.NotReady:
                exception = ServerNotReady();
                return(true);

            case TcpClientMessageDto.NotHandled.NotHandledReason.TooBusy:
                exception = ServerBusy();
                return(true);

            case TcpClientMessageDto.NotHandled.NotHandledReason.NotLeader:
            case TcpClientMessageDto.NotHandled.NotHandledReason.IsReadOnly:
                switch (notHandled.AdditionalInfo)
                {
                case TcpClientMessageDto.NotHandled.LeaderInfo leaderInfo:
                    exception = LeaderInfo(new IPEndPoint(IPAddress.Parse(leaderInfo.ExternalHttpAddress),
                                                          leaderInfo.ExternalHttpPort));
                    return(true);

                default:
                    exception = NoLeaderInfo();
                    return(true);
                }

            default:
                return(false);
            }
        }
Пример #5
0
        public static void HandleNotHandled <T>(ClientMessage.NotHandled notHandled, TaskCompletionSource <T> result)
        {
            switch (notHandled.Reason)
            {
            case TcpClientMessageDto.NotHandled.NotHandledReason.NotReady:
                result.TrySetException(ServerNotReady());
                return;

            case TcpClientMessageDto.NotHandled.NotHandledReason.TooBusy:
                result.TrySetException(ServerBusy());
                return;

            case TcpClientMessageDto.NotHandled.NotHandledReason.NotLeader:
            case TcpClientMessageDto.NotHandled.NotHandledReason.IsReadOnly:
                switch (notHandled.AdditionalInfo)
                {
                case TcpClientMessageDto.NotHandled.LeaderInfo _:
                    return;

                default:
                    result.TrySetException(NoLeaderInfo());
                    return;
                }

            default:
                return;
            }
        }
        public NotHandled(ClientMessage.NotHandled source)
        {
            Reason = source.Reason switch {
                ClientMessage.NotHandled.Types.NotHandledReason.NotReady => Types.NotHandledReason.NotReady,
                ClientMessage.NotHandled.Types.NotHandledReason.TooBusy => Types.NotHandledReason.TooBusy,
                ClientMessage.NotHandled.Types.NotHandledReason.NotLeader => Types.NotHandledReason.NotLeader,
                ClientMessage.NotHandled.Types.NotHandledReason.IsReadOnly => Types.NotHandledReason.IsReadOnly,
                _ => throw new ArgumentOutOfRangeException()
            };
            //this is horrible and only for transport compatibility purposes
            if (source.LeaderInfo != null)
            {
                AdditionalInfo = new Types.LeaderInfo(source.LeaderInfo.ExternalTcp, source.LeaderInfo.IsSecure, source.LeaderInfo.Http).ToByteString();
            }
        }

        partial class Types {
Пример #7
0
 private static ResponseConfiguration HandleNotHandled(Uri requestedUri, ClientMessage.NotHandled notHandled)
 {
     switch (notHandled.Reason)
     {
         case TcpClientMessageDto.NotHandled.NotHandledReason.NotReady:
             return ServiceUnavailable("Server Is Not Ready");
         case TcpClientMessageDto.NotHandled.NotHandledReason.TooBusy:
             return ServiceUnavailable("Server Is Too Busy");
         case TcpClientMessageDto.NotHandled.NotHandledReason.NotMaster:
         {
             var masterInfo = notHandled.AdditionalInfo as TcpClientMessageDto.NotHandled.MasterInfo;
             if (masterInfo == null)
                 return InternalServerError("No master info available in response");
             return TemporaryRedirect(requestedUri, masterInfo.ExternalHttpAddress, masterInfo.ExternalHttpPort);
         }
         default:
             return InternalServerError(string.Format("Unknown not handled reason: {0}", notHandled.Reason));
     }
 }
Пример #8
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);
                        }
                    }
Пример #9
0
 public void Handle(ClientMessage.NotHandled message)
 {
     _forwardingProxy.TryForwardReply(
         message.CorrelationId, message,
         (clientCorrId, m) => new ClientMessage.NotHandled(clientCorrId, m.Reason, m.LeaderInfo));
 }
Пример #10
0
 public void Handle(ClientMessage.NotHandled message)
 {
     _requestTracker.RemovePendingRead(message.CorrelationId);
 }