diff --git a/src/Temporalio/Client/StartActivityOptions.cs b/src/Temporalio/Client/StartActivityOptions.cs
index 570accc6..2fb0ae80 100644
--- a/src/Temporalio/Client/StartActivityOptions.cs
+++ b/src/Temporalio/Client/StartActivityOptions.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using Temporalio.Api.Enums.V1;
using Temporalio.Common;
@@ -114,6 +115,26 @@ public StartActivityOptions(string id, string taskQueue)
///
public RpcOptions? Rpc { get; set; }
+ ///
+ /// Gets or sets the on-conflict options.
+ ///
+ internal Api.Common.V1.OnConflictOptions? OnConflictOptions { get; set; }
+
+ ///
+ /// Gets or sets the completion callbacks.
+ ///
+ internal IReadOnlyCollection? CompletionCallbacks { get; set; }
+
+ ///
+ /// Gets or sets the links to attach on activity start.
+ ///
+ internal IReadOnlyCollection? Links { get; set; }
+
+ ///
+ /// Gets or sets the request ID for the activity start request. If null, a new GUID is used.
+ ///
+ internal string? RequestId { get; set; }
+
///
/// Create a shallow copy of these options.
///
diff --git a/src/Temporalio/Client/TemporalClient.Activity.cs b/src/Temporalio/Client/TemporalClient.Activity.cs
index 4b9675b5..ad2c49d7 100644
--- a/src/Temporalio/Client/TemporalClient.Activity.cs
+++ b/src/Temporalio/Client/TemporalClient.Activity.cs
@@ -12,6 +12,7 @@
using Temporalio.Common;
using Temporalio.Converters;
using Temporalio.Exceptions;
+using Temporalio.Nexus;
#if NETCOREAPP3_0_OR_GREATER
using System.Runtime.CompilerServices;
@@ -118,7 +119,7 @@ public override async Task> StartActivityAsync(
Name = input.Options.TaskQueue!,
},
Identity = Client.Connection.Options.Identity,
- RequestId = Guid.NewGuid().ToString(),
+ RequestId = input.Options.RequestId ?? Guid.NewGuid().ToString(),
IdReusePolicy = input.Options.IdReusePolicy,
IdConflictPolicy = input.Options.IdConflictPolicy,
RetryPolicy = input.Options.RetryPolicy?.ToProto(),
@@ -126,7 +127,16 @@ public override async Task> StartActivityAsync(
input.Options.StaticSummary, input.Options.StaticDetails).
ConfigureAwait(false),
Priority = input.Options.Priority?.ToProto(),
+ OnConflictOptions = input.Options.OnConflictOptions,
};
+ if (input.Options.CompletionCallbacks is { } completionCallbacks)
+ {
+ req.CompletionCallbacks.AddRange(completionCallbacks);
+ }
+ if (input.Options.Links is { } activityLinks)
+ {
+ req.Links.AddRange(activityLinks);
+ }
if (input.Args.Count > 0)
{
req.Input = new Payloads();
@@ -173,6 +183,11 @@ public override async Task> StartActivityAsync(
var resp = await Client.Connection.WorkflowService.StartActivityExecutionAsync(
req, DefaultRetryOptions(input.Options.Rpc)).ConfigureAwait(false);
+ if (NexusOperationExecutionContext.HasCurrent &&
+ resp.Link?.ToNexusLink() is { } nexusLink)
+ {
+ NexusOperationExecutionContext.Current.HandlerContext.OutboundLinks.Add(nexusLink);
+ }
return new ActivityHandle(
Client: Client,
Id: input.Options.Id!,
diff --git a/src/Temporalio/Client/TemporalClient.Workflow.cs b/src/Temporalio/Client/TemporalClient.Workflow.cs
index 791a478e..251d3bc4 100644
--- a/src/Temporalio/Client/TemporalClient.Workflow.cs
+++ b/src/Temporalio/Client/TemporalClient.Workflow.cs
@@ -14,6 +14,7 @@
using Temporalio.Common;
using Temporalio.Converters;
using Temporalio.Exceptions;
+using Temporalio.Nexus;
#if NETCOREAPP3_0_OR_GREATER
using System.Runtime.CompilerServices;
@@ -739,6 +740,19 @@ private async Task> StartWorkflowInternalAsyn
}
var resp = await Client.Connection.WorkflowService.StartWorkflowExecutionAsync(
req, DefaultRetryOptions(input.Options.Rpc)).ConfigureAwait(false);
+ if (NexusOperationExecutionContext.HasCurrent)
+ {
+ // Prefer the link returned by the server; fall back to a
+ // WorkflowExecutionStarted link for older servers that don't populate it.
+ var nexusLink = resp.Link?.ToNexusLink() ?? new Link.Types.WorkflowEvent
+ {
+ Namespace = req.Namespace,
+ WorkflowId = req.WorkflowId,
+ RunId = resp.RunId,
+ EventRef = new() { EventId = 1, EventType = EventType.WorkflowExecutionStarted },
+ }.ToNexusLink();
+ NexusOperationExecutionContext.Current.HandlerContext.OutboundLinks.Add(nexusLink);
+ }
return new WorkflowHandle(
Client: Client,
Id: req.WorkflowId,
diff --git a/src/Temporalio/Nexus/ITemporalNexusClient.cs b/src/Temporalio/Nexus/ITemporalNexusClient.cs
index 59bccb15..1a0a9c4e 100644
--- a/src/Temporalio/Nexus/ITemporalNexusClient.cs
+++ b/src/Temporalio/Nexus/ITemporalNexusClient.cs
@@ -45,7 +45,8 @@ public interface ITemporalNexusClient
/// Workflow class type.
/// Workflow result type.
/// Invocation of workflow run method with a result.
- /// Start workflow options. ID and TaskQueue are required.
+ /// Start workflow options. ID is required; TaskQueue defaults to
+ /// the operation's task queue when omitted.
/// An async operation result containing the workflow-run token.
Task> StartWorkflowAsync(
Expression>> workflowRunCall, WorkflowOptions options);
@@ -56,7 +57,8 @@ Task> StartWorkflowAsync(
///
/// Workflow class type.
/// Invocation of workflow run method with no result.
- /// Start workflow options. ID and TaskQueue are required.
+ /// Start workflow options. ID is required; TaskQueue defaults to
+ /// the operation's task queue when omitted.
/// An async operation result containing the workflow-run token.
Task> StartWorkflowAsync(
Expression> workflowRunCall, WorkflowOptions options);
@@ -68,9 +70,52 @@ Task> StartWorkflowAsync(
/// Workflow result type.
/// Workflow type name.
/// Arguments for the workflow.
- /// Start workflow options. ID and TaskQueue are required.
+ /// Start workflow options. ID is required; TaskQueue defaults to
+ /// the operation's task queue when omitted.
/// An async operation result containing the workflow-run token.
Task> StartWorkflowAsync(
string workflow, IReadOnlyCollection