Beispiel #1
0
        protected virtual Exception HandleError(ClientActionContext context, Exception error, SessionMetadata session)
        {
            ErrorHandlingResult handlingResult = ErrorHandling.Handle(context, error);

            switch (handlingResult)
            {
            case ErrorHandlingResult.Close:
                session.ChangeState(context.Proxy, ProxyState.Closed);
                break;

            case ErrorHandlingResult.Recover:
                session.ClearSession();
                session.ChangeState(context.Proxy, ProxyState.Ready);
                if (!Recoverable)
                {
                    session.ChangeState(context.Proxy, ProxyState.Closed);
                }
                break;

            case ErrorHandlingResult.Rethrow:
                break;

            default:
                throw new ArgumentOutOfRangeException($"The value of '{handlingResult}' is not supported", nameof(handlingResult));
            }

            return(error);
        }
        public override async Task Invoke(ClientActionContext context)
        {
            ProxyState proxyState = context.Proxy.State;

            if (context.Proxy == null)
            {
                throw new InvalidOperationException("Proxy object is not assigned.");
            }

            if (context.Proxy.State == ProxyState.Closed)
            {
                throw new ProxyClosedException("Proxy object is already closed.");
            }

            try
            {
                await Next(context);

                if (proxyState == ProxyState.Ready)
                {
                    (context.Proxy as IPipelineCallback)?.ChangeState(ProxyState.Open);
                }
            }
            finally
            {
                if (proxyState == ProxyState.Open && context.Action == context.SessionContract.DestroySession)
                {
                    (context.Proxy as IPipelineCallback)?.ChangeState(ProxyState.Closed);
                }
            }
        }
        public override async Task InvokeAsync(ClientActionContext context)
        {
            try
            {
                await Next(context).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                ErrorHandlingResult result = _errorHandling.Handle(context, e);
                if (result == ErrorHandlingResult.Close || result == ErrorHandlingResult.Recover)
                {
                    (context.Proxy as IPipelineCallback)?.ChangeState(ProxyState.Closed);
                }

                throw;
            }
        }
        public override async Task InvokeAsync(ClientActionContext context)
        {
            if (context.ServerConnection == null)
            {
                context.ServerConnection = ServerProvider.GetServer();
            }

            context.EnsureRequest().RequestUri = EndpointProvider.GetEndpoint(context.ServerConnection.Server, context.Contract, context.Action);
            try
            {
                await Next(context);
            }
            catch (HttpRequestException)
            {
                ServerProvider.OnServerUnavailable(context.Request.RequestUri);
                throw;
            }
        }
        public override async Task InvokeAsync(ClientActionContext context)
        {
            if (context.ServerConnection == null)
            {
                context.ServerConnection = ServerProvider.GetServer();
            }

            context.GetRequestOrThrow().RequestUri = EndpointProvider.GetEndpoint(context.ServerConnection.Server, context.Contract, context.Action);
            try
            {
                await Next(context).ConfigureAwait(false);
            }
            catch (HttpRequestException)
            {
                ServerProvider.OnServerUnavailable(context.Request.RequestUri);
                throw;
            }
        }
        public override async Task InvokeAsync(ClientActionContext context)
        {
            int tries = 0;

            while (true)
            {
                try
                {
                    await Next(context).ConfigureAwait(false);

                    (context.Proxy as IPipelineCallback)?.ChangeState(ProxyState.Open);
                    return;
                }
                catch (Exception e)
                {
                    ErrorHandlingResult errorHandlingResult = ErrorHandling.Handle(context, e);
                    switch (errorHandlingResult)
                    {
                    case ErrorHandlingResult.Close:
                        (context.Proxy as IPipelineCallback)?.ChangeState(ProxyState.Closed);
                        throw;

                    case ErrorHandlingResult.Recover:
                        if (tries >= Retries)
                        {
                            (context.Proxy as IPipelineCallback)?.ChangeState(ProxyState.Closed);
                            throw;
                        }
                        tries++;
                        break;

                    case ErrorHandlingResult.Rethrow:
                        (context.Proxy as IPipelineCallback)?.ChangeState(ProxyState.Open);
                        throw;

                    default:
                        throw new ArgumentOutOfRangeException($"The value of '{errorHandlingResult}' is not supported.", nameof(errorHandlingResult));
                    }
                }

                context.ServerConnection = null;
                await Task.Delay(RetryDelay, context.RequestAborted).ConfigureAwait(false);
            }
        }
        public override async Task InvokeAsync(ClientActionContext context)
        {
            ProxyState proxyState = context.Proxy.State;

            if (context.Proxy == null)
            {
                throw new InvalidOperationException("Proxy object is not assigned.");
            }

            if (context.Proxy.State == ProxyState.Closed)
            {
                throw new ProxyClosedException("Proxy object is already closed.");
            }

            await Next(context).ConfigureAwait(false);

            if (proxyState == ProxyState.Ready)
            {
                (context.Proxy as IPipelineCallback)?.ChangeState(ProxyState.Open);
            }
        }
        public override async Task Invoke(ClientActionContext context)
        {
            int tries = 0;

            while (true)
            {
                try
                {
                    await Next(context);
                    (context.Proxy as IPipelineCallback)?.ChangeState(ProxyState.Open);
                    return;
                }
                catch (Exception e)
                {
                    ErrorHandlingResult errorHandlingResult = ErrorHandling.Handle(context, e);
                    switch (errorHandlingResult)
                    {
                        case ErrorHandlingResult.Close:
                            (context.Proxy as IPipelineCallback)?.ChangeState(ProxyState.Closed);
                            throw;
                        case ErrorHandlingResult.Recover:
                            if (tries >= Retries)
                            {
                                throw;
                            }
                            break;
                        case ErrorHandlingResult.Rethrow:
                            (context.Proxy as IPipelineCallback)?.ChangeState(ProxyState.Open);
                            throw;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
                }

                context.ServerConnection = null;
                tries++;
                await Task.Delay(RetryDelay, context.RequestAborted);
            }
        }
Beispiel #9
0
        public override async Task InvokeAsync(ClientActionContext context)
        {
            context.EnsureRequest();

            // access or create session assigned to current proxy
            SessionMetadata session = _sessions.GetOrAdd(
                context.Proxy,
                proxy => new SessionMetadata(BoltFramework.SessionMetadata.Resolve(proxy.Contract)));

            if (session.State != ProxyState.Open)
            {
                // we need to open proxy
                await EnsureConnectionAsync(context, session);
            }

            if (!UseDistributedSession)
            {
                // we stick to active connection otherwise new connection will be picked using PickConnectionMiddleware
                context.ServerConnection = session.ServerConnection;
            }

            if (context.Action == session.Contract.InitSession.Action)
            {
                // at this point session is opened, assign initialization result just in case
                if (context.ActionResult == null)
                {
                    context.ActionResult = session.InitSessionResult;
                }
            }
            else if (context.Action == session.Contract.DestroySession.Action)
            {
                if (context.Proxy.State == ProxyState.Closed)
                {
                    // no reason to continue in pipeline, proxy is already closed
                    session.ChangeState(context.Proxy, ProxyState.Closed);
                    context.ActionResult = session.DestroySessionResult;
                    return;
                }

                if (context.Proxy.State == ProxyState.Ready)
                {
                    // proxy was never initialized, ignore the rest of pipeline and close it
                    context.ActionResult = session.DestroySessionResult;
                    session.ChangeState(context.Proxy, ProxyState.Closed);
                    return;
                }

                if (session.RequiresDestroyParameters && context.Parameters == null)
                {
                    // we are trying to close proxy using IProxy.CloseAsync even when the destroy action requires actual parameters
                    throw new BoltClientException(
                        $"Destroing session requires parameters that were not provided for action '{context.Action.Name}'.",
                        ClientErrorCode.InvalidDestroySessionParameters,
                        context.Action,
                        null);
                }

                try
                {
                    // execute destroy session and close proxy
                    ClientSessionHandler.EnsureSession(context.EnsureRequest(), session.SessionId);
                    await Next(context);
                }
                finally
                {
                    _sessions.TryRemove(context.Proxy, out session);
                    session.ClearSession();
                    session.ChangeState(context.Proxy, ProxyState.Closed);
                }
            }
            else
            {
                // prepare the request with session
                ClientSessionHandler.EnsureSession(context.EnsureRequest(), session.SessionId);

                try
                {
                    // execute pipeline
                    await Next(context);
                }
                catch (Exception e)
                {
                    Exception handled = HandleError(context, e, session);
                    if (e == handled)
                    {
                        // the handled error is same, so just rethrow
                        throw;
                    }

                    if (handled != null)
                    {
                        throw handled;
                    }
                }
            }
        }
Beispiel #10
0
        private async Task<ConnectionDescriptor> EnsureConnectionAsync(ClientActionContext context, SessionMetadata sessionMetadata)
        {
            if (sessionMetadata.State == ProxyState.Open)
            {
                context.ActionResult = sessionMetadata.InitSessionResult;
                return sessionMetadata.ServerConnection;
            }

            if (sessionMetadata.State == ProxyState.Closed)
            {
                throw new ProxyClosedException();
            }

            using (await sessionMetadata.LockAsync())
            {
                // check connections tate again when under lock
                if (sessionMetadata.State == ProxyState.Open)
                {
                    context.ActionResult = sessionMetadata.InitSessionResult;
                    return sessionMetadata.ServerConnection;
                }

                if (sessionMetadata.State == ProxyState.Closed)
                {
                    throw new ProxyClosedException();
                }

                ClientActionContext initSessionContext = context;
                if (context.Action != sessionMetadata.Contract.InitSession.Action)
                {
                    // we are not initializaing proxy explicitely, so we need to check whether proxy has been initalized before
                    if (sessionMetadata.Contract.InitSession.HasParameters)
                    {
                        if (sessionMetadata.InitSessionParameters == null)
                        {
                            // we can not reuse initialization parameters, so throw 
                            throw new BoltClientException(
                                "Proxy need to be initialized before it can be used.",
                                ClientErrorCode.ProxyNotInitialized,
                                context.Action,
                                null);
                        }
                    }

                    // create init session context and reuse init parameters
                    initSessionContext = new ClientActionContext(
                        context.Proxy,
                        context.Contract,
                        sessionMetadata.Contract.InitSession.Action,
                        sessionMetadata.InitSessionParameters);
                }
                else if (sessionMetadata.Contract.InitSession.HasParameters)
                {
                    try
                    {
                        sessionMetadata.Contract.InitSession.ValidateParameters(initSessionContext.Parameters);
                    }
                    catch (Exception e)
                    {
                        // we can not reuse initialization parameters, so throw 
                        throw new BoltClientException(
                            $"Proxy is beeing initialized with invalid parameters. If session initialization has non empty parameters you should initialize it first by calling '{initSessionContext.Action.Name}' with proper parameters.",
                            ClientErrorCode.InvalidInitSessionParameters,
                            context.Action,
                            e);
                    }
                }

                try
                {
                    // execute whole pipeline
                    await Next(initSessionContext);

                    // extract connection and session id from response
                    string sessionId = ClientSessionHandler.GetSessionIdentifier(initSessionContext.Response);
                    if (sessionId == null)
                    {
                        throw new BoltServerException(
                            ServerErrorCode.SessionIdNotReceived,
                            sessionMetadata.Contract.InitSession.Action,
                            initSessionContext.Request?.RequestUri?.ToString());
                    }

                    if (initSessionContext.ServerConnection == null)
                    {
                        throw new BoltClientException(ClientErrorCode.ConnectionUnavailable, initSessionContext.Action);
                    }

                    sessionMetadata.InitSessionResult = initSessionContext.ActionResult;
                    sessionMetadata.InitSessionParameters = initSessionContext.Parameters;
                    sessionMetadata.SessionId = sessionId;
                    sessionMetadata.ServerConnection = initSessionContext.ServerConnection;
                    sessionMetadata.ChangeState(context.Proxy, ProxyState.Open);
                }
                catch (Exception e)
                {
                    Exception handled = HandleOpenConnectionError(initSessionContext, e, sessionMetadata);
                    if (handled == e)
                    {
                        throw;
                    }

                    if (handled != null)
                    {
                        throw handled;
                    }

                    throw;
                }
                finally
                {
                    // we should not dispose original context
                    if (context.Action != sessionMetadata.Contract.InitSession.Action)
                    {
                        initSessionContext.Dispose();
                    }
                }

                return sessionMetadata.ServerConnection;
            }
        }
Beispiel #11
0
        protected virtual Exception HandleOpenConnectionError(ClientActionContext context, Exception error, SessionMetadata session)
        {
            session.ClearSession();
            ErrorHandlingResult handlingResult = ErrorHandling.Handle(context, error);
            switch (handlingResult)
            {
                case ErrorHandlingResult.Close:
                    session.ChangeState(context.Proxy, ProxyState.Closed);
                    break;
                case ErrorHandlingResult.Recover:
                case ErrorHandlingResult.Rethrow:
                    session.ChangeState(context.Proxy, ProxyState.Ready);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return error;
        }
 public SerializeParametersContent(ISerializer serializer, ClientActionContext clientContext)
 {
     _serializer    = serializer;
     _clientContext = clientContext;
 }
 public override Task Invoke(ClientActionContext context)
 {
     context.Request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(CultureInfo.CurrentCulture.Name));
     return Next(context);
 }
Beispiel #14
0
        public override async Task InvokeAsync(ClientActionContext context)
        {
            context.GetRequestOrThrow();

            // access or create session assigned to current proxy
            SessionMetadata session = _sessions.GetOrAdd(
                context.Proxy,
                proxy => new SessionMetadata(proxy.Contract.Session));

            if (session.State != ProxyState.Open)
            {
                // we need to open proxy
                await EnsureConnectionAsync(context, session).ConfigureAwait(false);
            }

            if (!UseDistributedSession)
            {
                // we stick to active connection otherwise new connection will be picked using PickConnectionMiddleware
                context.ServerConnection = session.ServerConnection;
            }

            if (context.Action.Action == session.Contract.InitSession.Action)
            {
                // at this point session is opened, assign initialization result just in case
                if (context.ActionResult == null)
                {
                    context.ActionResult = session.InitSessionResult;
                }
            }
            else if (context.Action.Action == session.Contract.DestroySession.Action)
            {
                if (context.Proxy.State == ProxyState.Closed)
                {
                    // no reason to continue in pipeline, proxy is already closed
                    session.ChangeState(context.Proxy, ProxyState.Closed);
                    context.ActionResult = session.DestroySessionResult;
                    return;
                }

                if (context.Proxy.State == ProxyState.Ready)
                {
                    // proxy was never initialized, ignore the rest of pipeline and close it
                    context.ActionResult = session.DestroySessionResult;
                    session.ChangeState(context.Proxy, ProxyState.Closed);
                    return;
                }

                if (session.RequiresDestroyParameters && context.Parameters == null)
                {
                    // we are trying to close proxy using IProxy.CloseAsync even when the destroy action requires actual parameters
                    throw new BoltClientException(
                              $"Destroing session requires parameters that were not provided for action '{context.Action.Name}'.",
                              ClientErrorCode.InvalidDestroySessionParameters,
                              context.Action.Name,
                              null);
                }

                try
                {
                    // execute destroy session and close proxy
                    ClientSessionHandler.EnsureSession(context.GetRequestOrThrow(), session.SessionId);
                    await Next(context).ConfigureAwait(false);
                }
                finally
                {
                    _sessions.TryRemove(context.Proxy, out session);
                    session.ClearSession();
                    session.ChangeState(context.Proxy, ProxyState.Closed);
                }
            }
            else
            {
                // prepare the request with session
                ClientSessionHandler.EnsureSession(context.GetRequestOrThrow(), session.SessionId);

                try
                {
                    // execute pipeline
                    await Next(context).ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    Exception handled = HandleError(context, e, session);
                    if (e == handled)
                    {
                        // the handled error is same, so just rethrow
                        throw;
                    }

                    if (handled != null)
                    {
                        throw handled;
                    }
                }
            }
        }
Beispiel #15
0
        private async Task <ConnectionDescriptor> EnsureConnectionAsync(ClientActionContext context, SessionMetadata sessionMetadata)
        {
            if (sessionMetadata.State == ProxyState.Open)
            {
                context.ActionResult = sessionMetadata.InitSessionResult;
                return(sessionMetadata.ServerConnection);
            }

            if (sessionMetadata.State == ProxyState.Closed)
            {
                throw new ProxyClosedException();
            }

            using (await sessionMetadata.LockAsync().ConfigureAwait(false))
            {
                // check connections tate again when under lock
                if (sessionMetadata.State == ProxyState.Open)
                {
                    context.ActionResult = sessionMetadata.InitSessionResult;
                    return(sessionMetadata.ServerConnection);
                }

                if (sessionMetadata.State == ProxyState.Closed)
                {
                    throw new ProxyClosedException();
                }

                ClientActionContext initSessionContext = context;
                if (context.Action.Action != sessionMetadata.Contract.InitSession.Action)
                {
                    // we are not initializaing proxy explicitely, so we need to check whether proxy has been initalized before
                    if (sessionMetadata.Contract.InitSession.HasParameters)
                    {
                        if (sessionMetadata.InitSessionParameters == null)
                        {
                            // we can not reuse initialization parameters, so throw
                            throw new BoltClientException(
                                      $"Action '{context.Action.Name}' on contract '{context.Contract.NormalizedName}' cannot be executed because proxy that is used for communication has not been initialized. Initialize the proxy first by explicitely calling '{initSessionContext.Action.Name}' action with proper parameters.",
                                      ClientErrorCode.InvalidInitSessionParameters,
                                      context.Action.Name);
                        }
                    }

                    // create init session context and reuse init parameters
                    initSessionContext = new ClientActionContext();
                    initSessionContext.Init(
                        context.Proxy,
                        context.Contract,
                        sessionMetadata.Contract.InitSession,
                        sessionMetadata.InitSessionParameters);
                }
                else if (sessionMetadata.Contract.InitSession.HasParameters)
                {
                    try
                    {
                        sessionMetadata.Contract.InitSession.ValidateParameters(initSessionContext.Parameters);
                    }
                    catch (Exception e)
                    {
                        // we can not reuse initialization parameters, so throw
                        throw new BoltClientException(
                                  $"Proxy initialization action '{context.Action.Name}' on contract '{context.Contract.NormalizedName}' cannot be executed because the provided parameters are invalid.",
                                  ClientErrorCode.InvalidInitSessionParameters,
                                  context.Action.Name,
                                  e);
                    }
                }

                try
                {
                    // execute whole pipeline
                    await Next(initSessionContext).ConfigureAwait(false);

                    // extract connection and session id from response
                    string sessionId = ClientSessionHandler.GetSessionIdentifier(initSessionContext.Response);
                    if (initSessionContext.ServerConnection == null)
                    {
                        throw new BoltClientException(ClientErrorCode.ConnectionUnavailable, initSessionContext.Action.Name);
                    }

                    sessionMetadata.InitSessionResult     = initSessionContext.ActionResult;
                    sessionMetadata.InitSessionParameters = initSessionContext.Parameters;
                    sessionMetadata.SessionId             = sessionId ?? throw new BoltServerException(
                                                                      ServerErrorCode.SessionIdNotReceived,
                                                                      sessionMetadata.Contract.InitSession.Action.Name,
                                                                      initSessionContext.Request?.RequestUri?.ToString());
                    sessionMetadata.ServerConnection = initSessionContext.ServerConnection;
                    sessionMetadata.ChangeState(context.Proxy, ProxyState.Open);
                }
                catch (Exception e)
                {
                    Exception handled = HandleOpenConnectionError(initSessionContext, e, sessionMetadata);
                    if (handled != null && handled != e)
                    {
                        throw handled;
                    }

                    throw;
                }
                finally
                {
                    // we should not dispose original context
                    if (context.Action.Action != sessionMetadata.Contract.InitSession.Action)
                    {
                        initSessionContext.Reset();
                    }
                }

                return(sessionMetadata.ServerConnection);
            }
        }
Beispiel #16
0
        protected virtual Exception HandleError(ClientActionContext context, Exception error, SessionDescriptor session)
        {
            ErrorHandlingResult handlingResult = ErrorHandling.Handle(context, error);
            switch (handlingResult)
            {
                case ErrorHandlingResult.Close:
                    session.ChangeState(context.Proxy, ProxyState.Closed);
                    break;
                case ErrorHandlingResult.Recover:
                    session.ClearSession();
                    session.ChangeState(context.Proxy, ProxyState.Ready);
                    if (!Recoverable)
                    {
                        session.ChangeState(context.Proxy, ProxyState.Closed);
                    }
                    break;
                case ErrorHandlingResult.Rethrow:
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return error;
        }