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);
     }
 }
示例#2
0
        /// <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)
                });
            }
        }