public async Task SignalAsync(WorkflowExecution execution, string signalName, params object[] args) { await SyncContext.Clear; var dataConverter = Activity.Client.DataConverter; await Activity.Client.SignalWorkflowAsync(execution, signalName, CadenceHelper.ArgsToBytes(dataConverter, args)); }
/// <summary> /// Internal constructor for use outside of a workflow. /// </summary> /// <param name="client">Specifies the associated client.</param> /// <param name="execution">Specifies the target workflow execution.</param> /// <param name="domain">Optionally specifies the target domain (defaults to the client's default domain).</param> internal ExternalWorkflowStub(CadenceClient client, WorkflowExecution execution, string domain = null) { Covenant.Requires <ArgumentNullException>(client != null, nameof(client)); Covenant.Requires <ArgumentNullException>(execution != null, nameof(execution)); this.client = client; this.domain = client.ResolveDomain(domain); this.Execution = execution; }
/// <summary> /// Used to construct an untyped workflow stub that can manage an existing external workflow. /// </summary> /// <param name="client">The associated client.</param> /// <param name="execution">The workflow execution.</param> /// <param name="withinWorkflow"> /// Optionally indicates that the stub was created from within a workflow and that /// operations such as get result, query, signal, and cancel must be performed /// within local activities such that that can be replayed from history correctly. /// </param> internal WorkflowStub(CadenceClient client, WorkflowExecution execution, bool withinWorkflow = false) { Covenant.Requires <ArgumentNullException>(client != null, nameof(client)); Covenant.Requires <ArgumentNullException>(execution != null); this.client = client; this.Execution = execution; this.withinWorkflow = withinWorkflow; }
/// <summary> /// Creates an untyped stub for a known workflow execution. /// </summary> /// <param name="execution">The workflow execution.</param> /// <returns>The <see cref="WorkflowStub"/>.</returns> /// <remarks> /// Unlike activity stubs, a workflow stub may only be used to launch a single /// workflow. You'll need to create a new stub for each workflow you wish to /// invoke and then the first method called on a workflow stub must be /// the one of the methods tagged by <see cref="WorkflowMethodAttribute"/>. /// </remarks> public WorkflowStub NewUntypedWorkflowStub(WorkflowExecution execution) { Covenant.Requires <ArgumentNullException>(execution != null, nameof(execution)); EnsureNotDisposed(); return(new WorkflowStub(this) { Execution = execution }); }
/// <summary> /// Internal constructor for use within a workflow. /// </summary> /// <param name="parentWorkflow">Specifies the parent workflow.</param> /// <param name="execution">Specifies the target workflow execution.</param> /// <param name="domain">Optionally specifies the target domain (defaults to the client's default domain).</param> internal ExternalWorkflowStub(Workflow parentWorkflow, WorkflowExecution execution, string domain = null) { Covenant.Requires <ArgumentNullException>(parentWorkflow != null, nameof(parentWorkflow)); Covenant.Requires <ArgumentNullException>(execution != null, nameof(execution)); this.parentWorkflow = parentWorkflow; this.client = parentWorkflow.Client; this.domain = client.ResolveDomain(domain); this.Execution = execution; }
/// <summary> /// Creates a typed workflow stub connected to a known workflow execution /// using a <see cref="WorkflowExecution"/>. This can be used to signal and /// query the workflow via the type-safe interface methods. /// </summary> /// <typeparam name="TWorkflowInterface">Identifies the workflow interface.</typeparam> /// <param name="execution">Specifies the <see cref="WorkflowExecution"/>.</param> /// <returns>The dynamically generated stub that implements the workflow methods defined by <typeparamref name="TWorkflowInterface"/>.</returns> /// <remarks> /// Unlike activity stubs, a workflow stub may only be used to launch a single /// workflow. You'll need to create a new stub for each workflow you wish to /// invoke and then the first method called on a workflow stub must be /// the one of the methods tagged by <see cref="WorkflowMethodAttribute"/>. /// </remarks> public TWorkflowInterface NewWorkflowStub <TWorkflowInterface>(WorkflowExecution execution) where TWorkflowInterface : class { Covenant.Requires <ArgumentNullException>(execution != null, nameof(execution)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(execution.WorkflowId), nameof(execution.WorkflowId)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(execution.RunId), nameof(execution.RunId)); CadenceHelper.ValidateWorkflowInterface(typeof(TWorkflowInterface)); EnsureNotDisposed(); return(StubManager.NewWorkflowStub <TWorkflowInterface>(this, execution.WorkflowId, execution.RunId)); }
/// <summary> /// Used to construct an untyped workflow stub that can be used to start an external workflow. /// </summary> /// <param name="client">The associated client.</param> /// <param name="workflowTypeName">The workflow type name.</param> /// <param name="execution">The workflow execution.</param> /// <param name="options">The workflow options.</param> internal WorkflowStub(CadenceClient client, string workflowTypeName, WorkflowExecution execution, WorkflowOptions options) { Covenant.Requires <ArgumentNullException>(client != null, nameof(client)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(workflowTypeName)); Covenant.Requires <ArgumentNullException>(execution != null); Covenant.Requires <ArgumentNullException>(options != null); this.client = client; this.WorkflowTypeName = workflowTypeName; this.Execution = execution; this.Options = options; this.withinWorkflow = false; }
/// <summary> /// <para> /// Cancels a workflow if it has not already finished. /// </para> /// <note> /// Workflow cancellation is typically considered to be a normal activity /// and not an error as opposed to workflow termination which will usually /// happen due to an error. /// </note> /// </summary> /// <param name="execution">Identifies the running workflow.</param> /// <param name="domain">Optionally identifies the domain. This defaults to the client domain.</param> /// <returns>The tracking <see cref="Task"/>.</returns> /// <exception cref="CadenceEntityNotExistsException">Thrown if the workflow no longer exists.</exception> /// <exception cref="CadenceBadRequestException">Thrown if the request is invalid.</exception> /// <exception cref="CadenceInternalServiceException">Thrown for internal Cadence problems.</exception> internal async Task CancelWorkflowAsync(WorkflowExecution execution, string domain = null) { Covenant.Requires <ArgumentNullException>(execution != null); var reply = (WorkflowCancelReply) await CallProxyAsync( new WorkflowCancelRequest() { WorkflowId = execution.WorkflowId, RunId = execution.RunId, Domain = ResolveDomain(domain) }); reply.ThrowOnError(); }
/// <summary> /// Default constructor. /// </summary> /// <param name="client">The associated client.</param> /// <param name="workflowTypeName">The workflow type name.</param> /// <param name="execution">The workflow execution or <c>null</c> if the workflow hasn't been started.</param> /// <param name="taskList">Specifies the task list.</param> /// <param name="options">Specifies the workflow options.</param> /// <param name="domain">Specifies specifies the domain.</param> internal WorkflowStub(CadenceClient client, string workflowTypeName, WorkflowExecution execution, string taskList, WorkflowOptions options, string domain) { Covenant.Requires <ArgumentNullException>(client != null); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(workflowTypeName)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(taskList)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(domain)); this.client = client; this.WorkflowTypeName = workflowTypeName; this.Execution = execution; this.taskList = taskList; this.Options = options; this.domain = domain; }
/// <summary> /// Transmits a signal to a running workflow. /// </summary> /// <param name="execution">The <see cref="WorkflowExecution"/>.</param> /// <param name="signalName">Identifies the signal.</param> /// <param name="signalArgs">Optionally specifies the signal arguments as a byte array.</param> /// <param name="domain">Optionally specifies the domain. This defaults to the client domain.</param> /// <returns>The tracking <see cref="Task"/>.</returns> /// <exception cref="CadenceEntityNotExistsException">Thrown if the workflow no longer exists.</exception> /// <exception cref="CadenceInternalServiceException">Thrown for internal Cadence problems.</exception> internal async Task SignalWorkflowAsync(WorkflowExecution execution, string signalName, byte[] signalArgs = null, string domain = null) { Covenant.Requires <ArgumentNullException>(execution != null); var reply = (WorkflowSignalReply) await CallProxyAsync( new WorkflowSignalRequest() { WorkflowId = execution.WorkflowId, SignalName = signalName, SignalArgs = signalArgs, RunId = execution.RunId, Domain = ResolveDomain(domain) }); reply.ThrowOnError(); }
/// <summary> /// <para> /// Cancels a workflow if it has not already finished. /// </para> /// <note> /// Workflow termination is typically considered to be due to an error as /// opposed to cancellation which is usually considered as a normal activity. /// </note> /// </summary> /// <param name="execution">Identifies the running workflow.</param> /// <param name="reason">Optionally specifies an error reason string.</param> /// <param name="details">Optionally specifies additional details as a byte array.</param> /// <param name="domain">Optionally specifies the domain. This defaults to the client domain.</param> /// <returns>The tracking <see cref="Task"/>.</returns> /// <exception cref="CadenceEntityNotExistsException">Thrown if the workflow no longer exists.</exception> /// <exception cref="CadenceBadRequestException">Thrown if the request is invalid.</exception> /// <exception cref="CadenceInternalServiceException">Thrown for internal Cadence problems.</exception> internal async Task TerminateWorkflowAsync(WorkflowExecution execution, string reason = null, byte[] details = null, string domain = null) { Covenant.Requires <ArgumentNullException>(execution != null); var reply = (WorkflowTerminateReply) await CallProxyAsync( new WorkflowTerminateRequest() { WorkflowId = execution.WorkflowId, RunId = execution.RunId, Domain = ResolveDomain(domain), Reason = reason, Details = details });; reply.ThrowOnError(); }
/// <summary> /// Returns the current state of a running workflow. /// </summary> /// <param name="execution">Identifies the workflow execution.</param> /// <param name="domain">Optionally specifies the domain. This defaults to the client domain.</param> /// <returns>A <see cref="WorkflowDescription"/>.</returns> /// <exception cref="CadenceEntityNotExistsException">Thrown if the workflow no longer exists.</exception> /// <exception cref="CadenceBadRequestException">Thrown if the request is invalid.</exception> /// <exception cref="CadenceInternalServiceException">Thrown for internal Cadence problems.</exception> internal async Task <WorkflowDescription> GetWorkflowDescriptionAsync(WorkflowExecution execution, string domain = null) { Covenant.Requires <ArgumentNullException>(execution != null); var reply = (WorkflowDescribeExecutionReply) await CallProxyAsync( new WorkflowDescribeExecutionRequest() { WorkflowId = execution.WorkflowId, RunId = execution.RunId, Domain = ResolveDomain(domain) }); reply.ThrowOnError(); return(reply.Details.ToPublic()); }
/// <summary> /// Starts the workflow, returning an <see cref="IAsyncFuture"/> that can be used /// to wait for the the workflow to complete and obtain its result. /// </summary> /// <typeparam name="TResult">The workflow result type.</typeparam> /// <param name="args">The workflow arguments.</param> /// <returns>An <see cref="ExternalWorkflowFuture{TResult}"/> that can be used to retrieve the workflow result as an <c>object</c>.</returns> /// <exception cref="InvalidOperationException">Thrown if the workflow has already been started.</exception> /// <remarks> /// <note> /// <b>IMPORTANT:</b> You need to take care to ensure that the parameters passed /// and the result type are compatible with the target workflow method. /// </note> /// </remarks> public async Task <ExternalWorkflowFuture <TResult> > StartAsync <TResult>(params object[] args) { await SyncContext.ClearAsync; Covenant.Requires <ArgumentNullException>(args != null, nameof(args)); if (execution != null) { throw new InvalidOperationException("Cannot start a future stub more than once."); } execution = await client.StartWorkflowAsync(workflowTypeName, client.DataConverter.ToData(args), options); // Create and return the future. return(new ExternalWorkflowFuture <TResult>(client, execution)); }
/// <summary> /// Returns the result from a workflow execution, blocking until the workflow /// completes if it is still running. /// </summary> /// <param name="execution">Identifies the workflow execution.</param> /// <param name="domain">Optionally specifies the domain. This defaults to the client domain.</param> /// <returns>The workflow result encoded as bytes or <c>null</c>.</returns> /// <exception cref="EntityNotExistsException">Thrown if the workflow no longer exists.</exception> /// <exception cref="BadRequestException">Thrown if the request is invalid.</exception> /// <exception cref="InternalServiceException">Thrown for internal Cadence problems.</exception> internal async Task <byte[]> GetWorkflowResultAsync(WorkflowExecution execution, string domain = null) { Covenant.Requires <ArgumentNullException>(execution != null, nameof(execution)); EnsureNotDisposed(); var reply = (WorkflowGetResultReply) await CallProxyAsync( new WorkflowGetResultRequest() { WorkflowId = execution.WorkflowId, RunId = execution.RunId, Domain = ResolveDomain(domain) }); reply.ThrowOnError(); return(reply.Result); }
/// <summary> /// Queries a workflow. /// </summary> /// <param name="execution">The <see cref="WorkflowExecution"/>.</param> /// <param name="queryType">Identifies the query.</param> /// <param name="queryArgs">Optionally specifies the query arguments encoded as a byte array.</param> /// <param name="domain">Optionally specifies the domain. This defaults to the client domain.</param> /// <returns>The query result encoded as a byte array.</returns> /// <exception cref="CadenceEntityNotExistsException">Thrown if the workflow no longer exists.</exception> /// <exception cref="CadenceInternalServiceException">Thrown for internal Cadence problems.</exception> internal async Task <byte[]> QueryWorkflowAsync(WorkflowExecution execution, string queryType, byte[] queryArgs = null, string domain = null) { Covenant.Requires <ArgumentNullException>(execution != null); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(queryType)); var reply = (WorkflowQueryReply) await CallProxyAsync( new WorkflowQueryRequest() { WorkflowId = execution.WorkflowId, QueryName = queryType, QueryArgs = queryArgs, RunId = execution.RunId, Domain = ResolveDomain(domain) }); reply.ThrowOnError(); return(reply.Result); }
/// <summary> /// Used to externally cancel an activity identified by <see cref="WorkflowExecution"/> and activity ID. /// </summary> /// <param name="execution">The workflow execution.</param> /// <param name="activityId">The activity ID.</param> /// <param name="domain">Optionally overrides the default <see cref="CadenceClient"/> domain.</param> /// <returns>The tracking <see cref="Task"/>.</returns> /// <exception cref="EntityNotExistsException">Thrown if the activity no longer exists.</exception> public async Task ActivityCancelByIdAsync(WorkflowExecution execution, string activityId, string domain = null) { await SyncContext.ClearAsync; Covenant.Requires <ArgumentNullException>(execution != null, nameof(execution)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(activityId), nameof(activityId)); EnsureNotDisposed(); var reply = (ActivityCompleteReply) await CallProxyAsync( new ActivityCompleteRequest() { Domain = ResolveDomain(domain), WorkflowId = execution.WorkflowId, RunId = execution.RunId, ActivityId = activityId, Error = new CadenceError(new CancelledException("Cancelled")) }); reply.ThrowOnError(); }
/// <summary> /// Used to externally complete an activity identified by <see cref="WorkflowExecution"/> and activity ID. /// </summary> /// <param name="execution">The workflow execution.</param> /// <param name="activityId">The activity ID.</param> /// <param name="result">Passed as the activity result for activity success.</param> /// <param name="domain">Optionally overrides the default <see cref="CadenceClient"/> domain.</param> /// <returns>The tracking <see cref="Task"/>.</returns> /// <exception cref="EntityNotExistsException">Thrown if the activity no longer exists.</exception> public async Task ActivityCompleteByIdAsync(WorkflowExecution execution, string activityId, object result = null, string domain = null) { await SyncContext.Clear; Covenant.Requires <ArgumentNullException>(execution != null, nameof(execution)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(activityId), nameof(activityId)); EnsureNotDisposed(); var reply = (ActivityCompleteReply) await CallProxyAsync( new ActivityCompleteRequest() { Domain = ResolveDomain(domain), WorkflowId = execution.WorkflowId, RunId = execution.RunId, ActivityId = activityId, Result = GetClient(ClientId).DataConverter.ToData(result) }); reply.ThrowOnError(); }
/// <summary> /// Constructor. /// </summary> /// <param name="client">The associated client.</param> /// <param name="execution">The workflow execution.</param> /// <param name="domain">Optionally specifies the target domain. This defaults to the default client domain.</param> internal ExternalWorkflowFuture(CadenceClient client, WorkflowExecution execution, string domain = null) { this.client = client; this.Execution = execution; this.domain = client.ResolveDomain(domain); }
/// <summary> /// Constructor. /// </summary> /// <param name="client">The associated client.</param> /// <param name="execution">The workflow execution.</param> internal ExternalWorkflowFuture(CadenceClient client, WorkflowExecution execution) { this.client = client; this.Execution = execution; }
public async Task SignalAsync(WorkflowExecution execution, string signalName, params object[] args) { var dataConverter = Activity.Client.DataConverter; await Activity.Client.SignalWorkflowAsync(execution, signalName, dataConverter.ToData(args)); }
public async Task <byte[]> GetResultBytesAsync(WorkflowExecution execution) { return(await Activity.Client.GetWorkflowResultAsync(execution)); }
public async Task GetResultAsync(WorkflowExecution execution) { await Activity.Client.GetWorkflowResultAsync(execution); }
public async Task CancelAsync(WorkflowExecution execution) { await Activity.Client.CancelWorkflowAsync(execution); }