private Exception ProcessLoadWorkflowByInstanceKey( InstancePersistenceContext context, LoadWorkflowByInstanceKeyCommand command) { try { Guid instanceId = _dataStore.GetInstanceAssociation( command.LookupInstanceKey); if (instanceId == Guid.Empty) { throw new InstanceKeyNotReadyException( String.Format("Unable to load instance for key: {0}", command.LookupInstanceKey)); } SharedLoadWorkflow(context, instanceId); return(null); } catch (InstancePersistenceException exception) { Console.WriteLine( "ProcessLoadWorkflowByInstanceKey exception: {0}", exception.Message); return(exception); } }
private Exception ProcessLoadWorkflowByInstanceKey( InstancePersistenceContext context, LoadWorkflowByInstanceKeyCommand command) { try { Guid instanceId = _dataStore.GetInstanceAssociation( command.LookupInstanceKey); if (instanceId == Guid.Empty) { throw new InstanceKeyNotReadyException( String.Format(ErrorResource.UnableToLoadInstance, command.LookupInstanceKey)); } SharedLoadWorkflow(context, instanceId); return(null); } catch (InstancePersistenceException exception) { Console.WriteLine( // ReSharper disable LocalizableElement "ProcessLoadWorkflowByInstanceKey exception: {0}", // ReSharper restore LocalizableElement exception.Message); return(exception); } }
private InstancePersistenceCommand CreateLoadCommandHelper(InstanceKey key, out InstanceHandle handle, bool canCreateInstance, Guid suggestedIdOrId, ICollection <InstanceKey> associatedKeys, bool loadAny) { if (loadAny) { handle = this.store.CreateInstanceHandle(this.owner); return(new TryLoadRunnableWorkflowCommand()); } if (key != null) { LoadWorkflowByInstanceKeyCommand command; handle = this.store.CreateInstanceHandle(this.owner); if (canCreateInstance) { command = new LoadWorkflowByInstanceKeyCommand { LookupInstanceKey = key.Value, AssociateInstanceKeyToInstanceId = (suggestedIdOrId == Guid.Empty) ? Guid.NewGuid() : suggestedIdOrId, AcceptUninitializedInstance = true }; } else { command = new LoadWorkflowByInstanceKeyCommand { LookupInstanceKey = key.Value }; } InstanceKey keyToAdd = ((canCreateInstance && (key.Metadata != null)) && (key.Metadata.Count > 0)) ? key : null; if (associatedKeys != null) { foreach (InstanceKey key3 in associatedKeys) { if (key3 == key) { if (!canCreateInstance) { continue; } keyToAdd = null; } TryAddKeyToInstanceKeysCollection(command.InstanceKeysToAssociate, key3); } } if (keyToAdd != null) { TryAddKeyToInstanceKeysCollection(command.InstanceKeysToAssociate, keyToAdd); } return(command); } if (associatedKeys != null) { throw System.ServiceModel.Activities.FxTrace.Exception.AsError(new InvalidOperationException(System.ServiceModel.Activities.SR.NoAdditionalKeysOnInstanceIdLoad)); } handle = this.store.CreateInstanceHandle(this.owner, (suggestedIdOrId == Guid.Empty) ? Guid.NewGuid() : suggestedIdOrId); return(new LoadWorkflowCommand { AcceptUninitializedInstance = canCreateInstance }); }
protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state) { SaveWorkflowCommand save = command as SaveWorkflowCommand; if (save != null) { lock (FileStore.s_thisLock) { ProcessSaveCommand(context, save); } } LoadWorkflowCommand load = command as LoadWorkflowCommand; if (load != null) { lock (FileStore.s_thisLock) { ProcessLoadCommand(context, load); } } LoadWorkflowByInstanceKeyCommand loadByKey = command as LoadWorkflowByInstanceKeyCommand; if (loadByKey != null) { lock (FileStore.s_thisLock) { ProcessLoadByKeyCommand(context, loadByKey); } } if (save != null || load != null || loadByKey != null) { return(new CompletedAsyncResult(callback, state)); } if (command is CreateWorkflowOwnerCommand createOwner) { Guid ownerId = Guid.NewGuid(); Owner owner = new Owner(); lock (s_thisLock) { owner.Id = ownerId; owner.LockToken = Guid.NewGuid(); owner.Metadata = new PropertyBag(createOwner.InstanceOwnerMetadata); PersistenceItemManager.SaveToFile <Owner>(owner); } context.BindInstanceOwner(ownerId, owner.LockToken); context.BindEvent(HasRunnableWorkflowEvent.Value); return(new CompletedAsyncResult(callback, state)); } if (command is DeleteWorkflowOwnerCommand deleteOwner) { Guid ownerId = context.InstanceView.InstanceOwner.InstanceOwnerId; lock (FileStore.s_thisLock) { Owner owner = PersistenceItemManager.Load <Owner>(ownerId); if (owner != null && owner.LockToken == context.LockToken) { PersistenceItemManager.Remove <Owner>(ownerId); } } context.InstanceHandle.Free(); return(new CompletedAsyncResult(callback, state)); } return(base.BeginTryCommand(context, command, timeout, callback, state)); }
private long ProcessLoadByKeyCommand(InstancePersistenceContext context, LoadWorkflowByInstanceKeyCommand command) { Owner owner = CheckOwner(context, command.Name); Key key = PersistenceItemManager.Load <Key>(command.LookupInstanceKey); Instance instance; if (key == null) { if (context.InstanceView.IsBoundToLock && context.InstanceView.InstanceId != command.AssociateInstanceKeyToInstanceId) { // This happens in the bind reclaimed lock case. context.InstanceHandle.Free(); throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId); } if (command.AssociateInstanceKeyToInstanceId == Guid.Empty) { throw new InstanceKeyNotReadyException(command.Name, new InstanceKey(command.LookupInstanceKey)); } key = new Key() { Id = command.LookupInstanceKey, TargetInstanceId = command.AssociateInstanceKeyToInstanceId, Metadata = new PropertyBag() }; instance = PersistenceItemManager.Load <Instance>(command.AssociateInstanceKeyToInstanceId); if (instance == null) { // Checking instance.Owner is like an InstanceLockQueryResult. context.QueriedInstanceStore(new InstanceLockQueryResult(command.AssociateInstanceKeyToInstanceId, Guid.Empty)); if (context.InstanceView.IsBoundToLock) { // This happens in the bind reclaimed lock case. context.InstanceHandle.Free(); throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId); } context.BindInstance(command.AssociateInstanceKeyToInstanceId); if (command.AcceptUninitializedInstance) { instance = new Instance() { Id = command.AssociateInstanceKeyToInstanceId, Version = 1, Metadata = new PropertyBag(), Owner = context.InstanceView.InstanceOwner.InstanceOwnerId }; PersistenceItemManager.SaveToFile <Instance>(instance); } else { throw new Exception("Could not create new Instance"); } context.BindAcquiredLock(1); } else { // Checking instance.Owner is like an InstanceLockQueryResult. context.QueriedInstanceStore(new InstanceLockQueryResult(command.AssociateInstanceKeyToInstanceId, instance.Owner)); if (context.InstanceView.IsBoundToLock) { if (instance.Version != context.InstanceVersion || instance.Owner != context.InstanceView.InstanceOwner.InstanceOwnerId) { if (context.InstanceVersion > instance.Version) { throw new InvalidProgramException("This is a bug, the context should never be bound higher than the lock."); } context.InstanceHandle.Free(); throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId); } } if (instance.Data != null) { // LoadByInstanceKeyCommand only allows auto-association to an uninitialized instance. throw new InstanceCollisionException(command.Name, command.AssociateInstanceKeyToInstanceId); } if (!context.InstanceView.IsBoundToLock) { if (instance.Owner == Guid.Empty) { context.BindInstance(command.AssociateInstanceKeyToInstanceId); instance.Version++; instance.Owner = context.InstanceView.InstanceOwner.InstanceOwnerId; PersistenceItemManager.SaveToFile <Instance>(instance); context.BindAcquiredLock(instance.Version); } else if (instance.Owner == context.InstanceView.InstanceOwner.InstanceOwnerId) { // This is a pretty weird case - maybe it's a retry? context.BindInstance(command.AssociateInstanceKeyToInstanceId); return(instance.Version); } else { throw new InstanceLockedException(command.Name, instance.Owner); } } } if (command.InstanceKeysToAssociate.TryGetValue(command.LookupInstanceKey, out IDictionary <XName, InstanceValue> lookupKeyMetadata)) { key.Metadata = new PropertyBag(lookupKeyMetadata); } else { key.Metadata = new PropertyBag(); } key.Id = command.LookupInstanceKey; key.TargetInstanceId = command.AssociateInstanceKeyToInstanceId; PersistenceItemManager.SaveToFile <Key>(key); context.AssociatedInstanceKey(command.LookupInstanceKey); if (lookupKeyMetadata != null) { foreach (KeyValuePair <XName, InstanceValue> property in lookupKeyMetadata) { context.WroteInstanceKeyMetadataValue(command.LookupInstanceKey, property.Key, property.Value); } } } else { if (context.InstanceView.IsBoundToLock && (key.State == InstanceKeyState.Completed || key.TargetInstanceId != context.InstanceView.InstanceId)) { // This happens in the bind reclaimed lock case. context.InstanceHandle.Free(); throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId); } if (key.State == InstanceKeyState.Completed) { throw new InstanceKeyCompleteException(command.Name, new InstanceKey(command.LookupInstanceKey)); } instance = PersistenceItemManager.Load <Instance>(key.TargetInstanceId); // Checking instance.Owner is like an InstanceLockQueryResult. context.QueriedInstanceStore(new InstanceLockQueryResult(key.TargetInstanceId, instance.Owner)); if (context.InstanceView.IsBoundToLock) { if (instance.Version != context.InstanceVersion || instance.Owner != context.InstanceView.InstanceOwner.InstanceOwnerId) { if (context.InstanceVersion > instance.Version) { throw new InvalidProgramException("This is a bug, the context should never be bound higher than the lock."); } context.InstanceHandle.Free(); throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId); } } if (instance.Data == null && !command.AcceptUninitializedInstance) { throw new InstanceNotReadyException(command.Name, key.TargetInstanceId); } if (!context.InstanceView.IsBoundToLock) { if (instance.Owner == Guid.Empty) { context.BindInstance(key.TargetInstanceId); instance.Version++; instance.Owner = context.InstanceView.InstanceOwner.InstanceOwnerId; PersistenceItemManager.SaveToFile <Instance>(instance); context.BindAcquiredLock(instance.Version); } else if (instance.Owner == context.InstanceView.InstanceOwner.InstanceOwnerId) { // This is the very interesting parallel-convoy conflicting handle race resolution case. Two handles // can get bound to the same lock, which is necessary to allow parallel convoy to succeed without preventing // zombied locked instances from being reclaimed. context.BindInstance(key.TargetInstanceId); return(instance.Version); } else { throw new InstanceLockedException(command.Name, instance.Owner); } } } Key newKey; Exception exception = null; foreach (KeyValuePair <Guid, IDictionary <XName, InstanceValue> > keyEntry in command.InstanceKeysToAssociate) { newKey = PersistenceItemManager.Load <Key>(keyEntry.Key); if (newKey == null) { newKey = new Key() { Id = keyEntry.Key, TargetInstanceId = key.TargetInstanceId, Metadata = new PropertyBag(keyEntry.Value) }; PersistenceItemManager.AddKeyToInstance(key.TargetInstanceId, newKey); context.AssociatedInstanceKey(keyEntry.Key); if (keyEntry.Value != null) { foreach (KeyValuePair <XName, InstanceValue> property in keyEntry.Value) { context.WroteInstanceKeyMetadataValue(keyEntry.Key, property.Key, property.Value); } } } else { if (newKey.TargetInstanceId != key.TargetInstanceId && exception == null) { exception = new InstanceKeyCollisionException(command.Name, key.TargetInstanceId, new InstanceKey(keyEntry.Key), newKey.TargetInstanceId); } } } if (exception != null) { throw exception; } Dictionary <Guid, IDictionary <XName, InstanceValue> > associatedKeys = new Dictionary <Guid, IDictionary <XName, InstanceValue> >(); Dictionary <Guid, IDictionary <XName, InstanceValue> > completedKeys = new Dictionary <Guid, IDictionary <XName, InstanceValue> >(); foreach (Guid keyId in instance.RelatedKeys) { key = PersistenceItemManager.Load <Key>(keyId); if (key.TargetInstanceId == context.InstanceView.InstanceId) { if (key.State == InstanceKeyState.Completed) { completedKeys.Add(key.Id, ExcludeWriteOnlyPropertyBagItems(key.Metadata)); } else { associatedKeys.Add(key.Id, ExcludeWriteOnlyPropertyBagItems(key.Metadata)); } } } instance.State = instance.Data == null ? InstanceState.Uninitialized : InstanceState.Initialized; PersistenceItemManager.SaveToFile <Instance>(instance); context.LoadedInstance(instance.State, ExcludeWriteOnlyPropertyBagItems(instance.Data), ExcludeWriteOnlyPropertyBagItems(instance.Metadata), associatedKeys, completedKeys); return(0); }