Exemple #1
0
    public TransitionFloat(float value, TransitionConfiguration config)
    {
        // initial value
        this.value = value;

        // initialize state
        this.startTime        = Time.unscaledTime;
        this.finishTime       = Time.unscaledTime;
        this.sourceValue      = value;
        this.destinationValue = value;

        // assign properties
        this.duration = config.duration;
        this.bezier   = config.bezier;
        this.delay    = config.delay;
    }
Exemple #2
0
 public TransitionEvaluationContext(StateExecutionContext stateExecutionContext,
                                    TransitionConfiguration transitionConfiguration)
 {
     TransitionConfiguration = transitionConfiguration;
     StateExecutionContext   = stateExecutionContext;
 }
Exemple #3
0
 public StateExecutionTransition(StateTypeConfiguration nextStateType, TransitionConfiguration transitionConfiguration)
 {
     NextStateType           = nextStateType;
     TransitionConfiguration = transitionConfiguration;
 }
        private async Task TransitionToState(WorkflowContext workflowContext, StateConfiguration stateConfiguration,
                                             TransitionConfiguration transitionConfiguration, CancellationToken cancellationToken = default)
        {
            // move to failed state with no additional checks in synchronous fashion
            if (stateConfiguration.Type == StateTypeConfiguration.Failed)
            {
                await ProcessState(workflowContext, stateConfiguration, cancellationToken).ConfigureAwait(false);

                return;
            }

            // in case if transition is trying to been done to the same state where workflow instance is ==> move to failed
            if (string.Equals(workflowContext.WorkflowInstance.CurrentStateCode, stateConfiguration.Code, StringComparison.OrdinalIgnoreCase))
            {
                Log.Warning("{workflowInstanceId} is attempted to be moved to the same state as it is now [{state}], moving it to failed state",
                            workflowContext.WorkflowInstance.Id, stateConfiguration.Code);

                await ProcessState(workflowContext, workflowContext.WorkflowConfiguration.GetFailedStateConfiguration(), cancellationToken).ConfigureAwait(false);

                return;
            }

            // if state has any event ==> move to awaiting event sub-state
            if (stateConfiguration.Events.Any())
            {
                // [assumption] state cannot have both event and incoming async transition (this check is done during WF configuration loading)
                workflowContext.WorkflowInstance.CurrentStateCode     = stateConfiguration.Code;
                workflowContext.WorkflowInstance.CurrentStateProgress = StateExecutionProgress.AwaitingEvent;
                await SaveWorkflowInstance(workflowContext.WorkflowInstance, cancellationToken).ConfigureAwait(false);

                Log.Debug("{workflowInstanceId} has been moved to [{state}::{subState}]",
                          workflowContext.WorkflowInstance.Id, stateConfiguration.Code, StateExecutionProgress.AwaitingEvent);

                return;
            }

            // process synchronous / delayed transition
            if (transitionConfiguration.Type.In(TransitionTypeConfiguration.Synchronous, TransitionTypeConfiguration.AsynchronousWithDelay))
            {
                // save current transition as a checkpoint
                workflowContext.WorkflowInstance.CurrentStateCode     = stateConfiguration.Code;
                workflowContext.WorkflowInstance.CurrentStateProgress = StateExecutionProgress.Started;
                await SaveWorkflowInstance(workflowContext.WorkflowInstance, cancellationToken).ConfigureAwait(false);

                Log.Debug("{workflowInstanceId} is moved to [{state}::{subState}]",
                          workflowContext.WorkflowInstance.Id, stateConfiguration.Code, StateExecutionProgress.Started);

                await ProcessState(workflowContext, stateConfiguration, cancellationToken).ConfigureAwait(false);

                return;
            }

            // process asynchronous-immediate transition
            if (transitionConfiguration.Type == TransitionTypeConfiguration.AsynchronousImmediate)
            {
                workflowContext.WorkflowInstance.CurrentStateCode     = stateConfiguration.Code;
                workflowContext.WorkflowInstance.CurrentStateProgress = StateExecutionProgress.AwaitingAsyncTransition;
                await SaveWorkflowInstance(workflowContext.WorkflowInstance, cancellationToken).ConfigureAwait(false);

                var workflowMessage = new AsynchronousTransitionWorkflowMessage(workflowContext.WorkflowConfiguration.Id, workflowContext.WorkflowInstance.Id);
                await WorkflowEngineBuilder.WorkflowMessageTransportFactoryProvider
                .CreateMessageTransportFactory(workflowContext.WorkflowConfiguration.RuntimeConfiguration.EndpointConfiguration.Type)
                .CreateMessageTransport(workflowContext.WorkflowConfiguration.RuntimeConfiguration.EndpointConfiguration.Address)
                .Send(workflowContext.WorkflowConfiguration.RuntimeConfiguration.EndpointConfiguration, workflowMessage, cancellationToken)
                .ConfigureAwait(false);

                // TODO: make sure that asynchronous-immediate transition will not have race conditions with current workflow engine
                //    ==> send them as delayed workflow messages with default delay interval (1 second)
//                var delay = TimeSpan.FromSeconds(1D);
//                var currentStateCode = workflowContext.WorkflowInstance.CurrentStateCode;
//                var workflowMessage = new DelayedTransitionWorkflowMessage(workflowContext.WorkflowConfiguration.Id,
//                    workflowContext.WorkflowInstance.Id, delay, currentStateCode, transitionConfiguration.MoveToState);
//                await WorkflowEngineBuilder.WorkflowMessageTransportFactory
//                    .CreateMessageTransport(workflowContext.WorkflowConfiguration.RuntimeConfiguration.EndpointConfiguration.Address)
//                    .SendWithDelay(workflowContext.WorkflowConfiguration.RuntimeConfiguration.EndpointConfiguration, workflowMessage, cancellationToken).ConfigureAwait(false);

                Log.Debug("{workflowInstanceId} has been moved to [{state}::{subState}]",
                          workflowContext.WorkflowInstance.Id, stateConfiguration.Code, StateExecutionProgress.AwaitingAsyncTransition);

                return;
            }

            throw new WorkflowException("Non synchronous/asynchronous-immediate transitions are not supported");
        }
Exemple #5
0
        public async Task <TransitionEvaluationResult> Evaluate(StateExecutionContext stateExecutionContext, TransitionConfiguration transitionConfiguration, CancellationToken cancellationToken)
        {
            ITransition transition = null;

            if (!string.IsNullOrEmpty(transitionConfiguration.Code))
            {
                transition = _workflowEngine.WorkflowEngineBuilder
                             .TransitionFactory.CreateTransition(transitionConfiguration.Code);
            }

            if (null == transition && !string.IsNullOrEmpty(transitionConfiguration.ConditionScript) &&
                transitionConfiguration.ConditionScriptType == ScriptTypeConfiguration.CSharp)
            {
                transition = new CSharpScriptTransition(stateExecutionContext.StateConfiguration.Code,
                                                        transitionConfiguration.ConditionScriptType, transitionConfiguration.ConditionScript);
            }

            if (null == transition)
            {
                // there is neither code nor condition for transition
                //     ==> assume transition always evaluates to true
                return(new TransitionEvaluationResult(TransitionEvaluationStatus.EvaluatedTrue));
            }

            Log.Verbose("Starting evaluation of transition [{code}] [{condition}] for [{workflowInstanceId}]",
                        transitionConfiguration.Code, transitionConfiguration.ConditionScriptType,
                        stateExecutionContext.WorkflowContext.WorkflowInstance.Id);

            try
            {
                var transitionEvaluationContext = new TransitionEvaluationContext(stateExecutionContext, transitionConfiguration);
                var transitionEvaluationResult  = await transition.Evaluate(transitionEvaluationContext, cancellationToken).ConfigureAwait(false);

                if (transitionEvaluationResult.Status == TransitionEvaluationStatus.EvaluationFailed)
                {
                    throw new WorkflowException(string.Format(CultureInfo.InvariantCulture,
                                                              "Evaluation of an transition [code={0}], [condition={1}] returns [EvaluationFailed] for workflow instance [{2:D}]",
                                                              transitionConfiguration.Code, transitionConfiguration.ConditionScript,
                                                              stateExecutionContext.WorkflowContext.WorkflowInstance.Id));
                }

                return(transitionEvaluationResult);
            }
            catch (Exception ex)
            {
                throw new WorkflowException(string.Format(CultureInfo.InvariantCulture,
                                                          "An error has occurred during evaluation of an transition [code={0}], [condition={1}] for workflow instance [{2:D}]",
                                                          transitionConfiguration.Code, transitionConfiguration.ConditionScript,
                                                          stateExecutionContext.WorkflowContext.WorkflowInstance.Id), ex);
            }
        }