Esempio n. 1
0
        public void IdlePersistenceModeShouldSave()
        {
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.Never, WorkflowInstanceState.Aborted, isStarting: false));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.Never, WorkflowInstanceState.Runnable, isStarting: false));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.Never, WorkflowInstanceState.Idle, isStarting: false));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.Never, WorkflowInstanceState.Idle, isStarting: true));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.Never, WorkflowInstanceState.Complete, isStarting: false));

            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnCompleted, WorkflowInstanceState.Aborted, isStarting: false));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnCompleted, WorkflowInstanceState.Runnable, isStarting: false));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnCompleted, WorkflowInstanceState.Idle, isStarting: false));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnCompleted, WorkflowInstanceState.Idle, isStarting: true));
            Assert.IsTrue(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnCompleted, WorkflowInstanceState.Complete, isStarting: false));

            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnPersistableIdle, WorkflowInstanceState.Aborted, isStarting: false));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnPersistableIdle, WorkflowInstanceState.Runnable, isStarting: false));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnPersistableIdle, WorkflowInstanceState.Idle, isStarting: true));
            Assert.IsTrue(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnPersistableIdle, WorkflowInstanceState.Idle, isStarting: false));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnPersistableIdle, WorkflowInstanceState.Complete, isStarting: false));

            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnStart, WorkflowInstanceState.Aborted, isStarting: false));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnStart, WorkflowInstanceState.Runnable, isStarting: false));
            Assert.IsTrue(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnStart, WorkflowInstanceState.Idle, isStarting: true));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnStart, WorkflowInstanceState.Idle, isStarting: false));
            Assert.IsFalse(IdlePersistenceModeExtensions.ShouldSave(IdlePersistenceMode.OnStart, WorkflowInstanceState.Complete, isStarting: false));
        }
        // The TAP async version of OnNotifyPaused() above.
        protected async Task OnNotifyPausedAsync()
        {
            var workflowInstanceState = this.Controller.State;

            if (workflowInstanceState == WorkflowInstanceState.Aborted)
            {
                // If there were a OnRequestAbort() previously, notify the host now.
                if (this.onRequestAbortReason != null)
                {
                    await NotifyHostOnUnhandledExceptionAsync(this.onRequestAbortReason, null);
                }
            }
            else
            {
                try
                {
                    // If it's completed, call OnCompletedAsync() on host.
                    if (workflowInstanceState == WorkflowInstanceState.Complete &&
                        !this.hasRaisedCompleted)
                    {
                        await IfHasPendingThenFlushTrackingRecordsAsync();

                        var completionState = this.Controller.GetCompletionState(out var outputs, out var terminationException);
                        await this.host.OnCompletedAsync(completionState, outputs, terminationException);

                        this.hasRaisedCompleted = true;
                    }

                    // Call OnPausedAsync() on INotificationParticipant extensions.
                    await OnPausedAsync();

                    // Track the Idle state.
                    if (workflowInstanceState == WorkflowInstanceState.Idle &&
                        this.Controller.TrackingEnabled)
                    {
                        this.Controller.Track(new WorkflowInstanceRecord(this.Id, this.WorkflowDefinition.DisplayName,
                                                                         System.Activities.Tracking.WorkflowInstanceStates.Idle, this.DefinitionIdentity));
                        await IfHasPendingThenFlushTrackingRecordsAsync();
                    }

                    // If required, save state.
                    if (this.Controller.IsPersistable)
                    {
                        if (IdlePersistenceModeExtensions.ShouldSave(this.Parameters.IdlePersistenceMode, workflowInstanceState, this.IsStarting))
                        {
                            await SaveAsync();
                        }
                        this.IsStarting = false;
                    }
                }
                catch (Exception e)
                {
                    // Notify host, this can be eg. a serialization exception!
                    await NotifyHostOnUnhandledExceptionAsync(e, null);

                    // TODO Do we really need to protect againts exceptions below? Theoretically Controller won't throw now.
                    // The instance will abort, independently from the configuration.
                    await ExecuteWithExceptionTrackingAsync(() =>
                    {
                        return(AbortAsync(e));
                    });

                    workflowInstanceState = this.Controller.State;
                }
            }
            // finally
            // TODO Do we really need to protect againts exceptions below? Theoretically Controller won't throw now.
            await ExecuteWithExceptionTrackingAsync(() =>
            {
                // At this point it is possible, that Cancel/Teminate was called by OnNotifyUnhandledException() or OnNotifyPaused(),
                // and controller/executor Run() should be called, in this case we won't set the reset event,
                // the Run() will result a callback to OnNotifyPaused() or OnNotifyUnhandledException() again.
                if (workflowInstanceState == WorkflowInstanceState.Runnable)
                {
                    return(RunAsync());
                }
                else
                {
                    this.host.OnNotifyIdle();
                    return(TaskConstants.Completed);
                }
            });
        }