Ejemplo n.º 1
0
        private async Task<ConnectionDescriptor> EnsureConnectionAsync(ClientActionContext context, SessionDescriptor sessionDescriptor)
        {
            if (sessionDescriptor.State == ProxyState.Open)
            {
                context.ActionResult = sessionDescriptor.InitSessionResult;
                return sessionDescriptor.ServerConnection;
            }

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

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

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

                ClientActionContext initSessionContext = context;
                if (context.Action != sessionDescriptor.Contract.InitSession)
                {
                    // we are not initializaing proxy explicitely, so we need to check whether proxy has been initalized before
                    if (sessionDescriptor.RequiresInitParameters)
                    {
                        if (sessionDescriptor.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,
                        sessionDescriptor.Contract.InitSession,
                        sessionDescriptor.InitSessionParameters);
                }
                else if (sessionDescriptor.RequiresInitParameters)
                {
                    try
                    {
                        BoltFramework.ValidateParameters(sessionDescriptor.Contract.InitSession, 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,
                            sessionDescriptor.Contract.InitSession,
                            initSessionContext.Request?.RequestUri?.ToString());
                    }

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

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

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

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

                return sessionDescriptor.ServerConnection;
            }
        }
Ejemplo n.º 2
0
        protected virtual Exception HandleOpenConnectionError(ClientActionContext context, Exception error, SessionDescriptor 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;
        }