// Save the workflow instance state at the point of persistence with option of locking the instance state if it is shared // across multiple runtimes or multiple phase instance updates protected override void SaveWorkflowInstanceState(Activity rootActivity, bool unlock) { // Save the workflow Guid contextGuid = (Guid)rootActivity.GetValue(Activity.ActivityContextGuidProperty); Console.WriteLine("Saving instance: {0}\n", contextGuid); SerializeToFile( WorkflowPersistenceService.GetDefaultSerializedForm(rootActivity), contextGuid); // See when the next timer (Delay activity) for this workflow will expire TimerEventSubscriptionCollection timers = (TimerEventSubscriptionCollection)rootActivity.GetValue(TimerEventSubscriptionCollection.TimerCollectionProperty); TimerEventSubscription subscription = timers.Peek(); if (subscription != null) { // Set a system timer to automatically reload this workflow when its next timer expires TimerCallback callback = new TimerCallback(ReloadWorkflow); TimeSpan timeDifference = subscription.ExpiresAt - DateTime.UtcNow; // check to make sure timeDifference is in legal range if (timeDifference > FilePersistenceService.MaxInterval) { timeDifference = FilePersistenceService.MaxInterval; } else if (timeDifference < TimeSpan.Zero) { timeDifference = TimeSpan.Zero; } this.instanceTimers.Add(contextGuid, new System.Threading.Timer( callback, subscription.WorkflowInstanceId, timeDifference, new TimeSpan(-1))); } }
// Save the workflow instance state at the point of persistence with option of locking the instance state if it is shared // across multiple runtimes or multiple phase instance updates protected override void SaveWorkflowInstanceState(Activity rootActivity, bool unlock) { // Save the workflow var contextId = (Guid)rootActivity.GetValue(Activity.ActivityContextGuidProperty); _instanceStore[contextId] = GetDefaultSerializedForm(rootActivity); // See when the next timer (Delay activity) for this workflow will expire var timers = (TimerEventSubscriptionCollection)rootActivity.GetValue(TimerEventSubscriptionCollection.TimerCollectionProperty); TimerEventSubscription subscription = timers.Peek(); if (subscription != null) { // Set a system timer to automatically reload this workflow when its next timer expires TimeSpan timeDifference = subscription.ExpiresAt - DateTime.UtcNow; // check to make sure timeDifference is in legal range if (timeDifference > MaxInterval) { timeDifference = MaxInterval; } else if (timeDifference < TimeSpan.Zero) { timeDifference = TimeSpan.Zero; } _instanceTimers.Add(contextId, new Timer( ReloadWorkflow, subscription.WorkflowInstanceId, timeDifference, new TimeSpan(-1))); } }
void IEventActivity.Subscribe(ActivityExecutionContext parentContext, IActivityEventListener <QueueEventArgs> parentEventHandler) { if (parentContext == null) { throw new ArgumentNullException("parentContext"); } if (parentEventHandler == null) { throw new ArgumentNullException("parentEventHandler"); } this.IsInEventActivityMode = true; base.RaiseEvent(InitializeTimeoutDurationEvent, this, EventArgs.Empty); TimeSpan timeoutDuration = this.TimeoutDuration; DateTime expiresAt = DateTime.UtcNow + timeoutDuration; WorkflowQueuingService service = parentContext.GetService <WorkflowQueuingService>(); IComparable queueName = ((IEventActivity)this).QueueName; TimerEventSubscription item = new TimerEventSubscription((Guid)queueName, base.WorkflowInstanceId, expiresAt); service.CreateWorkflowQueue(queueName, false).RegisterForQueueItemAvailable(parentEventHandler, base.QualifiedName); this.SubscriptionID = item.SubscriptionId; Activity parent = this; while (parent.Parent != null) { parent = parent.Parent; } ((TimerEventSubscriptionCollection)parent.GetValue(TimerEventSubscriptionCollection.TimerCollectionProperty)).Add(item); }
/// <summary> /// Persist a workflow instance to the persistence store. /// </summary> /// <param name="rootActivity"> /// Root activity of the workflow instance. /// </param> /// <param name="unlock"> /// Indicates whether to unlock the instance when complete. /// </param> protected override void SaveWorkflowInstanceState(Activity rootActivity, bool unlock) { TraceHelper.Trace(); try { if (rootActivity == null) { throw new ArgumentNullException("rootActivity"); } PendingWorkItem workItem = new PendingWorkItem(); workItem.Status = GetWorkflowStatus(rootActivity); workItem.IsBlocked = GetIsBlocked(rootActivity); workItem.Info = GetSuspendOrTerminateInfo(rootActivity); workItem.StateId = (Guid)rootActivity.GetValue(Activity.ActivityContextGuidProperty); workItem.Type = PendingWorkItem.ItemType.Instance; workItem.InstanceId = WorkflowEnvironment.WorkflowInstanceId; workItem.Unlock = unlock; if (workItem.Status != WorkflowStatus.Completed && workItem.Status != WorkflowStatus.Terminated) { workItem.SerialisedActivity = GetDefaultSerializedForm(rootActivity); } else { workItem.SerialisedActivity = new byte[0]; } TimerEventSubscription timerEventSubscription = ((TimerEventSubscriptionCollection)rootActivity.GetValue( TimerEventSubscriptionCollection.TimerCollectionProperty)).Peek(); if (timerEventSubscription == null) { workItem.NextTimer = null; } else { workItem.NextTimer = timerEventSubscription.ExpiresAt; } WorkflowEnvironment.WorkBatch.Add(this, workItem); } catch (Exception e) { WfLogHelper.WriteLog("持久化SaveWorkflowInstanceState发生异常:" + e.ToString()); string errorMessage = RM.Get_Error_PersistenceServiceException(e.ToString()); TraceHelper.Trace(errorMessage); PersistenceException persistenceException = new PersistenceException(errorMessage, e); base.RaiseServicesExceptionNotHandledEvent( persistenceException, WorkflowEnvironment.WorkflowInstanceId); throw persistenceException; } }
public void Constructor2() { TimerEventSubscription timer; Guid workflowInstanceId = Guid.NewGuid(); DateTime expiresAt = DateTime.Today; timer = new TimerEventSubscription(workflowInstanceId, expiresAt); Assert.AreEqual(workflowInstanceId, timer.WorkflowInstanceId, "C1#1"); Assert.AreEqual(timer.SubscriptionId, timer.QueueName, "C1#2"); }
public void TestCollection() { TimerEventSubscriptionCollection col; // There is no public constructor for TimerEventSubscriptionCollection col = (TimerEventSubscriptionCollection)Activator.CreateInstance (typeof(TimerEventSubscriptionCollection), BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, null, null); TimerEventSubscription event1 = new TimerEventSubscription(Guid.NewGuid(), new DateTime(2006, 07, 30)); TimerEventSubscription event2 = new TimerEventSubscription(Guid.NewGuid(), new DateTime(2006, 07, 28)); TimerEventSubscription event3 = new TimerEventSubscription(Guid.NewGuid(), new DateTime(2006, 08, 28)); TimerEventSubscription event4 = new TimerEventSubscription(Guid.NewGuid(), new DateTime(2007, 08, 28)); TimerEventSubscription event5 = new TimerEventSubscription(Guid.NewGuid(), new DateTime(2006, 05, 28)); TimerEventSubscription event6 = new TimerEventSubscription(Guid.NewGuid(), new DateTime(2008, 02, 28)); TimerEventSubscription event7 = new TimerEventSubscription(Guid.NewGuid(), new DateTime(2005, 05, 28)); col.Add(event1); col.Add(event2); col.Add(event3); col.Add(event4); col.Add(event5); col.Add(event6); col.Add(event7); Assert.AreEqual(event7.ExpiresAt, col.Peek().ExpiresAt, "C1#1"); col.Remove(col.Peek()); Assert.AreEqual(event5.ExpiresAt, col.Peek().ExpiresAt, "C1#2"); col.Remove(col.Peek()); Assert.AreEqual(event2.ExpiresAt, col.Peek().ExpiresAt, "C1#3"); col.Remove(col.Peek()); Assert.AreEqual(event1.ExpiresAt, col.Peek().ExpiresAt, "C1#4"); col.Remove(col.Peek()); Assert.AreEqual(event3.ExpiresAt, col.Peek().ExpiresAt, "C1#5"); col.Remove(col.Peek()); Assert.AreEqual(event4.ExpiresAt, col.Peek().ExpiresAt, "C1#6"); }
protected IComparable SetTimer(ActivityExecutionContext executionContext, DateTime expiresAt) { #if RUNTIME_DEP TimerEventSubscription te; WorkflowQueue queue; te = new TimerEventSubscription(executionContext.ExecutionContextManager.Workflow.InstanceId, expiresAt); WorkflowQueuingService qService = executionContext.GetService <WorkflowQueuingService> (); queue = qService.CreateWorkflowQueue(te.QueueName, true); queue.QueueItemArrived += OnQueueTimerItemArrived; executionContext.ExecutionContextManager.Workflow.TimerEventSubscriptionCollection.Add(te); return(te.QueueName); #else return(null); #endif }
void IEventActivity.Subscribe(ActivityExecutionContext parentContext, IActivityEventListener <QueueEventArgs> parentEventHandler) { if (parentContext == null) { throw new ArgumentNullException("parentContext"); } if (parentEventHandler == null) { throw new ArgumentNullException("parentEventHandler"); } this.IsInEventActivityMode = true; base.RaiseEvent(DelayActivity.InitializeTimeoutDurationEvent, this, EventArgs.Empty); TimeSpan timeSpan = this.TimeoutDuration; DateTime timeOut = DateTime.UtcNow + timeSpan; WorkflowQueuingService qService = parentContext.GetService <WorkflowQueuingService>(); IComparable queueName = ((IEventActivity)this).QueueName; TimerEventSubscription timerSub = new TimerEventSubscription((Guid)queueName, this.WorkflowInstanceId, timeOut); WorkflowQueue queue = qService.CreateWorkflowQueue(queueName, false); queue.RegisterForQueueItemAvailable(parentEventHandler, this.QualifiedName); this.SubscriptionID = timerSub.SubscriptionId; Activity root = this; while (root.Parent != null) { root = root.Parent; } TimerEventSubscriptionCollection timers = (TimerEventSubscriptionCollection)root.GetValue(TimerEventSubscriptionCollection.TimerCollectionProperty); Debug.Assert(timers != null, "TimerEventSubscriptionCollection on root activity should never be null, but it was"); timers.Add(timerSub); }
protected internal override void SaveWorkflowInstanceState(Activity rootActivity, bool unlock) { if (rootActivity == null) { throw new ArgumentNullException("rootActivity"); } WorkflowStatus workflowStatus = WorkflowPersistenceService.GetWorkflowStatus(rootActivity); bool isBlocked = WorkflowPersistenceService.GetIsBlocked(rootActivity); string suspendOrTerminateInfo = WorkflowPersistenceService.GetSuspendOrTerminateInfo(rootActivity); Guid guid = (Guid)rootActivity.GetValue(Activity.ActivityContextGuidProperty); PendingWorkItem workItem = new PendingWorkItem { Type = PendingWorkItem.ItemType.Instance, InstanceId = WorkflowEnvironment.WorkflowInstanceId }; if ((workflowStatus != WorkflowStatus.Completed) && (workflowStatus != WorkflowStatus.Terminated)) { workItem.SerializedActivity = WorkflowPersistenceService.GetDefaultSerializedForm(rootActivity); } else { workItem.SerializedActivity = new byte[0]; } workItem.Status = (int)workflowStatus; workItem.Blocked = isBlocked ? 1 : 0; workItem.Info = suspendOrTerminateInfo; workItem.StateId = guid; workItem.Unlocked = unlock; TimerEventSubscription subscription = ((TimerEventSubscriptionCollection)rootActivity.GetValue(TimerEventSubscriptionCollection.TimerCollectionProperty)).Peek(); workItem.NextTimer = (subscription == null) ? SqlDateTime.MaxValue : subscription.ExpiresAt; if (workItem.Info == null) { workItem.Info = ""; } WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SqlWorkflowPersistenceService({4}):Committing instance {0}, Blocked={1}, Unlocked={2}, NextTimer={3}", new object[] { guid.ToString(), workItem.Blocked, workItem.Unlocked, workItem.NextTimer.Value.ToLocalTime(), this._serviceInstanceId.ToString() }); WorkflowEnvironment.WorkBatch.Add(this, workItem); }