damirarh / damirscorner-utterances

utteranc.es comments for https://damirscorner.com
0 stars 0 forks source link

/blog/posts/20140317-RefreshingInstanceStoreHandleInWorkflowFoundation.html #10

Open damirarh opened 1 year ago

damirarh commented 1 year ago

Imported

URL: https://www.damirscorner.com/blog/posts/20140317-RefreshingInstanceStoreHandleInWorkflowFoundation.html

damirarh commented 1 year ago

Imported comment written by hamid rezaeirad on 2015-09-06T12:33:36

Hi,

I want to persist the workflow instance and load it.I create a WF app and reference it to a windows application and persist the WF but when I close the application and Open it again I give error :

The execution of an InstancePersistenceCommand was interrupted because the instance 'ba8ab62d-5642-4ebe-9c9d-bbb9d41e3dbc' is locked by a different instance owner. This error usually occurs because a different host has the instance loaded. The instance owner ID of the owner or host with a lock on the instance is 'ccaa704a-4fd9-4447-8963-9012da81ffc0'.

damirarh commented 1 year ago

Imported comment written by Damir Arh on 2015-09-06T19:36:56

I assume you open the application again within a short period of time. This probably means that the instance owner from before you closed the application is still holding the lock, because HostLockRenewalPeriod has not passed yet.

When you don't need the instance store any more before you close the application, you should delete the instance owner:

var deleteOwnerCmd = new DeleteWorkflowOwnerCommand();
instanceStore.Execute(instanceHandle, deleteOwnerCmd, TimeSpan.FromSeconds(10));

This should release the lock immediately, without waiting for the HostLockRenewalPeriod to pass.

damirarh commented 1 year ago

Imported comment written by hamid rezaeirad on 2015-09-07T07:02:51

Thank you for your reply.Yes, You right.I open the application for short period of time.I decrease the period of time and wait a few minutes to open the application then it works.

I want to create SOA(service oriented architect) application with WCF and WF.I searched to find reference for create WF service as WCF.but I could n`t find any.could you please help me how to do that?

damirarh commented 1 year ago

Imported comment written by Damir Arh on 2015-09-07T20:24:10

The best resource I've found on the topic is the book "Pro WF: Windows Workflow in .NET 4": http://amzn.to/1JNAgLM. It's great learning material for both Workflow Services (that's WF based WCF services you're interested in), and Workflow Foundation 4 in general. Note, that there's also a newer book "Pro WF 4.5" from the same publisher, but it's written by a different author: http://amzn.to/1XCwY7g. I haven't read that one, so I can't say how good it is.

There's not a lot of online resources on the topic, though. To get you started, you could take a look at Workflow Services on MSDN: https://msdn.microsoft.com/....

damirarh commented 1 year ago

Imported comment written by Nayana Nayak on 2016-02-01T08:31:38

I want to persist the workflow instance and load it.I create a WF app and reference it to a windows application and persist the WF and it is working fine with respect to windows application. but when I create same with reference wit the web applications its showing following errors :

The execution of an InstancePersistenceCommand was interrupted because the instance 'ba8ab62d-5642-4ebe-9c9d-bbb9d41e3dbc' is locked by a different instance owner. This error usually occurs because a different host has the instance loaded. The instance owner ID of the owner or host with a lock on the instance is 'ccaa704a-4fd9-4447-8963-9012da81ffc0'

damirarh commented 1 year ago

Imported comment written by Damir Arh on 2016-02-01T17:53:29

It's a similar issue to the one, discussed with Hamid. Since this is happening to you only in web applications, you are probably attempting to access the same instance from multiple requests in parallel or in short succession, i.e. before the HostLockRenewalPeriod has passed.

You'll need to avoid doing that. I suggest you manage access to workflows at the web application level, not the request level. You'll need to have only a single (global) instance store for accessing a single workflow instance, which will allow you to serialize access to it from different requests - the next request will only be given access to it, after the previous one completes. By using the same instance store for all requests you will also avoid any issues caused by the HostLockRenewalPeriod being to long.

You might even be able to have a single instance store for all requests, no matter the instance they are accessing. Make sure you do some performance tests to make sure this doesn't cause bottlenecks.

Web farm scenarios will make this much more difficult. If you have such requirements, it would be best to balance the load based on the workflow instance a request needs to access.

damirarh commented 1 year ago

Imported comment written by Parag on 2016-02-18T06:22:41

Hi Damir,
When we have many workflows is it still better to have single store (of course given performance is fine) or we should keep different instance store for each type of workflow?

Another question regarding resuming runnable instance when using delay activity which I couldn't find answer yet. We are using 4.5, have a long running workflow in which have a pick activity with bookmark and delay activity being triggers. If bookmark is not called and delay expires workflow should become runnable and execute next steps. To start the workflow we are using identity, to pass in WorkflowApplication (e.g. WorkflowApplication instance = new WorkflowApplication(wf, inputs, IdentityV1);). Workflow host then waits for events as suggested in many places -

private static void WaitForRunnableInstance(InstanceStore store, InstanceHandle ownerHandle)
{
IEnumerable<instancepersistenceevent> events = store.WaitForEvents(ownerHandle, TimeSpan.MaxValue);
bool foundRunnable = false;
// Loop through the persistence events looking for the HasRunnableWorkflow event (in this sample, it corresponds with

// the workflow instance whose timer has expired and is ready to be resumed by the host).

foreach (InstancePersistenceEvent persistenceEvent in events)
{
if (persistenceEvent.Equals(HasRunnableWorkflowEvent.Value))
{
foundRunnable = true;
Console.WriteLine("Found runnable instance");
break;
}
}
if (!foundRunnable)
{
throw new ApplicationException("Unexpected: No runnable instances found in the instance store");
}
}

But when we use identity waitForEvents never generate events and stuck forever in above method. If we dont use identity in WorkflowApplication it works. There was a solution (second last in thread) at this link https://social.msdn.microso... but this does not worked either.
Can you suggest solution to this issue? Or do we need to poll DB in our own thread to check runnable instances and run when found?

damirarh commented 1 year ago

Imported comment written by Damir Arh on 2016-02-19T08:16:31

I don't think there's any reason to have different instance stores for different types of workflows, if you don't have any performance problems. In the product I was working on, we only had a single instance store for all the different workflow definitions, and never had any problems because of that.

Unfortunately, I don't have any suggestions for your second issue. I did some tests with dynamic update (which would require the use of workflow identity), but couldn't get it to work reliably enough to ever implement it in the product. Hence, I have very limited experience with workflow identity.

damirarh commented 1 year ago

Imported comment written by Parag on 2016-02-19T08:33:39

Thanks Damir for reply, but that issue is resolved, I was using CreateWorkflowOwnerCommand instead of CreateWorkflowOwnerWithIdentityCommand as suggested on msdn post.
Another issue I am trying to find answer now - In your workflows did you had delay activities, if yes, then how did you handled loading runnable instances when using single store?

damirarh commented 1 year ago

Imported comment written by Damir Arh on 2016-02-19T11:10:16

No, we didn't have a need for delay activities, nor did we support them. We did store additional data about each instance in the database to know the workflow definition it mapped to, if that's the problem you are encountering.

damirarh commented 1 year ago

Imported comment written by Parag on 2016-03-01T14:28:47

Hi Damir, thank you for the pointers, I used "workflow definition" - "workflow host" relation to reload the runnable workflow when delay is expired and its working fine as of now.

damirarh commented 1 year ago

Imported comment written by Sergey 222 on 2016-03-14T10:44:14

Hello guys!
I've got the same problem with absence of events in store while using wf identity. Parag, could you please help me with this issue. I think my code is good, but seems I've lost some minor detail...

damirarh commented 1 year ago

Imported comment written by Parag on 2016-03-14T12:39:40

Hi Sergey,
In my case issue was with creating handle, I was using CreateWorkflowOwnerCommand instead of CreateWorkflowOwnerWithIdentityCommand. Now my code to create handle is as below -
Please note the xnamespaces, specially WorkflowHostTypePropertyName defined in my method below should use 4.0 properties not 4.5.
I hope this helps.

private static readonly XNamespace _workflowNamespace = XNamespace.Get("urn:schemas-microsoft-com:System.Activities/4.0/properties");

private static readonly XNamespace _workflow45Namespace = XNamespace.Get("urn:schemas-microsoft-com:System.Activities/4.5/properties");

private void CreateHandle()

{

_handle = _instanceStore.CreateInstanceHandle();

XName WorkflowHostTypePropertyName = _workflowNamespace.GetName("WorkflowHostType");

XName DefinitionIdentityFilterName = _workflow45Namespace.GetName("DefinitionIdentityFilter");

XName WorkflowApplicationName = _workflow45Namespace.GetName("WorkflowApplication");

XName DefinitionIdentitiesName = _workflow45Namespace.GetName("DefinitionIdentities");

CreateWorkflowOwnerWithIdentityCommand ownerCommand = new CreateWorkflowOwnerWithIdentityCommand()

{

InstanceOwnerMetadata =

{

{ WorkflowHostTypePropertyName, new InstanceValue(WorkflowApplicationName) },

{ DefinitionIdentityFilterName, new InstanceValue(WorkflowIdentityFilter.Any) },

}

};

_instanceStore.DefaultInstanceOwner = _instanceStore.Execute(_handle, ownerCommand, TimeSpan.MaxValue).InstanceOwner;

}
damirarh commented 1 year ago

Imported comment written by Sergey 222 on 2016-03-14T14:59:06

Ahahah, it works! Thank you!