Refreshing Instance Store Handle in Workflow Foundation
Certain aspects of Workflow Foundation are still poorly documented; the persistence framework being one of them. The following snippet is typically used for setting up the instance store:
var instanceStore = new SqlWorkflowInstanceStore(connectionString);
instanceStore.HostLockRenewalPeriod = TimeSpan.FromSeconds(30);
var instanceHandle = instanceStore.CreateInstanceHandle();
var view = instanceStore.Execute(instanceHandle,
new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
instanceStore.DefaultInstanceOwner = view.InstanceOwner;
It's difficult to find a detailed explanation of what all of this does; and to be honest, usually it's not necessary. At least not, until you start encountering problems, such as InstanceOwnerException
:
The execution of an InstancePersistenceCommand was interrupted because the instance owner registration for owner ID '9938cd6d-a9cb-49ad-a492-7c087dcc93af' has become invalid. This error indicates that the in-memory copy of all instances locked by this owner have become stale and should be discarded, along with the InstanceHandles. Typically, this error is best handled by restarting the host.
The error is closely related to the HostLockRenewalPeriod
property which defines how long obtained instance handle is valid without being renewed. If you try monitoring the database while an instance store with a valid instance handle is instantiated, you will notice [System.Activities.DurableInstancing].[ExtendLock]
being called periodically. This stored procedure is responsible for renewing the handle. If for some reason it fails to be called within the specified HostLockRenewalPeriod
, the above mentioned exception will be thrown when attempting to persist a workflow. A typical reason for this would be temporarily inaccessible database due to maintenance or networking problems. It's not something that happens often, but it's bound to happen if you have a long living instance store, e.g. in a constantly running workflow host, such as a Windows service.
Fortunately it's not all that difficult to fix the problem, once you know the cause of it. Before using the instance store you should always check, if the handle is still valid; and renew it, if it's not:
if (!instanceHandle.IsValid)
{
instanceHandle = instanceStore.CreateInstanceHandle();
var view = instanceStore.Execute(instanceHandle,
new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
instanceStore.DefaultInstanceOwner = view.InstanceOwner;
}
It's definitely less invasive than the restart of the host, suggested by the error message.