예제 #1
0
 bool IsRunCompleted(WorkflowRun run)
 {
     return(run.WorkflowRunStatus_Enum != WorkflowRunState_Enumeration.WorkflowRunPaused &&
            run.WorkflowRunStatus_Enum != WorkflowRunState_Enumeration.WorkflowRunSuspended &&
            run.WorkflowRunStatus_Enum != WorkflowRunState_Enumeration.WorkflowRunStarted &&
            run.WorkflowRunStatus_Enum != WorkflowRunState_Enumeration.WorkflowRunQueued);
 }
예제 #2
0
        /// <summary>
        /// Get the request context this workflow will be running as, taking into account triggering user and owner.
        /// </summary>
        private RequestContextData GetEffectiveSecurityContext(WorkflowRun run, WorkflowMetadata metaData)
        {
            var effectiveUser  = GetEffectiveUser(run, metaData);
            var triggeringUser = GetTriggeringUser(run);

            // Error! The caller will deal with the missing info. We can't throw becasue RunState is needed for the error reporting
            if (effectiveUser == null)
            {
                return(null);
            }

            if (metaData.WfRunAsOwner && metaData.WfSecurityOwner == null)
            {
                return(null);
            }

            var identityInfo = new IdentityInfo(effectiveUser.Id, effectiveUser.Name);


            var context = RequestContext.GetContext();

            var effectiveSecurityContext = new RequestContextData(context);

            effectiveSecurityContext.Identity = identityInfo;

            // If we are running as someone other than the triggerer, set the secondary identity to the triggerer.
            // NOTE: This could potentially cause a problem in the case where a wf triggering another wf scenario.
            // It's possible that the user will see stale data. The risk should be quite low.
            if (triggeringUser != null && triggeringUser.Id != effectiveUser.Id)
            {
                effectiveSecurityContext.SecondaryIdentity = new IdentityInfo(triggeringUser.Id, triggeringUser.Name);
            }

            return(effectiveSecurityContext);
        }
예제 #3
0
        private void ValidateWorkflowRun1(WorkflowRun workflowRun)
        {
            Assert.Equal("/subscriptions/66666666-6666-6666-6666-666666666666/resourceGroups/rgName/providers/Microsoft.Logic/workflows/wfName/runs/run87646872399558047", workflowRun.Id);
            Assert.Equal("run87646872399558047", workflowRun.Name);
            Assert.Equal("Microsoft.Logic/workflows/runs", workflowRun.Type);

            Assert.Equal(2015, workflowRun.StartTime.Value.Year);
            Assert.Equal(06, workflowRun.StartTime.Value.Month);
            Assert.Equal(23, workflowRun.StartTime.Value.Day);
            Assert.Equal(21, workflowRun.StartTime.Value.Hour);
            Assert.Equal(47, workflowRun.StartTime.Value.Minute);
            Assert.Equal(00, workflowRun.StartTime.Value.Second);
            Assert.Equal(00, workflowRun.StartTime.Value.Millisecond);
            Assert.Equal(DateTimeKind.Utc, workflowRun.StartTime.Value.Kind);

            Assert.Equal(2015, workflowRun.EndTime.Value.Year);
            Assert.Equal(06, workflowRun.EndTime.Value.Month);
            Assert.Equal(23, workflowRun.EndTime.Value.Day);
            Assert.Equal(21, workflowRun.EndTime.Value.Hour);
            Assert.Equal(47, workflowRun.EndTime.Value.Minute);
            Assert.Equal(30, workflowRun.EndTime.Value.Second);
            Assert.Equal(130, workflowRun.EndTime.Value.Millisecond);
            Assert.Equal(DateTimeKind.Utc, workflowRun.EndTime.Value.Kind);

            Assert.Equal(WorkflowStatus.Succeeded, workflowRun.Status.Value);
            Assert.Equal("a04da054-a1ae-409d-80ff-b09febefc357", workflowRun.CorrelationId);
            Assert.Equal("/subscriptions/66666666-6666-6666-6666-666666666666/resourceGroups/rgName/providers/Microsoft.Logic/workflows/wfName/versions/ver87717906782501130", workflowRun.Workflow.Id);
            Assert.Equal("Microsoft.Logic/workflows/versions", workflowRun.Workflow.Type);
            Assert.Equal("wfName/ver87717906782501130", workflowRun.Workflow.Name);

            Assert.Equal("6A65DA9E-CFF8-4D3E-B5FB-691739C7AD61", workflowRun.Trigger.Name);
            Assert.Equal(0, workflowRun.Outputs.Count);
        }
예제 #4
0
        private string ResumeWorkflowAsync_old(WorkflowRun workflowRun, IWorkflowEvent resumeEvent)
        {
            Action runAction = () =>
            {
                using (new WorkflowRunContext {
                    RunTriggersInCurrentThread = true
                })
                {
                    ResumeWorkflow(workflowRun, resumeEvent);
                }
            };

            Factory.WorkflowRunTaskManager.RegisterStart(workflowRun.TaskId);
            HandleDiagnostics(workflowRun, "Queued");

            if (WorkflowRunContext.Current.RunTriggersInCurrentThread)
            {
                // Ignore the Asyn and process it syncronously
                runAction();
            }
            else // Async
            {
                WorkflowRunContext.Current.QueueAction(() =>
                {
                    runAction();
                });
            }

            return(workflowRun.TaskId);
        }
예제 #5
0
        public void GetWorkflowDescriptionTest_Empty()
        {
            var run      = new WorkflowRun();
            var runState = new TestRunState(new WorkflowMetadata(), run);

            Assert.That(runState.GetSafeWorkflowDescription(), Is.StringContaining(run.Id.ToString()));
        }
예제 #6
0
        public void TestTimeout( )
        {
            var dummyTimeoutHelper = new DummyTimeoutHelper();

            using (var scope = Factory.Current.BeginLifetimeScope(builder =>
            {
                builder.Register(ctx => dummyTimeoutHelper).As <ITimeoutActivityHelper>();
            }))
                using (Factory.SetCurrentScope(scope))
                {
                    Workflow displayFormWf = CreateDisplayFormTestWf(null, null, null, 5);

                    WorkflowRun run = RunWorkflow(displayFormWf);

                    dummyTimeoutHelper.Timeout();

                    run = Entity.Get <WorkflowRun>(run);

                    Assert.AreEqual(WorkflowRunState_Enumeration.WorkflowRunCompleted, run.WorkflowRunStatus_Enum);

                    var exitPoint = run.GetExitPoint();

                    Assert.AreEqual("Time-out", exitPoint.Name, "Workflow exited at a time-out");
                    // Need to figure out how to test the exit point.
                }
        }
예제 #7
0
        public string ResumeWorkflowAsync_new(WorkflowRun workflowRun, IWorkflowEvent resumeEvent)
        {
            Factory.WorkflowRunTaskManager.RegisterStart(workflowRun.TaskId);

            bool runInForeground = WorkflowRunContext.Current.RunTriggersInCurrentThread;

            var queueEvent = resumeEvent as IWorkflowQueuedEvent;

            if (queueEvent == null)
            {
                EventLog.Application.WriteError("Attempted to queue a resume task that cannot be queued, running it on the foreground thread instead. EventType: {resumeEvent.GetType()}");
                runInForeground = true;
            }

            if (runInForeground)
            {
                ResumeWorkflow(workflowRun, resumeEvent);
            }
            else
            {
                var task = ResumeWorkflowHandler.CreateBackgroundTask(workflowRun, queueEvent);

                Factory.BackgroundTaskManager.EnqueueTask(task);

                HandleDiagnostics(workflowRun, "Queued");
            }

            return(workflowRun.TaskId);
        }
예제 #8
0
 public RunState(WorkflowMetadata metaData, WorkflowRun workflowRun, RequestContextData effectiveSecurityContext)
     : base(metaData, workflowRun, effectiveSecurityContext)
 {
     ownerAccountRuntimeArgName     = Entity.GetName(new EntityRef("workflowOwnerAccount").Id);
     triggeringUserRuntimeArgName   = Entity.GetName(new EntityRef("triggeringUserAccount").Id);
     triggeringPersonRuntimeArgName = Entity.GetName(new EntityRef("triggeringPerson").Id);
 }
        void ProcessResult(IRunState context, WorkflowRun run)
        {
            if (run.WorkflowRunStatus_Enum != WorkflowRunState_Enumeration.WorkflowRunCompleted)
            {
                throw new InnerWorkflowFailedException(string.Format("Inner workflow '{0}' failed", run.WorkflowBeingRun.Name));
            }

            var proxyExitPoint    = run.GetExitPoint();
            var matchingExitPoint = context.Metadata.GetExitpointsForActivity(ActivityInstance.Id).SingleOrDefault(ep => ep.Name == proxyExitPoint.Name);

            if (matchingExitPoint == null)
            {
                throw new WorkflowRunException("Workflow proxy returned using an exit point that doesn't match anything in the parent");
            }

            context.ExitPointId = matchingExitPoint;

            var outputs = run.GetOutput();

            var outArgs = ActivityInstance.GetOutputArguments();

            // copy the values from the results into the arguments witht eh same name
            foreach (var arg in outArgs)
            {
                var    name  = arg.Name;
                object value = null;

                if (outputs.TryGetValue(name, out value))
                {
                    context.SetArgValue(ActivityInstance, arg, value);
                }
            }
        }
예제 #10
0
        private void ValidateRun1(WorkflowRun run)
        {
            Assert.True(this.ValidateIdFormat(id: run.Id, entityTypeName: "workflows", entitySubtypeName: "runs"));
            Assert.Equal("08587692861242198730", run.Name);
            Assert.Equal("Microsoft.Logic/workflows/runs", run.Type);

            Assert.Equal(2015, run.StartTime.Value.Year);
            Assert.Equal(06, run.StartTime.Value.Month);
            Assert.Equal(23, run.StartTime.Value.Day);
            Assert.Equal(21, run.StartTime.Value.Hour);
            Assert.Equal(47, run.StartTime.Value.Minute);
            Assert.Equal(00, run.StartTime.Value.Second);
            Assert.Equal(DateTimeKind.Utc, run.StartTime.Value.Kind);

            Assert.Equal(2015, run.EndTime.Value.Year);
            Assert.Equal(06, run.EndTime.Value.Month);
            Assert.Equal(23, run.EndTime.Value.Day);
            Assert.Equal(21, run.EndTime.Value.Hour);
            Assert.Equal(47, run.EndTime.Value.Minute);
            Assert.Equal(30, run.EndTime.Value.Second);
            Assert.Equal(DateTimeKind.Utc, run.EndTime.Value.Kind);

            Assert.Equal(WorkflowStatus.Succeeded, run.Status);
            Assert.Equal("4701405c-1543-4127-adb9-a396717a4ffb", run.CorrelationId);
            Assert.Equal("/subscriptions/66666666-6666-6666-6666-666666666666/resourceGroups/rgName/providers/Microsoft.Logic/workflows/wfName/versions/08587717906782501130", run.Workflow.Id);
            Assert.Equal("wfName/08587717906782501130", run.Workflow.Name);
            Assert.Equal("Microsoft.Logic/workflows/versions", run.Workflow.Type);
            Assert.Equal("https://someurl.blob.core.windows.net/someurl", run.Trigger.OutputsLink.Uri);
            Assert.Equal("\"0x8D262D79DE77699\"", run.Trigger.OutputsLink.ContentVersion);
            Assert.Equal(2080, run.Trigger.OutputsLink.ContentSize);
            Assert.Equal("md5", run.Trigger.OutputsLink.ContentHash.Algorithm);
            Assert.Equal("4Ikl8rJkAg3bN8C9I6nKFQ==", run.Trigger.OutputsLink.ContentHash.Value);
        }
        public void SuspendRestore()
        {
            using (new SecurityBypassContext())
            {
                var handler = new ResumeWorkflowHandler();

                var run = new WorkflowRun()
                {
                    WorkflowRunStatus_Enum = WorkflowRunState_Enumeration.WorkflowRunSuspended
                };
                run.Save();

                var task = ResumeWorkflowHandler.CreateBackgroundTask(run, new WorkflowRestoreEvent());

                var taskEntity = handler.CreateSuspendedTask(task).As <SuspendedRun>();
                taskEntity.Save();

                taskEntity.Should().NotBeNull();
                taskEntity.SrRun.Should().NotBeNull();
                taskEntity.SrRun.Id.Should().Be(run.Id);

                var bgTasks = handler.RestoreSuspendedTasks();

                bgTasks.Should().HaveCount(1);

                var runParam = bgTasks.First().GetData <ResumeWorkflowParams>();

                runParam.WorkflowRunId.ShouldBeEquivalentTo(run.Id);
                Assert.That(runParam.WorkflowRunId, Is.EqualTo(run.Id));
            }
        }
예제 #12
0
 public void ScheduleTimeout(IResumableActivity activityInstance, WorkflowRun workflowRun, decimal timeoutMinutes)
 {
     timeoutAction = () =>
     {
         var workflowEvent = new TimeoutEvent();
         WorkflowRunner.Instance.ResumeWorkflow(workflowRun, workflowEvent);
     };
 }
예제 #13
0
 private void cancel_Click(object sender, EventArgs e)
 {
     if (guidBox.Text != "")
     {
         loadBTN_Click(sender, e);
     }
     workflowRun?.Cancel();
     workflowRun = null;
 }
예제 #14
0
        public static TestRunState CreateDummyState(Workflow workflow)
        {
            var workflowRun = new WorkflowRun()
            {
                WorkflowBeingRun = workflow
            };

            return(new TestRunState(new WorkflowMetadata(workflow), workflowRun));
        }
예제 #15
0
 private void loadBTN_Click(object sender, EventArgs e)
 {
     if (guidBox.Text == "")
     {
         return;
     }
     workflowRun?.Dispose();
     workflowRun = new WorkflowRun(guidBox.Text, UpdateControls);
 }
예제 #16
0
        private UserAccount GetEffectiveUser(WorkflowRun run, WorkflowMetadata metaData)
        {
            if (metaData != null && metaData.WfRunAsOwner)
            {
                return(metaData.WfSecurityOwner);
            }

            return(GetTriggeringUser(run));
        }
예제 #17
0
        Notification RunNotify(IEntity person, TwilioNotifier notifier, bool waitForReplies, IEntity linkTo = null, string replyWorkflowString = null, Workflow replyWorkflow = null)
        {
            var inputs = new Dictionary <string, object>
            {
                { "People", person.ToEnumerable() },
                { "LinkToRecord", linkTo },
            };

            var wf = new Workflow {
                Name = "RunNotify " + DateTime.UtcNow.ToString()
            };

            wf
            .AddDefaultExitPoint()
            .AddInput <ResourceListArgument>("People", Person.Person_Type)
            .AddInput <ResourceArgument>("LinkToRecord", UserResource.UserResource_Type)
            .AddOutput <ResourceArgument>("NotificationRecord", Notification.Notification_Type)
            .AddNotify(
                "Notify", "People", "'Test'",
                waitForReplies,
                linkToRecordExpression: "LinkToRecord",
                replyMap: replyWorkflowString == null ? null :
                new Dictionary <string, Workflow> {
                { replyWorkflowString, replyWorkflow }
            })
            .AddAssignToVar("Assign", "[Notify_Notification Record]", "NotificationRecord");

            wf.Save();
            ToDelete.Add(wf.Id);

            using (var scope = Factory.Current.BeginLifetimeScope(builder =>
            {
                builder.Register(c => new TenantSmsNotifier(notifier.Id)).As <INotifier>();
            }))
                using (Factory.SetCurrentScope(scope))
                {
                    WorkflowRun run = null;

                    using (new TestWfRunContext())
                    {
                        run = RunWorkflow(wf, inputs);
                        run.Save();
                    }

                    Thread.Sleep(1000);

                    Assert.That(run.WorkflowRunStatus_Enum, Is.EqualTo(WorkflowRunState_Enumeration.WorkflowRunCompleted));

                    var results = run.GetOutput();

                    Assert.That(results.Keys, Has.Member("NotificationRecord"));

                    var entity = (IEntity)results["NotificationRecord"];
                    return(entity.As <Notification>());
                }
        }
        bool ShouldDelete(WorkflowRun run, DateTime deleteOlderThan)
        {
            DateTime runCompletedAt = run.RunCompletedAt ?? DateTime.MinValue;

            return
                (runCompletedAt < deleteOlderThan &&
                 (
                     run.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunFailed ||
                     run.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunCompleted
                 ));
        }
예제 #19
0
 public void CancelTimeout(WorkflowRun workflowRun)
 {
     try
     {
         SchedulingHelper.Instance.DeleteJob(GetJobId(workflowRun));
     }
     catch (Exception ex)
     {
         EventLog.Application.WriteError($"Unable to cancel timeout: Job may not have been created. RunId: {workflowRun.Id}  Exception: {ex}");
     }
 }
예제 #20
0
 /// <summary>
 /// Resume a workflow. The workflow will run async unless it is in a RunTriggersInCurrentThread WorkflowContext.
 /// </summary>
 /// <param name="workflowRun"></param>
 /// <param name="resumeEvent"></param>
 public string ResumeWorkflowAsync(WorkflowRun workflowRun, IWorkflowEvent resumeEvent)
 {
     if (Factory.FeatureSwitch.Get("longRunningWorkflow"))
     {
         return(ResumeWorkflowAsync_new(workflowRun, resumeEvent));
     }
     else
     {
         return(ResumeWorkflowAsync_old(workflowRun, resumeEvent));
     }
 }
        private static WorkflowRun CreateWorkflowRun(WorkflowRunTrigger trigger)
        {
            var correlation = new Correlation(BogusGenerator.Random.String().OrNull(BogusGenerator)).OrNull(BogusGenerator);
            var workflowRun = new WorkflowRun(
                name: BogusGenerator.Internet.DomainWord(),
                startTime: BogusGenerator.Date.Recent(),
                status: GenerateStatus(),
                error: BogusGenerator.Random.Bytes(10).OrNull(BogusGenerator),
                correlation: correlation,
                trigger: trigger);

            return(workflowRun);
        }
예제 #22
0
        public static BackgroundTask CreateBackgroundTask(WorkflowRun run, IWorkflowQueuedEvent resumeEvent)
        {
            if (resumeEvent == null)
            {
                throw new ArgumentNullException(nameof(resumeEvent));
            }

            var runParams = new ResumeWorkflowParams {
                WorkflowRunId = run.Id
            };

            return(BackgroundTask.Create(HandlerKey, runParams));
        }
예제 #23
0
        public RunStateBase(WorkflowMetadata metaData, WorkflowRun _workflowRun, RequestContextData effectiveSecurityContext)
            : this(metaData)
        {
            WorkflowInvoker = new WorkflowInvoker();
            WorkflowRun     = _workflowRun;

            StepsTakenInSession      = 0;
            EffectiveSecurityContext = effectiveSecurityContext;
            ExitPointId     = _workflowRun.WorkflowRunExitPoint;
            HasTimeout      = _workflowRun.HasTimeout ?? false;
            PendingActivity = _workflowRun.PendingActivity;
            RunStatus       = _workflowRun.WorkflowRunStatus_Enum;
            CompletedAt     = _workflowRun.RunCompletedAt;
        }
예제 #24
0
        /// <summary>
        /// Send the notifications on a background thread.
        /// </summary>
        void SendMessagesInBackground(IRunState context, long notificationId, List <long> userIds, bool waitForReplies)
        {
            context.SetPostRunAction(() =>
            {
                var runId = context.WorkflowRunId;

                WorkflowRunContext.Current.QueueAction(() =>
                                                       SecurityBypassContext.Elevate(() =>
                {
                    var workflowRunner = Factory.Current.Resolve <IWorkflowRunner>();
                    WorkflowRun run    = Entity.Get <WorkflowRun>(runId);;

                    try
                    {
                        var notification = Entity.Get <Notification>(notificationId);
                        var users        = Entity.Get(userIds);

                        Factory.Current.Resolve <INotifier>().Send(notification, users, true);
                        var sends            = notification.SendRecords;
                        var sentWithoutError = sends.Where(r => r.SrErrorMessage == null);

                        // update the notification

                        bool resume = true;
                        if (waitForReplies)
                        {
                            notification             = notification.AsWritable <Notification>();
                            notification.NPendingRun = run;
                            notification.Save();

                            resume = notification.Complete(); // Just in case all the replies were completed while we were sending.
                        }

                        if (resume && run != null)
                        {
                            workflowRunner.ResumeWorkflow(run, new NotifyResumeEvent());
                        }
                    }
                    catch
                    {
                        if (run != null)
                        {
                            workflowRunner.ResumeWorkflow(run, new NotifyResumeFailedEvent());
                        }

                        throw;
                    }
                }));
            });
        }
예제 #25
0
 /// <summary>
 /// Handles the diagnostics.
 /// </summary>
 /// <param name="workflowRun">The workflow run.</param>
 /// <param name="status">The status.</param>
 private void HandleDiagnostics(WorkflowRun workflowRun, string status)
 {
     if (DiagnosticsEnabled)
     {
         if (DateTime.UtcNow - DiagnosticsLastUpdated > TimeSpan.FromMinutes(5))
         {
             DiagnosticsEnabled = false;
         }
         else
         {
             SendDiagnostics(workflowRun, status);
         }
     }
 }
예제 #26
0
        public void GetWorkflowDescriptionTest_MissingActivity()
        {
            var workflow = new Workflow()
            {
                Name = "wfName"
            };
            var workflowRun = new WorkflowRun()
            {
                WorkflowBeingRun = workflow
            };

            var runState = new TestRunState(new WorkflowMetadata(workflow), workflowRun);

            Assert.That(runState.GetSafeWorkflowDescription(), Is.StringContaining(workflowRun.Id.ToString()));
        }
예제 #27
0
        public void DeferSave(WorkflowRun run)
        {
            if (this == _rootContext)
            {
                throw new ArgumentException("run");
            }

            if (HandleDeferred || _parentContext == null)
            {
                _deferredRuns.Enqueue(run);
            }
            else
            {
                _parentContext.DeferSave(run);
            }
        }
예제 #28
0
        private static UserAccount EnsureTriggeringUser(WorkflowRun workflowRun)
        {
            if (!workflowRun.IsTemporaryId || workflowRun.TriggeringUser != null)
            {
                return(null);
            }

            var deferredRun = workflowRun as WorkflowRunDeferred;

            if (deferredRun != null && deferredRun.TriggeringUserId > 0)
            {
                return(deferredRun.GetTriggeringUser());
            }

            return(null);
        }
예제 #29
0
        /// <summary>
        /// Create a run state
        /// </summary>
        /// <returns>A run state - note the security information will be missing if it has been set incorrectly in the workflow</returns>
        public IRunState CreateRunState(WorkflowMetadata metaData, WorkflowRun workflowRun)
        {
            using (Profiler.Measure("DefaultRunStateFactory.CreateRunState"))
            {
                var run = workflowRun;

                if (!run.IsTemporaryId)
                {
                    run = run.AsWritable <WorkflowRun>();
                }

                //var effectiveUser = GetEffectiveUser(run, metaData);
                var effectiveSecurityContext = GetEffectiveSecurityContext(run, metaData);

                return(new RunState(metaData, run, effectiveSecurityContext));
            }
        }
예제 #30
0
        private UserAccount GetTriggeringUser(WorkflowRun run)
        {
            if (run != null && run.TriggeringUser == null)
            {
                var deferredRun = run as WorkflowRunDeferred;
                if (deferredRun != null)
                {
                    return(deferredRun.GetTriggeringUser());
                }
            }

            if (run != null)
            {
                return(run.TriggeringUser);
            }

            return(null);
        }