///<summary> ///Commits the list of work items by using the specified <see cref="T:System.Transactions.Transaction"></see> object. ///</summary> /// ///<param name="items">The work items to be committed.</param> ///<param name="transaction">The <see cref="T:System.Transactions.Transaction"></see> associated with the pending work.</param> public void Commit(Transaction transaction, ICollection items) { TraceHelper.Trace(); if (transaction == null) { throw new ArgumentNullException("transaction"); } if (items == null) { throw new ArgumentNullException("items"); } try { using (IPersistenceResourceAccessor resourceAccessor = CreateAccessor(_resourceProvider, transaction)) { foreach (PendingWorkItem item in items) { switch (item.Type) { case PendingWorkItem.ItemType.Instance: resourceAccessor.InsertInstanceState(item, _serviceId, ownershipTimeout); continue; case PendingWorkItem.ItemType.CompletedScope: resourceAccessor.InsertCompletedScope( item.InstanceId, item.StateId, item.SerialisedActivity); continue; case PendingWorkItem.ItemType.UnlockWorkflow: resourceAccessor.UnlockInstanceState( item.InstanceId, _serviceId); continue; } } } } catch (Exception e) { String errorMessage = RM.Get_Error_PersistenceServiceException(e.ToString()); TraceHelper.Trace(errorMessage); PersistenceException persistenceException = new PersistenceException(errorMessage, e); RaiseServicesExceptionNotHandledEvent( persistenceException, Guid.Empty); throw persistenceException; } }
///<summary> ///Called when the transaction has completed. ///</summary> /// ///<param name="items">An <see cref="T:System.Collections.ICollection"></see> of work items.</param> ///<param name="succeeded">true if the transaction succeeded; otherwise, false.</param> public void Complete(Boolean succeeded, ICollection items) { TraceHelper.Trace(); try { if (succeeded) { foreach (PendingWorkItem item in items) { if (item.Type == PendingWorkItem.ItemType.Instance && item.NextTimer != null) { _smartTimer.Update(item.NextTimer.Value); } } } } catch (Exception e) { String errorMessage = RM.Get_Error_PersistenceServiceException(e.ToString()); TraceHelper.Trace(errorMessage); PersistenceException persistenceException = new PersistenceException(errorMessage, e); RaiseServicesExceptionNotHandledEvent( persistenceException, Guid.Empty); throw persistenceException; } }
/// <summary> /// Persist a completed scope to the persistence store. /// </summary> /// <param name="activity"> /// The completed scope to pesist. /// </param> protected override void SaveCompletedContextActivity(Activity activity) { TraceHelper.Trace(); try { PendingWorkItem workItem = new PendingWorkItem(); workItem.Type = PendingWorkItem.ItemType.CompletedScope; workItem.SerialisedActivity = GetDefaultSerializedForm(activity); workItem.InstanceId = WorkflowEnvironment.WorkflowInstanceId; workItem.StateId = (Guid)activity.GetValue( Activity.ActivityContextGuidProperty); WorkflowEnvironment.WorkBatch.Add(this, workItem); } catch (Exception e) { String errorMessage = RM.Get_Error_PersistenceServiceException(e.ToString()); TraceHelper.Trace(errorMessage); PersistenceException persistenceException = new PersistenceException(errorMessage, e); RaiseServicesExceptionNotHandledEvent( persistenceException, WorkflowEnvironment.WorkflowInstanceId); throw persistenceException; } }
/// <summary> /// Load a completed scope from the persistence store. /// </summary> /// <param name="scopeId"> /// <see cref="Guid" /> representing the unique identifier of the completed scope. /// </param> /// <param name="outerActivity"> /// The activity in which to load the completed scope into. /// </param> protected override Activity LoadCompletedContextActivity(Guid scopeId, Activity outerActivity) { TraceHelper.Trace(); Activity contextActivity; try { using (IPersistenceResourceAccessor resourceAccessor = CreateAccessor(_resourceProvider)) { byte[] instanceState = resourceAccessor.RetrieveCompletedScope(scopeId); contextActivity = RestoreFromDefaultSerializedForm(instanceState, outerActivity); } } catch (Exception e) { String errorMessage = RM.Get_Error_PersistenceServiceException(e.ToString()); TraceHelper.Trace(errorMessage); PersistenceException persistenceException = new PersistenceException(errorMessage, e); RaiseServicesExceptionNotHandledEvent( persistenceException, WorkflowEnvironment.WorkflowInstanceId); throw persistenceException; } return(contextActivity); }
/// <summary> /// Unlock a workflow instance. /// </summary> /// <param name="rootActivity"> /// The root activity of the workflow instance. /// </param> protected override void UnlockWorkflowInstanceState(Activity rootActivity) { TraceHelper.Trace(); try { PendingWorkItem workItem = new PendingWorkItem(); workItem.Type = PendingWorkItem.ItemType.UnlockWorkflow; workItem.InstanceId = WorkflowEnvironment.WorkflowInstanceId; WorkflowEnvironment.WorkBatch.Add(this, workItem); } catch (Exception e) { String errorMessage = RM.Get_Error_PersistenceServiceException(e.ToString()); TraceHelper.Trace(errorMessage); PersistenceException persistenceException = new PersistenceException(errorMessage, e); RaiseServicesExceptionNotHandledEvent( persistenceException, WorkflowEnvironment.WorkflowInstanceId); throw persistenceException; } }
///<summary> /// Load the specified workflow instance into memory from the /// persistence store. ///</summary> ///<param name="instanceId"> /// The <see cref="T:System.Guid"></see> of the root activity of the workflow instance. /// </param> protected override Activity LoadWorkflowInstanceState(Guid instanceId) { TraceHelper.Trace(); Activity rootActivity; try { using (IPersistenceResourceAccessor resourceAccessor = CreateAccessor(_resourceProvider)) { byte[] instanceState = resourceAccessor.RetrieveInstanceState( instanceId, _serviceId, ownershipTimeout); rootActivity = RestoreFromDefaultSerializedForm(instanceState, null); } } catch (Exception e) { String errorMessage = RM.Get_Error_PersistenceServiceException(e.ToString()); TraceHelper.Trace(errorMessage); PersistenceException persistenceException = new PersistenceException(errorMessage, e); RaiseServicesExceptionNotHandledEvent( persistenceException, instanceId); throw persistenceException; } return(rootActivity); }
/// <summary> /// Kick-off the timer to check for workflows with expired timers, /// and recover running workflow instances. /// </summary> protected override void OnStarted() { TraceHelper.Trace(); try { base.OnStarted(); if (_loadInterval > TimeSpan.Zero) { lock (_timerLock) { _smartTimer = new SmartTimer( loadWorkflowsWithExpiredTimers, null, _loadInterval, _loadInterval); } } recoverRunningWorkflows(); } catch (Exception e) { String errorMessage = RM.Get_Error_PersistenceServiceException(e.ToString()); TraceHelper.Trace(errorMessage); PersistenceException persistenceException = new PersistenceException(errorMessage, e); RaiseServicesExceptionNotHandledEvent( persistenceException, Guid.Empty); throw persistenceException; } }
/// <summary> /// Perform shutdown duties associated with this persistence service. /// <remarks> /// This implementation disposes the internal <see cref="SmartTimer" /> /// responsible for loading expired workflows into memory. /// </remarks> /// </summary> protected override void Stop() { TraceHelper.Trace(); try { base.Stop(); lock (_timerLock) { if (_smartTimer != null) { _smartTimer.Dispose(); _smartTimer = null; } } } catch (Exception e) { String errorMessage = RM.Get_Error_PersistenceServiceException(e.ToString()); TraceHelper.Trace(errorMessage); PersistenceException persistenceException = new PersistenceException(errorMessage, e); RaiseServicesExceptionNotHandledEvent( persistenceException, Guid.Empty); throw persistenceException; } }
/// <summary> /// Perform startup duties associated with this persistence service. /// <remarks> /// This implementation calls a virtual method to create a single /// resource provider for this persistence service. /// </remarks> /// </summary> protected override void Start() { TraceHelper.Trace(); try { // retrieve the active resource provider _resourceProvider = CreateResourceProvider(); base.Start(); } catch (Exception e) { String errorMessage = RM.Get_Error_PersistenceServiceException(e.ToString()); TraceHelper.Trace(errorMessage); PersistenceException persistenceException = new PersistenceException(errorMessage, e); RaiseServicesExceptionNotHandledEvent( persistenceException, Guid.Empty); throw persistenceException; } }
///<summary> ///Called when the transaction has completed. ///</summary> /// ///<param name="items">An <see cref="T:System.Collections.ICollection"></see> of work items.</param> ///<param name="succeeded">true if the transaction succeeded; otherwise, false.</param> public void Complete(bool succeeded, ICollection items) { TraceHelper.Trace(); try { if (succeeded) { foreach (PendingWorkItem item in items) { if (item.Type == PendingWorkItem.ItemType.Instance && item.NextTimer != null) { this.smartTimer.Update(item.NextTimer.Value); } } WfLogHelper.WriteLog("持久化提交事务Complete完成......"); } } catch (Exception e) { WfLogHelper.WriteLog("持久化Complete务发生异常:" + e.ToString()); string errorMessage = RM.Get_Error_PersistenceServiceException(e.ToString()); TraceHelper.Trace(errorMessage); PersistenceException persistenceException = new PersistenceException(errorMessage, e); base.RaiseServicesExceptionNotHandledEvent( persistenceException, Guid.Empty); throw persistenceException; } }
/// <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; } }
/// <summary> /// Retrieve instance state from the persistence store. /// </summary> /// <param name="instanceId"></param> /// <param name="ownerId"></param> /// <param name="ownedUntil"></param> /// <returns></returns> public byte[] RetrieveInstanceState(Guid instanceId, Guid ownerId, DateTime ownedUntil) { byte[] instanceState = null; using (DbCommand dbCommand = CreateCommand(nameResolver.ResolveCommandName(PersistenceCommandName.RetrieveInstanceState), CommandType.StoredProcedure)) { string instanceParameter = nameResolver.ResolveParameterName( PersistenceCommandName.InsertInstanceState, PersistenceParameterName.InstanceId); string resultParameter = nameResolver.ResolveParameterName( PersistenceCommandName.InsertInstanceState, PersistenceParameterName.Result); AddParameter(dbCommand, instanceParameter, instanceId, AdoDbType.Guid); AddParameter(dbCommand, nameResolver.ResolveParameterName( PersistenceCommandName.RetrieveInstanceState, PersistenceParameterName.OwnerId), ownerId, AdoDbType.Guid); AddParameter(dbCommand, nameResolver.ResolveParameterName( PersistenceCommandName.RetrieveInstanceState, PersistenceParameterName.OwnedUntil), ownedUntil, AdoDbType.DateTime); AddParameter(dbCommand, resultParameter, AdoDbType.Int32, ParameterDirection.Output); AddParameter(dbCommand, nameResolver.ResolveParameterName( PersistenceCommandName.RetrieveInstanceState, PersistenceParameterName.CurrentOwnerId), AdoDbType.Guid, ParameterDirection.Output); AddParameter(dbCommand, nameResolver.ResolveParameterName( PersistenceCommandName.RetrieveInstanceState, PersistenceParameterName.State), AdoDbType.Cursor, ParameterDirection.Output); int? result; using (IDataReader dataReader = dbCommand.ExecuteReader()) { if (dataReader.Read()) instanceState = (byte[])valueReader.GetValue(dataReader, 0); result = valueReader.GetNullableInt32(dbCommand, resultParameter); } if (instanceState == null && result > 0) { // workflow could not be found PersistenceException e = new PersistenceException( RM.Get_Error_InstanceCouldNotBeLoaded(instanceId)); e.Data["WorkflowNotFound"] = true; Tracer.Debug("����ʵ��״̬ public byte[] RetrieveInstanceState(" + instanceId + ", " + ownerId + ", " + ownedUntil + ")�����쳣:" + e.ToString()); throw e; } else checkResult(dbCommand, resultParameter, instanceParameter); } return instanceState; }