예제 #1
0
        /// <summary>
        /// Converts the instance into an internal <see cref="InternalStartWorkflowOptions"/>.
        /// </summary>
        /// <returns>The corresponding <see cref="InternalStartWorkflowOptions"/>.</returns>
        internal InternalStartWorkflowOptions ToInternal()
        {
            Dictionary <string, byte[]> encodedMemos = null;

            if (Memo != null && Memo.Count > 0)
            {
                encodedMemos = new Dictionary <string, byte[]>();

                foreach (var item in Memo)
                {
                    encodedMemos.Add(item.Key, NeonHelper.JsonSerializeToBytes(item.Value));
                }
            }

            return(new InternalStartWorkflowOptions()
            {
                ID = this.WorkflowId,
                TaskList = this.TaskList,
                DecisionTaskStartToCloseTimeout = CadenceHelper.ToCadence(this.TaskStartToCloseTimeout.Value),
                ExecutionStartToCloseTimeout = CadenceHelper.ToCadence(this.ScheduleToCloseTimeout.Value),
                RetryPolicy = this.RetryOptions?.ToInternal(),
                WorkflowIdReusePolicy = (int)(this.WorkflowIdReusePolicy == WorkflowIdReusePolicy.UseDefault ? Cadence.WorkflowIdReusePolicy.AllowDuplicateFailedOnly : this.WorkflowIdReusePolicy),
                CronSchedule = this.CronSchedule,
                Memo = encodedMemos
            });
        }
예제 #2
0
 /// <summary>
 /// Converts this instance into the corresponding internal object.
 /// </summary>
 /// <returns>The equivalent <see cref="InternalLocalActivityOptions"/>.</returns>
 internal InternalLocalActivityOptions ToInternal()
 {
     return(new InternalLocalActivityOptions()
     {
         ScheduleToCloseTimeout = CadenceHelper.ToCadence(this.ScheduleToCloseTimeout),
         RetryPolicy = RetryOptions?.ToInternal()
     });
 }
예제 #3
0
        /// <summary>
        /// Converts the instance into an internal <see cref="InternalStartWorkflowOptions"/>.
        /// </summary>
        /// <param name="client">The <see cref="CadenceClient"/>.</param>
        /// <param name="taskList">Optionally specifies the target task list.</param>
        /// <param name="methodAttribute">Optionally specifies a <see cref="WorkflowMethodAttribute"/>.</param>
        /// <returns>The corresponding <see cref="InternalStartWorkflowOptions"/>.</returns>
        internal InternalStartWorkflowOptions ToInternal(CadenceClient client, string taskList = null, WorkflowMethodAttribute methodAttribute = null)
        {
            Covenant.Requires <ArgumentNullException>(client != null);

            taskList = client.ResolveTaskList(taskList);

            // Merge optional settings from these options and the method attribute.

            var decisionTaskStartToCloseTimeout = TimeSpan.FromSeconds(10);
            var executionStartToCloseTimeout    = CadenceClient.DefaultTimeout;
            var workflowIdReusePolicy           = global::Neon.Cadence.WorkflowIdReusePolicy.AllowDuplicateFailedOnly;

            if (methodAttribute != null)
            {
                if (string.IsNullOrEmpty(taskList))
                {
                    if (methodAttribute.TaskList != null)
                    {
                        taskList = methodAttribute.TaskList;
                    }
                    else
                    {
                        taskList = client.Settings.DefaultTaskList;
                    }
                }

                if (!DecisionTaskStartToCloseTimeout.HasValue && methodAttribute.TaskStartToCloseTimeoutSeconds > 0)
                {
                    decisionTaskStartToCloseTimeout = TimeSpan.FromSeconds(methodAttribute.TaskStartToCloseTimeoutSeconds);
                }

                if (!ExecutionStartToCloseTimeout.HasValue && methodAttribute.ExecutionStartToCloseTimeoutSeconds > 0)
                {
                    executionStartToCloseTimeout = TimeSpan.FromSeconds(methodAttribute.ExecutionStartToCloseTimeoutSeconds);
                }

                if (!WorkflowIdReusePolicy.HasValue && methodAttribute.WorkflowIdReusePolicy.HasValue)
                {
                    workflowIdReusePolicy = methodAttribute.WorkflowIdReusePolicy.Value;
                }
            }

            return(new InternalStartWorkflowOptions()
            {
                ID = this.WorkflowId,
                TaskList = taskList,
                DecisionTaskStartToCloseTimeout = CadenceHelper.ToCadence(decisionTaskStartToCloseTimeout),
                ExecutionStartToCloseTimeout = CadenceHelper.ToCadence(executionStartToCloseTimeout),
                RetryPolicy = this.RetryOptions?.ToInternal(),
                WorkflowIdReusePolicy = (int)workflowIdReusePolicy,
                CronSchedule = this.CronSchedule,
                Memo = this.Memo
            });
        }
예제 #4
0
 /// <summary>
 /// Converts the instance into an <see cref="InternalRetryPolicy"/>.
 /// </summary>
 /// <returns>The converted instance.</returns>
 internal InternalRetryPolicy ToInternal()
 {
     return(new InternalRetryPolicy()
     {
         BackoffCoefficient = this.BackoffCoefficient,
         ExpirationInterval = CadenceHelper.ToCadence(this.ExpirationInterval),
         InitialInterval = CadenceHelper.ToCadence(this.InitialInterval),
         MaximumAttempts = this.MaximumAttempts,
         MaximumInterval = CadenceHelper.ToCadence(this.MaximumInterval),
         NonRetriableErrorReasons = NonRetriableErrors.ToList()
     });
 }
예제 #5
0
 /// <summary>
 /// Converts the instance to its internal representation.
 /// </summary>
 internal InternalActivityOptions ToInternal()
 {
     return(new InternalActivityOptions()
     {
         TaskList = this.TaskList,
         ScheduleToCloseTimeout = CadenceHelper.ToCadence(this.ScheduleToCloseTimeout),
         ScheduleToStartTimeout = CadenceHelper.ToCadence(this.ScheduleToStartTimeout),
         StartToCloseTimeout = CadenceHelper.ToCadence(this.StartToCloseTimeout),
         HeartbeatTimeout = CadenceHelper.ToCadence(this.HeartbeatTimeout),
         WaitForCancellation = WaitForCancellation,
         RetryPolicy = RetryOptions?.ToInternal()
     });
 }
예제 #6
0
 /// <summary>
 /// Converts this instance into the corresponding internal object.
 /// </summary>
 /// <returns>The equivalent <see cref="InternalChildWorkflowOptions"/>.</returns>
 internal InternalChildWorkflowOptions ToInternal()
 {
     return(new InternalChildWorkflowOptions()
     {
         Domain = this.Domain,
         ChildClosePolicy = (int)this.ChildPolicy,
         CronSchedule = this.CronSchedule,
         ExecutionStartToCloseTimeout = CadenceHelper.ToCadence(this.ScheduleToCloseTimeout.Value),
         RetryPolicy = this.RetryOptions?.ToInternal(),
         TaskList = this.TaskList ?? string.Empty,
         TaskStartToCloseTimeout = CadenceHelper.ToCadence(this.TaskStartToCloseTimeout.Value),
         WaitForCancellation = this.WaitUntilFinished,
         WorkflowID = this.WorkflowId,
         WorkflowIdReusePolicy = (int)(this.WorkflowIdReusePolicy == WorkflowIdReusePolicy.UseDefault ? Cadence.WorkflowIdReusePolicy.AllowDuplicateFailedOnly : this.WorkflowIdReusePolicy)
     });
 }
예제 #7
0
 /// <summary>
 /// Converts this instance into the corresponding internal object.
 /// </summary>
 /// <returns>The equivalent <see cref="InternalChildWorkflowOptions"/>.</returns>
 internal InternalChildWorkflowOptions ToInternal()
 {
     return new InternalChildWorkflowOptions()
     {
         Domain                       = this.Domain,
         WorkflowID                   = this.WorkflowID,
         TaskList                     = this.TaskList,
         ExecutionStartToCloseTimeout = CadenceHelper.ToCadence(this.ExecutionStartToCloseTimeout),
         TaskStartToCloseTimeout      = CadenceHelper.ToCadence(this.TaskStartToCloseTimeout),
         ChildPolicy                  = (int)this.ChildPolicy,
         WaitForCancellation          = this.WaitUntilFinished,
         WorkflowIdReusePolicy        = (int)this.WorkflowIdReusePolicy,
         RetryPolicy                  = this.RetryPolicy?.ToInternal(),
         CronSchedule                 = this.CronSchedule
     };
 }
예제 #8
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)
                });
            }
        }