public InspectionResult InspectPackage(TcpPackage package)
        {
            try
            {
                if (package.Command == TcpCommand.DeniedToRoute)
                {
                    var route = package.Data.Deserialize<ClientMessage.DeniedToRoute>();
                    return new InspectionResult(InspectionDecision.Reconnect,
                                                data: new EndpointsPair(route.ExternalTcpEndPoint,
                                                                        route.ExternalHttpEndPoint));
                }
                if (package.Command != TcpCommand.TransactionWriteCompleted)
                {
                    return new InspectionResult(InspectionDecision.NotifyError,
                                             new CommandNotExpectedException(TcpCommand.TransactionWriteCompleted.ToString(),
                                                                             package.Command.ToString()));
                }

                var data = package.Data;
                var dto = data.Deserialize<ClientMessage.TransactionWriteCompleted>();
                _result = dto;

                switch ((OperationErrorCode)dto.ErrorCode)
                {
                    case OperationErrorCode.Success:
                        return new InspectionResult(InspectionDecision.Succeed);
                    case OperationErrorCode.PrepareTimeout:
                    case OperationErrorCode.CommitTimeout:
                    case OperationErrorCode.ForwardTimeout:
                        return new InspectionResult(InspectionDecision.Retry);
                    case OperationErrorCode.WrongExpectedVersion:
                        var err = string.Format("Transactional write failed due to WrongExpectedVersion. Stream: {0}, TransactionID: {1}, CorrID: {2}.",
                                                _stream,
                                                _transactionId,
                                                CorrelationId);
                        return new InspectionResult(InspectionDecision.NotifyError, new WrongExpectedVersionException(err));
                    case OperationErrorCode.StreamDeleted:
                        return new InspectionResult(InspectionDecision.NotifyError, new StreamDeletedException(_stream));
                    case OperationErrorCode.InvalidTransaction:
                        return new InspectionResult(InspectionDecision.NotifyError, new InvalidTransactionException());
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
            catch (Exception e)
            {
                return new InspectionResult(InspectionDecision.NotifyError, e);
            }
        }
        public InspectionResult InspectPackage(TcpPackage package)
        {
            try
            {
                if (package.Command == TcpCommand.DeniedToRoute)
                {
                    var route = package.Data.Deserialize<ClientMessage.DeniedToRoute>();
                    return new InspectionResult(InspectionDecision.Reconnect, data: route.ExternalTcpEndPoint);
                }
                if (package.Command != TcpCommand.TransactionWriteCompleted)
                {
                    return new InspectionResult(InspectionDecision.NotifyError,
                                             new CommandNotExpectedException(TcpCommand.TransactionWriteCompleted.ToString(),
                                                                             package.Command.ToString()));
                }

                var data = package.Data;
                var dto = data.Deserialize<ClientMessage.TransactionWriteCompleted>();
                _result = dto;

                switch (dto.Result)
                {
                    case ClientMessage.OperationResult.Success:
                        return new InspectionResult(InspectionDecision.Succeed);
                    case ClientMessage.OperationResult.PrepareTimeout:
                    case ClientMessage.OperationResult.CommitTimeout:
                    case ClientMessage.OperationResult.ForwardTimeout:
                        return new InspectionResult(InspectionDecision.Retry);
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
            catch (Exception e)
            {
                return new InspectionResult(InspectionDecision.NotifyError, e);
            }
        }