Esempio n. 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);
        }
Esempio n. 2
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;
        }
Esempio n. 3
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;
                    }
                }
            }
        }