public override int GetHashCode() { unchecked { var hashCode = Key.GetHashCode(); hashCode = (hashCode * 397) ^ (Type != null ? Type.GetHashCode() : 0); hashCode = (hashCode * 397) ^ WorkflowInstanceKey.GetHashCode(); hashCode = (hashCode * 397) ^ (BpmnProcessId != null ? BpmnProcessId.GetHashCode() : 0); hashCode = (hashCode * 397) ^ WorkflowDefinitionVersion; hashCode = (hashCode * 397) ^ WorkflowKey.GetHashCode(); hashCode = (hashCode * 397) ^ (ElementId != null ? ElementId.GetHashCode() : 0); hashCode = (hashCode * 397) ^ ElementInstanceKey.GetHashCode(); hashCode = (hashCode * 397) ^ (Worker != null ? Worker.GetHashCode() : 0); hashCode = (hashCode * 397) ^ Retries; hashCode = (hashCode * 397) ^ Deadline.GetHashCode(); hashCode = (hashCode * 397) ^ (Variables != null ? Variables.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (CustomHeaders != null ? CustomHeaders.GetHashCode() : 0); return(hashCode); } }
/// <summary> /// Handles workflow invocation. /// </summary> /// <param name="client">The associated cadence client.</param> /// <param name="request">The request message.</param> /// <returns>The reply message.</returns> internal static async Task <WorkflowInvokeReply> OnInvokeAsync(CadenceClient client, WorkflowInvokeRequest request) { Covenant.Requires <ArgumentNullException>(client != null); Covenant.Requires <ArgumentNullException>(request != null); Covenant.Requires <ArgumentException>(request.ReplayStatus != InternalReplayStatus.Unspecified); IWorkflowBase workflow; WorkflowRegistration registration; var contextId = request.ContextId; var workflowKey = new WorkflowInstanceKey(client, contextId); lock (syncLock) { if (request.ReplayStatus != InternalReplayStatus.Unspecified) { return(new WorkflowInvokeReply() { Error = new CadenceError($"[{nameof(WorkflowInvokeRequest)}] did not specify Workflow type name [Type={request.WorkflowType}] is not registered for this worker.") }); } if (idToWorkflow.TryGetValue(workflowKey, out workflow)) { return(new WorkflowInvokeReply() { Error = new CadenceError($"A workflow with [ID={workflowKey}] is already running on this worker.") }); } registration = GetWorkflowRegistration(client, request.WorkflowType); if (registration == null) { return(new WorkflowInvokeReply() { Error = new CadenceError($"Workflow type name [Type={request.WorkflowType}] is not registered for this worker.") }); } } workflow = (IWorkflowBase)Activator.CreateInstance(registration.WorkflowType); workflow.Workflow = new Workflow( parent: (WorkflowBase)workflow, client: client, contextId: contextId, workflowTypeName: request.WorkflowType, domain: request.Domain, taskList: request.TaskList, workflowId: request.WorkflowId, runId: request.RunId, isReplaying: request.ReplayStatus == InternalReplayStatus.Replaying, methodMap: registration.MethodMap); lock (syncLock) { idToWorkflow.Add(workflowKey, workflow); } // Register any workflow signal and/or query handlers with cadence-proxy foreach (var signalName in registration.MethodMap.GetSignalNames()) { var reply = (WorkflowSignalSubscribeReply)await client.CallProxyAsync( new WorkflowSignalSubscribeRequest() { ContextId = contextId, SignalName = signalName }); reply.ThrowOnError(); } foreach (var queryType in registration.MethodMap.GetQueryTypes()) { var reply = (WorkflowSetQueryHandlerReply)await client.CallProxyAsync( new WorkflowSetQueryHandlerRequest() { ContextId = contextId, QueryName = queryType }); reply.ThrowOnError(); } // Start the workflow by calling its workflow entry point method. // This method will indicate that it has completed via one of these // techniques: // // 1. The method returns normally with the workflow result. // // 2. The method calls [RestartAsync(result, args)] which throws an // [InternalWorkflowRestartException] which will be caught and // handled here. // // 3. The method throws another exception which will be caught // and be used to indicate that the workflow failed. try { var workflowMethod = registration.WorkflowMethod; var resultType = workflowMethod.ReturnType; var args = client.DataConverter.FromDataArray(request.Args, registration.WorkflowMethodParameterTypes); var serializedResult = emptyBytes; if (resultType.IsGenericType) { // Method returns: Task<T> var result = await(Task <object>) workflowMethod.Invoke(workflow, args); serializedResult = client.DataConverter.ToData(result); } else { // Method returns: Task await(Task <object>) workflowMethod.Invoke(workflow, args); serializedResult = emptyBytes; } return(new WorkflowInvokeReply() { Result = serializedResult }); } catch (CadenceWorkflowRestartException e) { return(new WorkflowInvokeReply() { ContinueAsNew = true, ContinueAsNewArgs = e.Args, ContinueAsNewDomain = e.Domain, ContinueAsNewTaskList = e.TaskList, ContinueAsNewExecutionStartToCloseTimeout = CadenceHelper.ToCadence(e.ExecutionStartToCloseTimeout), ContinueAsNewScheduleToCloseTimeout = CadenceHelper.ToCadence(e.ScheduleToCloseTimeout), ContinueAsNewScheduleToStartTimeout = CadenceHelper.ToCadence(e.ScheduleToStartTimeout), ContinueAsNewStartToCloseTimeout = CadenceHelper.ToCadence(e.TaskStartToCloseTimeout), }); } catch (CadenceException e) { return(new WorkflowInvokeReply() { Error = e.ToCadenceError() }); } catch (Exception e) { return(new WorkflowInvokeReply() { Error = new CadenceError(e) }); } }