public void TestPersistWithWrongStoreThrows() { var a = new Multiply() { X = 3, Y = 7, }; AutoResetEvent syncEvent = new AutoResetEvent(false); var app = new WorkflowApplication(a); app.InstanceStore = new SqlWorkflowInstanceStore("Server =localhost; Initial Catalog = WFXXX; Integrated Security = SSPI"); app.PersistableIdle = (eventArgs) => { Assert.True(false, "quick action no need to persist");//lazy return(PersistableIdleAction.Persist); }; //None of the handlers should be running app.OnUnhandledException = (e) => { return(UnhandledExceptionAction.Abort); }; var ex = Assert.Throws <System.Runtime.DurableInstancing.InstancePersistenceCommandException> (() => app.Persist(TimeSpan.FromSeconds(2))); Assert.NotNull(ex.InnerException); // Assert.Equal(typeof(TimeoutException), ex.InnerException.GetType()); sometimes is SqlException. }
static void StartAndUnloadInstance() { WorkflowApplication application = new WorkflowApplication(activity); application.InstanceStore = instanceStore; //returning IdleAction.Unload instructs the WorkflowApplication to persists application state and remove it from memory application.PersistableIdle = (e) => { return(PersistableIdleAction.Unload); }; application.Unloaded = (e) => { instanceUnloaded.Set(); }; //This call is not required //Calling persist here captures the application durably before it has been started application.Persist(); id = application.Id; application.Run(); instanceUnloaded.WaitOne(); }
public WorkflowApplication CreateWorkflow(Activity activity, IDictionary <string, object> inputs, Guid instanceId, bool notUseActivityStackTrace, bool usePersistAndLog) { if (_instances.Value.ContainsKey(instanceId)) { throw new DeveloperException("Процесс с кодом '{0}' уже существует.", instanceId); } var result = new WorkflowApplication(activity, inputs) { SynchronizationContext = SynchronizationContext.Current }; //Настраиваем Activity StackTrace ClearTrackingSource(); if (!notUseActivityStackTrace) { _trackingSource = new ActivityStackTrace(); result.Extensions.Add(CreateActivityTrackingParticipant()); } var traceExtension = new TraceExtension { NotUseActivityStackTrace = notUseActivityStackTrace, UsePersistAndLog = usePersistAndLog }; traceExtension.Set(TraceExtension.ParentWfInstanceIdPropertyName, instanceId); traceExtension.Set(TraceExtension.ActivityTrackingSourcePropertyName, _trackingSource); result.Extensions.Add(traceExtension); if (usePersistAndLog) { result.InstanceStore = new XmlWorkflowInstanceStore(result.Id); //Create the persistence Participant and add it to the workflow instance result.Extensions.Add(new XmlPersistenceParticipant(instanceId, result.Id)); //Add a tracking participant result.Extensions.Add(new SaveAllEventsToFileTrackingParticipant()); } _instances.Value.Add(instanceId, result); _keyLink.Value.Add(result.Id, instanceId); // пропишем события SubscribeEvents(result); if (usePersistAndLog) { result.Persist(); } return(result); }
public void TestPersistNonPersistable() { var a = new Multiply() { X = 3, Y = 7, }; bool completed1 = false; AutoResetEvent syncEvent = new AutoResetEvent(false); var app = new WorkflowApplication(a); app.InstanceStore = WFDefinitionStore.Instance.Store; app.PersistableIdle = (eventArgs) => { Assert.True(false, "quick action no need to persist");//lazy return(PersistableIdleAction.Persist); }; //None of the handlers should be running app.OnUnhandledException = (e) => { return(UnhandledExceptionAction.Abort); }; app.Completed = (e) => { completed1 = true; syncEvent.Set(); }; app.Unloaded = (e) => { Assert.True(false, "Nothing to persist"); }; app.Idle = e => { }; app.Persist(); var id = app.Id; app.Run(); syncEvent.WaitOne(); Assert.True(completed1); }
public void StartAndPersistInstance(Guid _documentId, DocumentState _state, IDictionary <string, object> documentData) { try { var documentTable = _DocumentService.Find(_documentId); IDictionary <string, object> inputArguments = new Dictionary <string, object>(); inputArguments.Add("inputStep", _state); inputArguments.Add("inputDocumentId", _documentId); inputArguments.Add("inputCurrentUser", HttpContext.Current.User.Identity.Name); inputArguments.Add("documentData", documentData); WorkflowApplication application = new WorkflowApplication(activity, inputArguments); application.InstanceStore = instanceStore; application.Extensions.Add(new WFTrackingParticipant()); #region Workflow Delegates application.PersistableIdle = (e) => { var ex = e.GetInstanceExtensions <WFTrackingParticipant>(); outputParameters = ex.First().Outputs; //instanceUnloaded.Set(); return(PersistableIdleAction.Unload); }; application.Unloaded = (e) => { instanceUnloaded.Set(); }; #endregion Workflow Delegates application.Persist(); application.Run(); instanceUnloaded.WaitOne(); documentTable.WWFInstanceId = application.Id; documentTable.DocumentState = (DocumentState)outputParameters["outputStep"]; _DocumentService.UpdateDocument(documentTable); } catch (Exception ex) { throw ex; } }
/// <summary> /// 创建并启动一个工作流,在申请时候触发 /// </summary> /// <param name="meeting">申请时所填表单的数据</param> /// <returns>返回一个Guid</returns> public static Guid CreateAndRun(Model.Meeting meeting, Dictionary <int, int> d_EquipmentCount, Dictionary <string, string> MeetingUserNameAndEmail, Model.MeetingRoom MeetingRoomIDAndName) { SqlWorkflowInstanceStore instanceStore = new SqlWorkflowInstanceStore(connectionString); InstanceView view = instanceStore.Execute(instanceStore.CreateInstanceHandle(), new CreateWorkflowOwnerCommand(), TimeSpan.FromDays(30)); instanceStore.DefaultInstanceOwner = view.InstanceOwner; IDictionary <string, object> input = new Dictionary <string, object>(); input.Add("Request", meeting); input.Add("EquipmentCount", d_EquipmentCount); input.Add("MeetingUserEmailFrom", MeetingUserNameAndEmail); input.Add("MeetingRoomIDAndName", MeetingRoomIDAndName); WorkflowApplication application = new WorkflowApplication(new MeetingApply(), input); application.InstanceStore = instanceStore; application.PersistableIdle = (e) => { instanceUnloaded.Set(); return(PersistableIdleAction.Unload); }; application.Unloaded = (e) => { instanceUnloaded.Set(); }; application.OnUnhandledException = (ex) => { return(UnhandledExceptionAction.Terminate); }; Guid id = application.Id; application.Persist(); application.Run(); instanceUnloaded.WaitOne(); return(id); }
/// <summary> /// Starts processing the given activity via the WorkflowApplication. /// </summary> /// <param name="command">The command to be ran.</param> /// <param name="firstParameter">The first parameter to include (if any).</param> /// <param name="secondParameter">The second parameter to include (if any).</param> /// <param name="thirdParameter">The third parameter to include (if any).</param> private void StartWorkflowScience(string command, string firstParameter, string secondParameter, string thirdParameter /* future use */) { // Now stage the WorkflowApplication, using the SQL instance, wrapped in using to dispose all of the things when done. using (AutoResetEvent syncEvent = new AutoResetEvent(false)) { // NOTE: If the string doesn't - explicitly - match, the .ctor() of the // SwedishCodeActivity will throw, since the string is the key. Also, // no boxing/unboxing required for Dictionary<T,T>; which saves overhead. Dictionary <string, SwedishCodeActivity <object> > newDictionary = new Dictionary <string, SwedishCodeActivity <object> > { // See the 'Activities' folder for examples of Activities that you can use here. { "CheckFreeDiskSpaceActivity", new CheckFreeDiskSpaceActivity() }, { "CopyFilesActivity", new CopyFilesActivity() }, { "CopyNIsAndDLLsActivity", new CopyImagesAndLibrariesActivity() }, { "DateTimeActivity", new UtcDateTimeActivity() }, { "DumpProcessThreadsActivity", new DumpProcessThreadsActivity() }, { "FileExistsActivity", new CheckIfFileExistsActivity() }, { "ForceBlueScreenActivity", new ForceBlueScreenActivity() }, { "GetLoggedOnUsersActivity", new GetCurrentLoggedOnUsersActivity() }, { "GetOsFileVersionActivity", new GetOsFileVersionActivity() }, { "GetProcessIdActivity", new GetProcessIdsActivity() }, { "GetSystemUptimeActivity", new GetSystemUptimeActivity() }, { "GetTimeSkewActivity", new GetSystemTimeSkewActivity() }, { "InstallSysInternalsActivity", new InstallSysInternalsActivity() }, { "ModifyConfigurationFileActivity", new EditConfigurationFileActivity() }, { "PingActivity", new PingResponseActivity() }, { "PortConnectivityActivity", new PortConnectivityActivity() }, { "ReadFileContentsActivity", new ReadFileContentsActivity() }, { "RenameMachineActivity", new RenameMachineActivity() }, { "RestartServiceActivity", new RestartServiceActivity() }, { "SetSymbolsEnvironmentPath", new SetSymbolServerEnvironmentPathActivity() }, { "StartSecureDeleteActivity", new StartSecureDeleteActivity() }, { "WindowsUpdateActivity", new WindowsUpdateActivity() }, { "WebStringActivity", new WebStringActivity() } }; SwedishCodeActivity <object> newSwedishCodeActivity = (SwedishCodeActivity <object>)newDictionary[command]; if (!string.IsNullOrWhiteSpace(firstParameter)) { newSwedishCodeActivity.FirstInArgument = firstParameter; } if (!string.IsNullOrWhiteSpace(secondParameter)) { newSwedishCodeActivity.SecondInArgument = secondParameter; } if (!string.IsNullOrWhiteSpace(thirdParameter)) { newSwedishCodeActivity.ThirdInArgument = thirdParameter; } SqlWorkflowInstanceStore newSqlWorkflowInstanceStore = new SqlWorkflowInstanceStore("Server=192.168.0.252,1433\\SQL2008EXPRESS;Initial Catalog=WorkflowInstanceStore;Integrated Security=SSPI") { HostLockRenewalPeriod = TimeSpan.FromSeconds(1), InstanceCompletionAction = InstanceCompletionAction.DeleteNothing, InstanceLockedExceptionAction = InstanceLockedExceptionAction.AggressiveRetry, RunnableInstancesDetectionPeriod = TimeSpan.FromSeconds(1) // Minimum allowed value. }; InstanceHandle workflowInstanceStoreHandle = newSqlWorkflowInstanceStore.CreateInstanceHandle(); CreateWorkflowOwnerCommand createWorkflowOwnerCommand = new CreateWorkflowOwnerCommand(); InstanceView newInstanceView = newSqlWorkflowInstanceStore.Execute(workflowInstanceStoreHandle, createWorkflowOwnerCommand, TimeSpan.FromSeconds(30)); newSqlWorkflowInstanceStore.DefaultInstanceOwner = newInstanceView.InstanceOwner; WorkflowApplication newWorkflowApplication = new WorkflowApplication(newSwedishCodeActivity, new WorkflowIdentity { // The Dictionary will throw for non-found key before we ever get here, so no need to validate input. Name = command, Version = new Version(0, 1, 0, 0) }) { InstanceStore = newSqlWorkflowInstanceStore, SynchronizationContext = SynchronizationContext.Current }; newWorkflowApplication.Persist(); ResultObject = new object(); newWorkflowApplication.Completed += delegate(WorkflowApplicationCompletedEventArgs e) { if (e.CompletionState == ActivityInstanceState.Faulted) { EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has faulted.\nException: {e.TerminationException.GetType().FullName}\nMessage:{e.TerminationException.Message}"); syncEvent.Set(); } else if (e.CompletionState == ActivityInstanceState.Canceled) { EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has been canceled."); syncEvent.Set(); } else { // Since the result can be *anything*, let's not treat it like a string. EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} completed. Result: {e.Outputs["Result"]}"); ResultObject = e.Outputs["Result"]; syncEvent.Set(); } }; newWorkflowApplication.Aborted = delegate(WorkflowApplicationAbortedEventArgs e) { // The workflow aborted, so let's find out why. EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has been aborted.\nException: {e.Reason.GetType().FullName}\nMessage:{e.Reason.Message}"); syncEvent.Set(); }; newWorkflowApplication.Idle = delegate(WorkflowApplicationIdleEventArgs e) { // TODO: [FUTURE] Need to handle future persistence maintenance. EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has entered the Idle state."); syncEvent.Set(); }; newWorkflowApplication.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e) { EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has entered PersistableIdle."); syncEvent.Set(); // Runtime will persist. return(PersistableIdleAction.Persist); }; newWorkflowApplication.Unloaded = delegate(WorkflowApplicationEventArgs e) { EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has been unloaded."); syncEvent.Set(); }; newWorkflowApplication.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e) { // Log the unhandled exception. EventLog.WriteEntry("Felsökning.Tomte.AdminService", !string.IsNullOrWhiteSpace(e.UnhandledException.InnerException?.Message) ? $"Workflow {e.InstanceId} has reached an AggregateException in OnUnhandledException.\nException Source: {e.ExceptionSource.DisplayName}\nException Instance ID: {e.ExceptionSourceInstanceId}\nException: {e.UnhandledException.InnerException.GetType().FullName}\nMessage: {e.UnhandledException.InnerException.Message}\nFirstArgument: {firstParameter}\nSecondArgument: {secondParameter}" : $"Workflow {e.InstanceId} has reached OnUnhandledException.\nException Source: {e.ExceptionSource.DisplayName}\nException Instance ID: {e.ExceptionSourceInstanceId}\nException: {e.UnhandledException.GetType().FullName}\nMessage: {e.UnhandledException.Message}\nFirstArgument: {firstParameter}\nSecondArgument: {secondParameter}"); syncEvent.Set(); // Instruct the runtime to terminate the workflow. // The other viable choices here are 'Abort' or 'Cancel' return(UnhandledExceptionAction.Terminate); }; newWorkflowApplication.Run(); // Because a new thread is spawned, we need to wait for it to complete before we can move on. syncEvent.WaitOne(); // Instance MUST be unloaded to update the SQL record. One would think this would happen on the overridden delegate methods (e.g.: Completed,OnUnhandledException, etc.) // but testing has proven this to not be the case. newWorkflowApplication.Unload(TimeSpan.FromSeconds(30)); // Now, we dump the instance owner. DeleteWorkflowOwnerCommand newDeleteWorkflowOwnerCommand = new DeleteWorkflowOwnerCommand(); newSqlWorkflowInstanceStore.Execute( workflowInstanceStoreHandle, newDeleteWorkflowOwnerCommand, TimeSpan.FromSeconds(30)); } GC.Collect(); }
public void LoadAOrCompleteInstance(Guid _documentId, DocumentState _state, TrackerType _trackerType, IDictionary <string, object> documentData) { var documentTable = _DocumentService.Find(_documentId); IEnumerable <WFTrackerTable> bookmarks; IDictionary <string, object> inputArguments = new Dictionary <string, object>(); inputArguments.Add("inputStep", _state); inputArguments.Add("inputCurrentUser", HttpContext.Current.User.Identity.Name); inputArguments.Add("documentData", documentData); WorkflowApplication application = new WorkflowApplication(activity); application.InstanceStore = instanceStore; application.Extensions.Add(new WFTrackingParticipant()); #region Workflow Delegates application.PersistableIdle = (e) => { var ex = e.GetInstanceExtensions <WFTrackingParticipant>(); outputParameters = ex.Last().Outputs; //instanceUnloaded.Set(); return(PersistableIdleAction.Unload); }; application.Completed = (e) => { outputParameters = e.Outputs; }; application.Unloaded = (workflowApplicationEventArgs) => { instanceUnloaded.Set(); }; #endregion Workflow Delegates application.Load(documentTable.WWFInstanceId); bookmarks = _DocumentService.GetCurrentSignStep(_documentId, HttpContext.Current.User.Identity.Name); if (bookmarks != null) { foreach (var bookmark in bookmarks) { application.ResumeBookmark(bookmark.ActivityName, inputArguments); application.Persist(); instanceUnloaded.WaitOne(); } } _DocumentService.SaveSignData(bookmarks, _trackerType); documentTable.WWFInstanceId = application.Id; documentTable.DocumentState = (DocumentState)outputParameters["outputStep"]; _DocumentService.UpdateDocument(documentTable); if (documentTable.DocumentState == DocumentState.Closed) { _EmailService.SendInitiatorClosedEmail(documentTable.Id); } }