public IBehaviour Setup(Actor target) { INodeInstance[] behaviourTokens = new INodeInstance[Nodes.Length]; int nodeCount = Nodes.Length; // Map and create tokens for (int i = 0; i < nodeCount; i++) { var node = Nodes[i]; behaviourTokens[i] = node.Create(); } var graphInstance = new GraphInstance(this, behaviourTokens); // Connect the token sockets for (int i = 0; i < nodeCount; i++) { Nodes[i].ConnectToken(graphInstance, behaviourTokens[i]); } // Setup tokens for (int i = 0; i < nodeCount; i++) { Nodes[i].Setup(graphInstance, behaviourTokens[i], target); } return(graphInstance); }
public virtual void Subscribe(INodeInstance node, Action callback) { if (Consumers == null) { Consumers = new List <ConnectionSubscription>(); } var subscription = new ConnectionSubscription(); foreach (var previousSubscribers in Consumers) { if (subscription.Node == previousSubscribers.Node) { subscription = previousSubscribers; } } if (subscription.Node == null) { subscription = new ConnectionSubscription(node); subscription.Callbacks.Add(callback); Consumers.Add(subscription); } else { subscription.Callbacks.Add(callback); } }
public HotNodeService(INodeInstance nodeInstance) { _nodeInstance = nodeInstance; _nodeProcess = (Process)typeof(OutOfProcessNodeInstance) .GetField("_nodeProcess", BindingFlags.Instance | BindingFlags.NonPublic) .GetValue(_nodeInstance); }
private async Task <T> InvokeExportWithPossibleRetryAsync <T>(string moduleName, string exportedFunctionName, object[] args, bool allowRetry, CancellationToken cancellationToken) { this.ThrowAnyOutstandingDelayedDisposalException(); var nodeInstance = this.GetOrCreateCurrentNodeInstance(); try { return(await nodeInstance.InvokeExportAsync <T>(cancellationToken, moduleName, exportedFunctionName, args)); } catch (NodeInvocationException ex) { // If the Node instance can't complete the invocation because it needs to restart (e.g., because the underlying // Node process has exited, or a file it depends on has changed), then we make one attempt to restart transparently. if (allowRetry && ex.NodeInstanceUnavailable) { // Perform the retry after clearing away the old instance // Since we disposal is delayed even though the node instance is replaced immediately, this produces the // "connection draining" feature whereby in-flight RPC calls are given a certain period to complete. lock (this._currentNodeInstanceAccessLock) { if (this._currentNodeInstance == nodeInstance) { var disposalDelay = ex.AllowConnectionDraining ? ConnectionDrainingTimespan : TimeSpan.Zero; this.DisposeNodeInstance(this._currentNodeInstance, disposalDelay); this._currentNodeInstance = null; } } // One the next call, don't allow retries, because we could get into an infinite retry loop, or a long retry // loop that masks an underlying problem. A newly-created Node instance should be able to accept invocations, // or something more serious must be wrong. return(await this.InvokeExportWithPossibleRetryAsync <T>(moduleName, exportedFunctionName, args, /* allowRetry */ false, cancellationToken)); } else { throw; } } }
public void Setup() { int nodeCount = Template.Nodes.Length; // Start allowing events to fire for (int i = 0; i < nodeCount; i++) { var nodeInstance = nodeInstances[i]; var nodeInputs = allInputs[i]; if (nodeInputs == null) { continue; } foreach (var input in nodeInputs) { connections[input.ConnectionId].RegisterInput(nodeInstance); } } // Run node setup process for (int i = 0; i < nodeCount; i++) { currentNode = nodeInstances[i]; Template.Nodes[i].Setup(this, currentNode); } // Release all buffered events. foreach (var connection in connections) { connection.BufferEvents = false; } }
public override Boolean take(IToken token) { Boolean oldAlive = token.IsAlive; EdgeInstanceEvent e = new EdgeInstanceEvent(this); e.Token = token; e.EventType = EdgeInstanceEventEnum.ON_TAKING_THE_TOKEN; for (int i = 0; this.eventListeners != null && i < this.eventListeners.Count; i++) { IEdgeInstanceEventListener listener = this.eventListeners[i]; listener.onEdgeInstanceEventFired(e); } Boolean newAlive = token.IsAlive; if (!newAlive) {//循环条件不满足,则恢复token的alive标示 token.IsAlive = oldAlive; return(newAlive); } else {//否则流转到下一个节点 INodeInstance nodeInst = this.LeavingNodeInstance; token.Value = this.Weight; nodeInst.fire(token);//触发同步器节点 return(newAlive); } }
public virtual void Unsubscribe(INodeInstance node, Action callback) { if (Consumers == null) { return; } for (int i = Consumers.Count - 1; i >= 0; i--) { var subscriber = Consumers[i]; if (subscriber.Node == node) { for (int j = subscriber.Callbacks.Count - 1; j >= 0; j--) { var findCallback = subscriber.Callbacks[j]; if (callback == findCallback) { subscriber.Callbacks.RemoveAt(j); } } } } }
public ManifestCaptureGraphInstance(Node singleNodeGraph) { node = singleNodeGraph; instance = node.Create(); node.Inputs(this, instance); node.Outputs(this, instance); }
public void RegisterInput(INodeInstance node) { if (Consumers == null) { Consumers = new List <ConnectionSubscription>(); } Consumers.Add(new ConnectionSubscription(node)); }
public void Dispose() { lock (_currentNodeInstanceAccessLock) { if (_currentNodeInstance != null) { DisposeNodeInstance(_currentNodeInstance, delay: TimeSpan.Zero); _currentNodeInstance = null; } } }
public void Setup(Actor target) { int nodeCount = graph.Nodes.Length; for (int i = 0; i < nodeCount; i++) { currentNode = nodeInstances[i]; graph.Nodes[i].Setup(this, currentNode, target); } }
public ManifestCaptureGraphInstance(NodeTemplate singleNodeGraph) { node = singleNodeGraph; instance = node.CreateInstance(); var connectionMapper = new ConnectionMapper(instance, this); node.Inputs(connectionMapper, instance); node.Outputs(connectionMapper, instance); }
public GraphInstance(Graph template, IDictionary <LocalId, JObject> data = null) { Template = template; int nodeCount = template.Nodes.Length; nodeInstances = new INodeInstance[nodeCount]; var serializer = new JsonSerializer(); serializer.Converters.Add(new OutputConverter()); // Map and create tokens for (int i = 0; i < nodeCount; i++) { var node = template.Nodes[i]; var instance = node.CreateInstance(); if (data != null && data.TryGetValue(node.Id, out var instanceData)) { using (var sr = instanceData.CreateReader()) { serializer.Populate(sr, instance); } } nodeInstances[i] = instance; } connections = new IConnection[template.ConnectionsCount]; // Allow all outputs to make their output type visible allOutputs = new OutputMap[nodeCount][]; for (int i = 0; i < nodeCount; i++) { currentNode = nodeInstances[i]; allOutputs[i] = template.Nodes[i].Outputs(this, currentNode); } // Allow inputs to subscribe to those outputs. allInputs = new InputMap[nodeCount][]; for (int i = 0; i < nodeCount; i++) { currentNode = nodeInstances[i]; allInputs[i] = template.Nodes[i].Inputs(this, currentNode); } // Stop events from taking effect immediately. foreach (var connection in connections) { connection.BufferEvents = true; } }
public void Dispose() { lock (this._currentNodeInstanceAccessLock) { if (this._currentNodeInstance != null) { this.DisposeNodeInstance(this._currentNodeInstance, delay: TimeSpan.Zero); this._currentNodeInstance = null; } HostingEnvironment.UnregisterObject(this); } }
private INodeInstance GetOrCreateCurrentNodeInstance() { var instance = this._currentNodeInstance; if (instance == null) { lock (this._currentNodeInstanceAccessLock) { instance = this._currentNodeInstance; if (instance == null) { instance = this._currentNodeInstance = this.CreateNewNodeInstance(); } } } return(instance); }
public GraphInstance(Graph graph, IDictionary <LocalId, JObject> data = null) { this.graph = graph; int nodeCount = graph.Nodes.Length; nodeInstances = new INodeInstance[nodeCount]; // Map and create tokens for (int i = 0; i < nodeCount; i++) { var node = graph.Nodes[i]; if (data != null && data.TryGetValue(node.Id, out var instanceData)) { var serializer = new JsonSerializer(); serializer.Converters.Add(new OutputConverter()); nodeInstances[i] = (INodeInstance)instanceData.ToObject(node.MetadataType, serializer); } else { nodeInstances[i] = node.Create(); } } connections = new IConnection[graph.ConnectionsCount]; // Allow all outputs to make their output type visible allOutputs = new OutputMap[nodeCount][]; for (int i = 0; i < nodeCount; i++) { currentNode = nodeInstances[i]; allOutputs[i] = graph.Nodes[i].Outputs(this, currentNode); } // Allow inputs to subscribe to those outputs. allInputs = new InputMap[nodeCount][]; for (int i = 0; i < nodeCount; i++) { currentNode = nodeInstances[i]; allInputs[i] = graph.Nodes[i].Inputs(this, currentNode); } }
private void DisposeNodeInstance(INodeInstance nodeInstance, TimeSpan delay) { if (delay == TimeSpan.Zero) { nodeInstance.Dispose(); } else { Task.Run(async() => { try { await Task.Delay(delay); nodeInstance.Dispose(); } catch (Exception ex) { // Nothing's waiting for the delayed disposal task, so any exceptions in it would // by default just get ignored. To make these discoverable, capture them here so // they can be rethrown to the next caller to InvokeExportAsync. this._instanceDelayedDisposalException = ex; } }); } }
public override Boolean take(IToken token) { EdgeInstanceEvent e = new EdgeInstanceEvent(this); e.Token = token; e.EventType = EdgeInstanceEventEnum.ON_TAKING_THE_TOKEN; for (int i = 0; this.eventListeners != null && i < this.eventListeners.Count; i++) { IEdgeInstanceEventListener listener = this.eventListeners[i]; listener.onEdgeInstanceEventFired(e);//调用TransitionInstanceExtension 来计算弧线上的条件表达式 } INodeInstance nodeInst = this.LeavingNodeInstance; //获取到流向哪个节点 token.Value = this.Weight; //获取到弧线上的权值 Boolean alive = token.IsAlive; nodeInst.fire(token);//节点触发 return(alive); }
/// <summary>wangmj 初始化一个工作流网实例,将引擎的扩展属性,注入到对应的工作流元素中</summary> /// <param name="process"></param> /// <param name="kenelExtensions"></param> public NetInstance(WorkflowProcess process, Dictionary <String, List <IKernelExtension> > kenelExtensions) { this.workflowProcess = process; //开始节点 StartNode startNode = workflowProcess.StartNode; StartNodeInstance = new StartNodeInstance(startNode); List <IKernelExtension> extensionList = kenelExtensions[StartNodeInstance.ExtensionTargetName]; for (int i = 0; extensionList != null && i < extensionList.Count; i++) { IKernelExtension extension = extensionList[i]; StartNodeInstance.registExtension(extension); } //this.StartNodeInstance = StartNodeInstance; 自身赋值自身没用。 wfElementInstanceMap.Add(startNode.Id, StartNodeInstance); //活动节点activity List <Activity> activities = workflowProcess.Activities; for (int i = 0; i < activities.Count; i++) { Activity activity = (Activity)activities[i]; ActivityInstance activityInstance = new ActivityInstance(activity); extensionList = kenelExtensions[activityInstance.ExtensionTargetName]; for (int j = 0; extensionList != null && j < extensionList.Count; j++) { IKernelExtension extension = extensionList[j]; activityInstance.registExtension(extension); } wfElementInstanceMap.Add(activity.Id, activityInstance); } //同步器节点 List <Synchronizer> synchronizers = workflowProcess.Synchronizers; for (int i = 0; i < synchronizers.Count; i++) { Synchronizer synchronizer = (Synchronizer)synchronizers[i]; SynchronizerInstance synchronizerInstance = new SynchronizerInstance(synchronizer); extensionList = kenelExtensions[synchronizerInstance.ExtensionTargetName]; for (int j = 0; extensionList != null && j < extensionList.Count; j++) { IKernelExtension extension = extensionList[j]; synchronizerInstance.registExtension(extension); } wfElementInstanceMap.Add(synchronizer.Id, synchronizerInstance); } //结束节点 List <EndNode> endNodes = workflowProcess.EndNodes; // List<EndNodeInstance> endNodeInstances = netInstance.getEndNodeInstances(); for (int i = 0; i < endNodes.Count; i++) { EndNode endNode = endNodes[i]; EndNodeInstance endNodeInstance = new EndNodeInstance(endNode); // endNodeInstances.add(endNodeInstance); extensionList = kenelExtensions[endNodeInstance.ExtensionTargetName]; for (int j = 0; extensionList != null && j < extensionList.Count; j++) { IKernelExtension extension = extensionList[j]; endNodeInstance.registExtension(extension); } wfElementInstanceMap.Add(endNode.Id, endNodeInstance); } //转移线 List <Transition> transitions = workflowProcess.Transitions; for (int i = 0; i < transitions.Count; i++) { Transition transition = (Transition)transitions[i]; TransitionInstance transitionInstance = new TransitionInstance(transition); String fromNodeId = transition.FromNode.Id; if (fromNodeId != null) { INodeInstance enteringNodeInstance = (INodeInstance)wfElementInstanceMap[fromNodeId]; if (enteringNodeInstance != null) { enteringNodeInstance.AddLeavingTransitionInstance(transitionInstance); transitionInstance.EnteringNodeInstance = enteringNodeInstance; } } String toNodeId = transition.ToNode.Id; if (toNodeId != null) { INodeInstance leavingNodeInstance = (INodeInstance)wfElementInstanceMap[toNodeId]; if (leavingNodeInstance != null) { leavingNodeInstance.AddEnteringTransitionInstance(transitionInstance); transitionInstance.LeavingNodeInstance = leavingNodeInstance; } } extensionList = kenelExtensions[transitionInstance.ExtensionTargetName]; for (int j = 0; extensionList != null && j < extensionList.Count; j++) { IKernelExtension extension = extensionList[j]; transitionInstance.registExtension(extension); } wfElementInstanceMap.Add(transitionInstance.Id, transitionInstance); } //循环线 List <Loop> loops = workflowProcess.Loops; for (int i = 0; i < loops.Count; i++) { Loop loop = (Loop)loops[i]; LoopInstance loopInstance = new LoopInstance(loop); String fromNodeId = loop.FromNode.Id; if (fromNodeId != null) { INodeInstance enteringNodeInstance = (INodeInstance)wfElementInstanceMap[fromNodeId]; if (enteringNodeInstance != null) { enteringNodeInstance.AddLeavingLoopInstance(loopInstance); loopInstance.EnteringNodeInstance = enteringNodeInstance; } } String toNodeId = loop.ToNode.Id; if (toNodeId != null) { INodeInstance leavingNodeInstance = (INodeInstance)wfElementInstanceMap[toNodeId]; if (leavingNodeInstance != null) { leavingNodeInstance.AddEnteringLoopInstance(loopInstance); loopInstance.LeavingNodeInstance = leavingNodeInstance; } } extensionList = kenelExtensions[loopInstance.ExtensionTargetName]; for (int j = 0; extensionList != null && j < extensionList.Count; j++) { IKernelExtension extension = extensionList[j]; loopInstance.registExtension(extension); } wfElementInstanceMap.Add(loopInstance.Id, loopInstance); } }
public void Connect(ref InputSocket input, out INodeInstance connection) { connection = null; }
public void Connect(ref InputSocket input, out INodeInstance connection) { connection = removeNodes[input.TargetId]; }
public abstract void Setup(IGraphInstance graph, INodeInstance metadata, Actor target);
public ConnectionSubscription(INodeInstance node) { Node = node; Callbacks = new List <Action>(); }
public EventInput(INodeInstance parent, IConnection connection) { Parent = parent; Connection = connection; }
public Input(INodeInstance parent, IConnection connection) { Parent = parent; Connection = (IConnection <T>)connection; }
public InputSource(Node node, INodeInstance instance, OutputMap outputMapping) { Node = node; Instance = instance ?? throw new ArgumentNullException(nameof(instance)); OutputInformation = outputMapping; }
public void Unsubscribe(INodeInstance node, Action callback) => Source.Unsubscribe(node, callback);
public abstract OutputMap[] Outputs(IGraphConnections graph, INodeInstance instance);
internal GraphInstanceNode(INodeInstance instance, InputMap[] inputs, OutputMap[] outputs) { Instance = instance; Inputs = inputs; Outputs = outputs; }
public void RegisterInput(INodeInstance node) => Source.RegisterInput(node);