SQLTracking and Persistence
Hi,
At the moment, I can't make SQLTracking and SQLPersistenceService work together. Here are my situation:
Situation 1 - SDK (v6.0) Sample : Technologies\Hosting\PersistenceServices
When I run the Sample, it works ok, so I tried to add the TrackingService to it with the following VB.NET Code:
Dim TrackingService As New SqlTrackingService(TrackingStoreConnectionString)
currentWorkflowRuntime.AddService(TrackingService)
I didn't write any code to add Tracking Profile yet. But this time when I run the application, it stopped at the line:
Workflow is idle
And then keep on wating. No persistence occur. Why?
Situation 2 - ASP.NET (State Machin Workflow)
I have an ASP.NET page which start the workflow like this:
Dim WFR As WorkflowRuntime = Nothing
Dim Scheduler As ManualWorkflowSchedulerService = Nothing
Dim DataService As ExternalDataExchangeService = Nothing
WFR = New WorkflowRuntime
WFR = Application("Workflowruntime")
Scheduler = WFR.GetService(Of ManualWorkflowSchedulerService)()
DataService = WFR.GetService(Of ExternalDataExchangeService)()
ClaimService = WFR.GetService(Of ClaimSubmissionFlow.ClaimService)()
If ClaimService Is Nothing Then
ClaimService = New ClaimSubmissionFlow.ClaimService
DataService.AddService(ClaimService)
End If
Dim WorkflowInstance As WorkflowInstance = WFR.CreateWorkflow(GetType(ClaimSubmissionFlow.ClaimSubmission))
WorkflowInstance.Start()
Scheduler.RunWorkflow(WorkflowInstance.InstanceId)
ClaimService.RaiseClaim(WorkflowInstance.InstanceId, 50)
Scheduler.RunWorkflow(WorkflowInstance.InstanceId)
It works fine, and the workflow instance can be sucessfully persisted. Then I added the Tracking Service to the Web.Config like this:
<add type="System.Workflow.Runtime.Tracking.SqlTrackingService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" ConnectionString="Data Source=MYPC\SQLEXPRESS;Initial Catalog=WorkflowTrackingStore;User ID=AppUser;password=SysPass;"/>
Again, I didn't write any code to add tracking profile. And try to run the page again, but this time, I got an error message:
Sometimes I got an ASP.NET error page with error message:
Workflow with id "546da577-cb03-41d9-8466-717651612883" not found in state persistence store.
Sometimes I got an Debug error from VS.NET : EventDeliveryFailedException:
Event "NewClaim" on interface type "ClaimSubmissionFlow.IClaim" for instance id "e30d474f-9de0-4b5d-a6f2-4fef52acf407" cannot be delivered.
Any ides? Please help.
Andy
[3527 byte] By [
AndyHo] at [2007-12-23]
I don't know if this has anything to do with your particular tracking/persistence situation, but in my personal experience , the
Event "blahblah" on interface type "blahblah" ... message typically means that the EventArgs or the Exchange Service are not Serializable.
This does indeed sound like there is a problem persisting the instance. First thing to do is to start with a clean environment. Rebuild your persistence and tracking databases (re-run the *schema.sql files) and make sure that your connection strings are correct. If both tracking and persistence are in the same database (which we generally recommend) then you can use add the SharedConnectionWorkflowCommitWorkBatch service to your runtime. Using this service avoids the use of a distributed transaction and multiple concurrent sql connections for a single instance persistence point. If you need separate databases make sure that DTC is enabled on your machine. My guess is that the reason persistence fails in this case is that the transaction is being escalated to a DTC and failing.
Thanks,
Joel West
MS SDE in WF runtime and hosting
This posting is provided "AS IS" with no warranties, and confers no rights
Joel,
Many thanks.
I enabled the DTC with the following steps (info. obtained from Microsoft):
Because the Microsoft Distributed Transaction Coordinator (MS DTC) is not completely configured in Windows, applications might fail to enlist SQL Server Express resources in a distributed transaction. This problem can affect linked servers, distributed queries, and remote stored procedures that use distributed transactions. To prevent such problems, you must fully enable MS DTC services on the server where SQL Server Express is installed.
To enable MS DTC fully:
1. In Control Panel, open Administrative Tools, and then double-click Component Services.
2. In the left pane of Console Root, click Component Services, and then expand Computers.
3. Right-click My Computer, and then click Properties.
4. On the MSDTC tab, click Security Configuration.
5. Under Security Settings, select all of the check boxes.
6. Verify that the DTC Logon Account name is set to NT AUTHORITY\NetworkService.
Everything just work well.
But I have a few more questions:
1) For Sequential Workflow, I can track the Instance History without using SQLPersistenceService, but for the Statemachine workflow, I must start the SQLPersistenceService before I can get the tracking history, is that true?
2) In Beta 2.2, I remember we have the script to create the SharedPersistenceAndTracking database. But for the RC version, where can we get the Sql Script to generate the Shared store?
3) After the workflow completion, we can get the Output Properties within the workflow instance with e.OutputParameters("ClaimAmount"). But before the completion, how can be get the properties (such as the Claim Amount we send to the workflow when we start the workflow) from the Workflow Tracking / Persistence database? For example, I want to show all the outstanding claim approval workflow instances and their claim amount, how to do that?
4) From the Persistence Store, how can we know the Name and type (Sequential or Statemachine) of an workflow instance? Because if it is a Sequential Workflow instance, we can't make use of the Statemachineinstance to check its latest Status.
Sorry for too many question. Hope you can help.
Thanks in advance.
Andy Ho
Glad to hear you got this working. A disabled DTC is usually the culprit in case like this. Additional answers below:
1) For Sequential Workflow, I can track the Instance History without using SQLPersistenceService, but for the Statemachine workflow, I must start the SQLPersistenceService before I can get the tracking history, is that true?
>> No, this is not true. However what you're seeing may be because the default behavior of the SqlTrackingService is to batch up events and write them to the database at the each persistence point. This achieves better performance and guarantees that the state that you see in tracking is always consistent with the committed state checkpoint stored in persistence. You may be seeing the difference between when a sequential workflow persists and when a state machine persists. If you let both types run to completion you should see tracking data for both with or without a persistence service.
2) In Beta 2.2, I remember we have the script to create the SharedPersistenceAndTracking database. But for the RC version, where can we get the Sql Script to generate the Shared store?
>> There is no script to create a database. You need to create the database yourself and then run the persistence and tracking .sql scripts in it. We strongly recommend that you use the same database for both the SqlWorkflowPersistencService and the SqlTrackingService.
3) After the workflow completion, we can get the Output Properties within the workflow instance with e.OutputParameters("ClaimAmount"). But before the completion, how can be get the properties (such as the Claim Amount we send to the workflow when we start the workflow) from the Workflow Tracking / Persistence database? For example, I want to show all the outstanding claim approval workflow instances and their claim amount, how to do that?
>> The recommendation is to use tracking to expose data from the workflow instance. To get data from the workflow written to the tracking database you need to author a profile that uses Activity or Workflow TrackingDataExtracts. The tracking samples have examples of how this works.
4) From the Persistence Store, how can we know the Name and type (Sequential or Statemachine) of an workflow instance? Because if it is a Sequential Workflow instance, we can't make use of the Statemachineinstance to check its latest Status.
>> The SqlWorkflowPersistenceService does not store these kinds of details. The SqlTrackingService however does store things like this.
Thanks,
Joel West
MSFTE - SDE in WF runtime and hosting
This posting is provided "AS IS" with no warranties, and confers no rights
Joel,
First of all, thank for your reply.
1) But the fact is I can't get any tracking data from an State Machine workflow instance without adding the SQLPersistenceService (I can get the Track Data without using the Persistence servce with the same code but only for Sequential Workflow)? Or is there any way to configure the Batch Up behaviour of the Tracking Service?
2) I see. Thanks and I will try to make the Shared Store by myself.
3) Means that we need to EXPOSE the value by ourselves? As everything should be serialized and stored in the Tracking/Persistence database, what I assume is there should be some way to get the values back easily. I have tried to use the User Track Point to expose the data, but it is not very easy for me to get only the "Latest" value (as the data are tracked based on Activity). Anyway, I will try the tracking samples again and focus on the TrackingDataExtracts issue. Hope can solve this quickly as it is so importance to a workflow host application.
4) I see. But right now I don't know how to list all outstanding workflow instances with Tracking Service (currently I'm using the SQLPersistenceService to list all persisted workflow instances). Anyway, do you have any sample code on my 3) and 4) questions?
Thanks again.
Andy
I had the same problem. The solution was adding the SharedConnectionWorkflowCommitWorkBatchService to the runtime as well. It seems to be some connection string sharing problem.
1) But the fact is I can't get any tracking data from an State Machine workflow instance without adding the SQLPersistenceService (I can get the Track Data without using the Persistence servce with the same code but only for Sequential Workflow)? Or is there any way to configure the Batch Up behaviour of the Tracking Service?
>> It's possible that without a persistence service we're not persisting because we don't detect that there is anything to persist. The behavior the the SqlTrackingService cannot be changed in this scenario.
3) Means that we need to EXPOSE the value by ourselves? As everything should be serialized and stored in the Tracking/Persistence database, what I assume is there should be some way to get the values back easily. I have tried to use the User Track Point to expose the data, but it is not very easy for me to get only the "Latest" value (as the data are tracked based on Activity). Anyway, I will try the tracking samples again and focus on the TrackingDataExtracts issue. Hope can solve this quickly as it is so importance to a workflow host application.
>> The TrackingDataExtracts classes are the recommended way to get hold of and save the values that you need from data members in your workflow/activities.
4) I see. But right now I don't know how to list all outstanding workflow instances with Tracking Service (currently I'm using the SQLPersistenceService to list all persisted workflow instances). Anyway, do you have any sample code on my 3) and 4) questions?
>> SELECT WorkflowInstanceId FROM WorkflowInstance WHERE EndDateTime IS NULL
Thanks,
Joel West
MSFTE - SDE in WF runtime and hosting
This posting is provided "AS IS" with no warranties, and confers no rights
I had the same problem. The solution was adding the SharedConnectionWorkflowCommitWorkBatchService to the runtime as well. It seems to be some connection string sharing problem.
There isn't a problem here in regards to connections or connection strings.. If you open two connections and enlist both in the same transaction it is likely that that transaction will propegate to a DTC. DTC needs to be configured correctly on your machine. Using the SharedConnectionWorkflowCommitWorkBatchService appears to solve the problem because this service allows the same underlying connection to be used by both the SqlTrackingService and the SqlWorkflowPersistenceService. This means that only one connection is used so the transaction doesn't need to be propegated to a DTC. So this doesn't fix the problem (which is that DTC is disable) you just never hit the problem because you no longer need DTC functionality.
Thanks,
Joel West
MSFTE - SDE in WF runtime and hosting
This posting is provided "AS IS" with no warranties, and confers no rights
Wow! Thanks for detailed desciption.
Daniel
I'm writing a Windows service that will run thousands, if not millions, of workflows.
It must persist the workflows during delays, and reload them as needed, because of memory constraints.
When the service is stopped, and then restarted, I'm not able to see any new entries in the persistence database, in the instancestate table. The other workflowinstance table does have new entries.
When I try to rehydrate/reload the objects after a service restart, I get a 'state not found' error.
What's causing this error? The unloadonidle flag is set to true in the sqlpersistenceservice constructor.
I'm using the RTM build of WWF.
Hi Joel,
Iam using a custom persistence service.
Iam persisting the instance by serializing it and successflly loading the instance back,using,
protected
override void SaveWorkflowInstanceState(Activity rootActivity, bool unlock){
Guid
contextGuid = (Guid)rootActivity.GetValue(Activity.ActivityContextGuidProperty); SerializeToFile(WorkflowPersistenceService.GetDefaultSerializedForm(rootActivity), contextGuid);
And
protected
override Activity LoadWorkflowInstanceState(Guid instanceId)
{
byte[] workflowBytes = DeserializeFromFile(instanceId);
Activity ac = WorkflowPersistenceService.RestoreFromDefaultSerializedForm(workflowBytes, null);
return WorkflowPersistenceService.RestoreFromDefaultSerializedForm(workflowBytes, null);
}
1) what i want to know is how can i access the information of instance after deserialization (like i want to know name property,address property)?
2)how can i store the instance data in a table (instead of serializing),like how default sqlpersistence service stores?
Aravind Kathiroju wrote: |
Hi Joel, Iam using a custom persistence service. Iam persisting the instance by serializing it and successflly loading the instance back,using, protected override void SaveWorkflowInstanceState(Activity rootActivity, bool unlock) { Guid contextGuid = (Guid)rootActivity.GetValue(Activity.ActivityContextGuidProperty); SerializeToFile(WorkflowPersistenceService.GetDefaultSerializedForm(rootActivity), contextGuid); And protected override Activity LoadWorkflowInstanceState(Guid instanceId) { byte[] workflowBytes = DeserializeFromFile(instanceId); Activity ac = WorkflowPersistenceService.RestoreFromDefaultSerializedForm(workflowBytes, null); return WorkflowPersistenceService.RestoreFromDefaultSerializedForm(workflowBytes, null); } 1) what i want to know is how can i access the information of instance after deserialization (like i want to know name property,address property)? 2)how can i store the instance data in a table (instead of serializing),like how default sqlpersistence service stores? |
|