/// <summary> /// Internal constructor. /// </summary> /// <param name="parentWorkflow">The parent workflow.</param> /// <param name="workflowTypeName">The workflow type name.</param> /// <param name="options">Optional child workflow options.</param> internal ChildWorkflowFutureStub(Workflow parentWorkflow, string workflowTypeName, ChildWorkflowOptions options = null) { Covenant.Requires <ArgumentNullException>(parentWorkflow != null, nameof(parentWorkflow)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(workflowTypeName), nameof(workflowTypeName)); this.parentWorkflow = parentWorkflow; this.client = parentWorkflow.Client; this.WorkflowTypeName = workflowTypeName; this.Options = ChildWorkflowOptions.Normalize(client, options); }
/// <summary> /// Starts a child workflow. /// </summary> /// <param name="parentWorkflow">The parent workflow.</param> /// <param name="workflowTypeName"> /// The type name used when registering the workers that will handle this workflow. /// This name will often be the fully qualified name of the workflow type but /// this may have been customized when the workflow worker was registered. /// </param> /// <param name="args">Specifies the workflow arguments encoded into a byte array.</param> /// <param name="options">Specifies the workflow options.</param> /// <returns>A <see cref="ChildExecution"/> identifying the new running workflow instance.</returns> /// <exception cref="EntityNotExistsException">Thrown if there is no workflow registered for <paramref name="workflowTypeName"/>.</exception> /// <exception cref="BadRequestException">Thrown if the request is not valid.</exception> /// <exception cref="WorkflowRunningException">Thrown if a workflow with this ID is already running.</exception> /// <remarks> /// This method kicks off a new child workflow instance and returns after Cadence has /// queued the operation but the method <b>does not</b> wait for the workflow to /// complete. /// </remarks> internal async Task <ChildExecution> StartChildWorkflowAsync(Workflow parentWorkflow, string workflowTypeName, byte[] args, ChildWorkflowOptions options) { Covenant.Requires <ArgumentNullException>(parentWorkflow != null, nameof(parentWorkflow)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(workflowTypeName), nameof(workflowTypeName)); EnsureNotDisposed(); if (options == null) { options = new ChildWorkflowOptions(); } else { options = options.Clone(); } if (!options.ScheduleToCloseTimeout.HasValue) { options.ScheduleToCloseTimeout = Settings.WorkflowScheduleToCloseTimeout; } if (!options.ScheduleToStartTimeout.HasValue) { options.ScheduleToStartTimeout = Settings.WorkflowScheduleToStartTimeout; } if (!options.TaskStartToCloseTimeout.HasValue) { options.TaskStartToCloseTimeout = Settings.WorkflowTaskStartToCloseTimeout; } var reply = await parentWorkflow.ExecuteNonParallel( async() => { return((WorkflowExecuteChildReply)await CallProxyAsync( new WorkflowExecuteChildRequest() { ContextId = parentWorkflow.ContextId, Workflow = workflowTypeName, Args = args, Options = options.ToInternal(), ScheduleToStartTimeout = options.ScheduleToStartTimeout ?? Settings.WorkflowScheduleToStartTimeout })); }); reply.ThrowOnError(); parentWorkflow.UpdateReplay(reply); return(new ChildExecution(reply.Execution.ToPublic(), reply.ChildId)); }
//--------------------------------------------------------------------- // Static members /// <summary> /// <b>INTERNAL USE ONLY:</b> Normalizes the options passed by creating or cloning a new /// instance as required and filling unset properties using default client settings. /// </summary> /// <param name="client">The associated Cadence client.</param> /// <param name="options">The input options or <c>null</c>.</param> /// <param name="workflowInterface">Optionally specifies the workflow interface definition.</param> /// <returns>The normalized options.</returns> /// <exception cref="ArgumentNullException">Thrown if a valid task list is not specified.</exception> public static ChildWorkflowOptions Normalize(CadenceClient client, ChildWorkflowOptions options, Type workflowInterface = null) { Covenant.Requires <ArgumentNullException>(client != null, nameof(client)); WorkflowInterfaceAttribute interfaceAttribute = null; if (workflowInterface != null) { CadenceHelper.ValidateWorkflowInterface(workflowInterface); interfaceAttribute = workflowInterface.GetCustomAttribute <WorkflowInterfaceAttribute>(); } if (options == null) { options = new ChildWorkflowOptions(); } else { options = options.Clone(); } if (!options.ScheduleToCloseTimeout.HasValue || options.ScheduleToCloseTimeout.Value <= TimeSpan.Zero) { options.ScheduleToCloseTimeout = client.Settings.WorkflowScheduleToCloseTimeout; } if (!options.ScheduleToStartTimeout.HasValue || options.ScheduleToStartTimeout.Value <= TimeSpan.Zero) { options.ScheduleToStartTimeout = client.Settings.WorkflowScheduleToStartTimeout; } if (!options.TaskStartToCloseTimeout.HasValue || options.TaskStartToCloseTimeout.Value <= TimeSpan.Zero) { options.TaskStartToCloseTimeout = client.Settings.WorkflowTaskStartToCloseTimeout; } if (string.IsNullOrEmpty(options.TaskList)) { if (interfaceAttribute != null && !string.IsNullOrEmpty(interfaceAttribute.TaskList)) { options.TaskList = interfaceAttribute.TaskList; } } return(options); }
/// <summary> /// Internal constructor. /// </summary> /// <param name="parentWorkflow">The associated parent workflow.</param> /// <param name="methodName">Identifies the target workflow method or <c>null</c> or empty.</param> /// <param name="options">The child workflow options or <c>null</c>.</param> internal ChildWorkflowStub(Workflow parentWorkflow, string methodName, ChildWorkflowOptions options) { Covenant.Requires <ArgumentNullException>(parentWorkflow != null, nameof(parentWorkflow)); var workflowInterface = typeof(TWorkflowInterface); CadenceHelper.ValidateWorkflowInterface(workflowInterface); this.parentWorkflow = parentWorkflow; this.options = ChildWorkflowOptions.Normalize(parentWorkflow.Client, options); this.hasStarted = false; var workflowTarget = CadenceHelper.GetWorkflowTarget(workflowInterface, methodName); this.workflowTypeName = workflowTarget.WorkflowTypeName; this.targetMethod = workflowTarget.TargetMethod; }
//--------------------------------------------------------------------- // Static members /// <summary> /// <b>INTERNAL USE ONLY:</b> Normalizes the options passed by creating or cloning a new /// instance as required and filling unset properties using default client settings. /// </summary> /// <param name="client">The associated Cadence client.</param> /// <param name="options">The input options or <c>null</c>.</param> /// <param name="workflowInterface">Optionally specifies the workflow interface definition.</param> /// <param name="method">Optionally specifies the target workflow method.</param> /// <returns>The normalized options.</returns> /// <exception cref="ArgumentNullException">Thrown if a valid task list is not specified.</exception> public static ChildWorkflowOptions Normalize(CadenceClient client, ChildWorkflowOptions options, Type workflowInterface = null, MethodInfo method = null) { Covenant.Requires <ArgumentNullException>(client != null, nameof(client)); WorkflowInterfaceAttribute interfaceAttribute = null; WorkflowMethodAttribute methodAttribute = null; if (options == null) { options = new ChildWorkflowOptions(); } else { options = options.Clone(); } if (workflowInterface != null) { CadenceHelper.ValidateWorkflowInterface(workflowInterface); interfaceAttribute = workflowInterface.GetCustomAttribute <WorkflowInterfaceAttribute>(); } if (method != null) { methodAttribute = method.GetCustomAttribute <WorkflowMethodAttribute>(); } if (string.IsNullOrEmpty(options.Domain)) { if (!string.IsNullOrEmpty(methodAttribute?.Domain)) { options.Domain = methodAttribute.Domain; } if (string.IsNullOrEmpty(options.Domain) && !string.IsNullOrEmpty(interfaceAttribute?.Domain)) { options.Domain = interfaceAttribute.Domain; } } if (string.IsNullOrEmpty(options.TaskList)) { if (!string.IsNullOrEmpty(methodAttribute?.TaskList)) { options.TaskList = methodAttribute.TaskList; } if (string.IsNullOrEmpty(options.TaskList) && !string.IsNullOrEmpty(interfaceAttribute?.TaskList)) { options.TaskList = interfaceAttribute.TaskList; } } if (options.StartToCloseTimeout <= TimeSpan.Zero) { if (methodAttribute != null && methodAttribute.StartToCloseTimeoutSeconds > 0) { options.StartToCloseTimeout = TimeSpan.FromSeconds(methodAttribute.StartToCloseTimeoutSeconds); } if (options.StartToCloseTimeout <= TimeSpan.Zero) { options.StartToCloseTimeout = client.Settings.WorkflowStartToCloseTimeout; } } if (options.ScheduleToStartTimeout <= TimeSpan.Zero) { if (methodAttribute != null && methodAttribute.ScheduleToStartTimeoutSeconds > 0) { options.ScheduleToStartTimeout = TimeSpan.FromSeconds(methodAttribute.ScheduleToStartTimeoutSeconds); } if (options.ScheduleToStartTimeout <= TimeSpan.Zero) { options.ScheduleToStartTimeout = client.Settings.WorkflowScheduleToStartTimeout; } } if (options.DecisionTaskTimeout <= TimeSpan.Zero) { if (methodAttribute != null && methodAttribute.DecisionTaskTimeoutSeconds > 0) { options.DecisionTaskTimeout = TimeSpan.FromSeconds(methodAttribute.DecisionTaskTimeoutSeconds); } if (options.DecisionTaskTimeout <= TimeSpan.Zero) { options.DecisionTaskTimeout = client.Settings.WorkflowDecisionTaskTimeout; } } if (options.WorkflowIdReusePolicy == Cadence.WorkflowIdReusePolicy.UseDefault) { if (methodAttribute != null && methodAttribute.WorkflowIdReusePolicy != WorkflowIdReusePolicy.UseDefault) { options.WorkflowIdReusePolicy = methodAttribute.WorkflowIdReusePolicy; } if (options.WorkflowIdReusePolicy == Cadence.WorkflowIdReusePolicy.UseDefault) { options.WorkflowIdReusePolicy = client.Settings.WorkflowIdReusePolicy; } } return(options); }