Click or drag to resize

TemporalClient Class

Implements a client that will be connected to a Temporal cluster and be used to create and manage workflows.
Inheritance Hierarchy

Namespace:  Neon.Temporal
Assembly:  Neon.Temporal (in Neon.Temporal.dll) Version: 2.14.0-alpha
public class TemporalClient : IDisposable

The TemporalClient type exposes the following members.

Public propertyDataConverter

Specifies the IDataConverter used for workflows and activities managed by the client. This defaults to JsonDataConverter.

Note Note
When you need a custom data converter, you must set this immediately after connecting the client. You must not change the converter after you've started workers.
Public propertyListenUri
Returns the URI the client is listening on for requests from the temporal-proxy.
Public propertyProxyUri
Returns the URI the associated temporal-proxy instance is listening on.
Public propertySettings
Returns the settings used to create the client.
Public propertySyncSignalRetry

Controls how synchronous signals operations are polled until the signal operation is completed. This defaults to something reasonable.

Note Note
The transient detector function specified by the policy passed is ignore and is replaced by a function that considers all exceptions to be transient.
Public methodActivityCompleteByIdAsync
Used to externally complete an activity identified by WorkflowExecution and activity ID.
Public methodActivityCompleteByTokenAsync
Used to externally complete an activity identified by task token.
Public methodActivityErrorByIdAsync
Used to externally fail an activity by WorkflowExecution and activity ID.
Public methodActivityErrorByTokenAsync
Used to externally fail an activity by task token.
Public methodActivityHeartbeatByIdAsync
Used to record an activity heartbeat externally by WorkflowExecution and activity ID.
Public methodActivityHeartbeatByTokenAsync
Used to record an activity heartbeat externally by task token.
Public methodStatic memberBuildActivityStubTActivity
Prebuilds and caches the internal activity stub class backing the TActivity interface. Subsequent calls for the same activity interface can be made but actually do nothing.
Public methodStatic memberBuildAssemblyStubs
Scans the assembly passed for any workflow or activity interfaces and pebuilds and caches the generated internal backing classes. Subsequent calls for the same assembly can be made but actually do nothing.
Public methodStatic memberBuildWorkflowStubTWorkflow
Prebuilds and caches the internal workflow stub class backing the TWorkflow interface. Subsequent calls for the same workflow interface can be made but actually do nothing.
Public methodStatic memberConnectAsync
Establishes a connection to a Temporal cluster.
Public methodDebugLog

INTERNAL USE ONLY: Appends a line of text to the debug log which is used internally to debug generated code like stubs. This hardcodes its output to C:\Temp\temporal-debug.log so this currently only works on Windows.

Note Note
This method doesn't actually log anything unless Debug is set to true.
Public methodDescribeNamespaceAsync
Describes the named Temporal namespace.
Public methodDescribeQueueListAsync
Returns information about pollers (AKA workers) that have communicated with the Temporal cluster in the last few minutes.
Public methodDescribeWorkflowExecutionAsync(WorkflowExecution, String)
Returns the current state of a running workflow.
Public methodDescribeWorkflowExecutionAsync(String, String, String)
Describes a workflow execution by explicit IDs.
Public methodDispose
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
Protected methodDispose(Boolean)
Releases all associated resources.
Public methodEquals
Determines whether the specified object is equal to the current object.
(Inherited from Object.)
Public methodStatic memberExtractTemporalProxy

Writes the temporal-proxy binaries to the specified folder. This is provided so that you can pre-provision the executable and then use the BinaryPath setting to reference it. These files will be written: The Windows AMD64 executable
temporal-proxy.linux The Linux AMD64 executable
temporal-proxy.osx The OS/X AMD64 executable

This is useful for situations where the executable must be pre-provisioned for security. One example is deploying Temporal workers to a Docker container with a read-only file system.

Protected methodFinalize
(Overrides ObjectFinalize.)
Public methodGetHashCode
Serves as the default hash function.
(Inherited from Object.)
Public methodGetType
Gets the Type of the current instance.
(Inherited from Object.)
Public methodGetWorkflowCacheSizeAsync
Returns the current maximum number of sticky workflows for which history will be retained as a performance optimization.
Public methodListNamespacesAsync
Lists the Temporal namespaces.
Protected methodMemberwiseClone
Creates a shallow copy of the current Object.
(Inherited from Object.)
Public methodNewUntypedWorkflowStub(String, StartWorkflowOptions)
Creates an untyped stub that can be used to start a single workflow execution.
Public methodNewUntypedWorkflowStub(WorkflowExecution, String)
Creates an untyped stub for a known workflow execution.
Public methodNewUntypedWorkflowStub(String, String, String)
Creates an untyped stub for a known workflow execution.
Public methodNewWorkerAsync
Creates a new Temporal Worker attached to the current client. You'll use this to register your workflow and/or activity implementations with Temporal and the start the worker to signal Temporal that the worker is ready for business.
Public methodNewWorkflowFutureStubTWorkflowInterface
Creates a stub suitable for starting an external workflow and then waiting for the result as separate operations.
Public methodNewWorkflowStub(String, StartWorkflowOptions)
Creates an untyped workflow stub to be used for launching a workflow.
Public methodNewWorkflowStubTWorkflowInterface(StartWorkflowOptions, String)
Creates a typed workflow stub that can be used to start as well as query and signal the workflow via the type-safe interface methods.
Public methodNewWorkflowStubTWorkflowInterface(WorkflowExecution, String)
Creates a typed workflow stub connected to a known workflow execution using a WorkflowExecution. This can be used to signal and query the workflow via the type-safe interface methods.
Public methodNewWorkflowStubTWorkflowInterface(String, String, String)
Creates a typed workflow stub connected to a known workflow execution using IDs. This can be used to signal and query the workflow via the type-safe interface methods.
Public methodPingAsync
Pings the temporal-proxy and waits for the reply. This is used mainly for low-level performance and load testing but can also be used to explicitly verify that the temporal-proxy is still alive.
Public methodRegisterNamespaceAsync
Registers a Temporal namespace using the specified parameters.
Public methodSetCacheMaximumSizeAsync

Sets the maximum number of sticky workflows for which of history will be retained for workflow workers created by this client as a performance optimization. When this is exceeded, Temporal will may need to retrieve the entire workflow history from the Temporal cluster when a workflow is scheduled on the client's workers.

This defaults to 10K sticky workflows.

Public methodTerminateWorkflowAsync
Terminates a workflow if it has not already finished.
Public methodToString
Returns a string that represents the current object.
(Inherited from Object.)
Public methodUpdateNamespaceAsync
Updates the named Temporal namespace.
Public methodWaitForWorkflowStartAsync
Waits for a resonable period of time for Temporal to start a workflow.
Public eventConnectionClosed
Raised when the connection is closed. You can determine whether the connection was closed normally or due to an error by examining the TemporalClientClosedArgs arguments passed to the handler.

To get started with Temporal, you'll need to deploy a Temporal cluster with one or more nodes and the establish a connection to the cluster from your workflow/activity implementations and management tools. This is pretty easy to do.

Temporal clusters interacts with client APIs via gRPC on port 7233 (by default). Server nodes are typically configured behind a TCP load balancer or a DNS name is configured such that it returns the IP addresses for each server node. The HostPort property is used to specify how to connect to the cluster. For single node clusters or clusters behind a load balancer, you'll typically specify HOST:7233 where HOST is the DNS name or IP address for the node.

Alternatively, if you've configured DNS to return IP addresses for each cluster node, you can specify dns:///host:port. In this case, the client will round-robin between the node addresses returned to locate healthy nodes to communicate with.

To establish a connection, you'll construct a TemporalSettings and add your cluster endpoint to the HostPort and then call the static ConnectAsync(TemporalSettings) method to obtain a connected TemporalClient. You'll use this for registering workflows and activities types as well as the workers that indicate that workflows and activities can be executed in the current process.

Note Note
IMPORTANT: The current .NET Temporal client release supports having only one client open at a time. A NotSupportedException will be thrown when attempting to connect a second client. This restriction may be relaxed for future releases.

You'll implement your workflows and activities by implementing classes that derive from WorkflowBase and ActivityBase and then registering these types with Temporal. Then you'll start workflow or activity workers so that Temporal will begin scheduling operations for execution by your code. Workflows and activities are registered using the fully qualified names of the derived WorkflowBase and ActivityBase types by defaut, but you can customize this if desired.

Temporal supports the concept of namespaces and task lists. Temporal is multi-tenant and namespaces are simply string names used to isolate deployments. For example, you could define a PROD namespace for your production workflows and STAGE for preproduction. It's also often useful to organize namespaces by the teams implementing and managing their workflows. Each TemporalClient is assigned to a default namespace via Namespace and this defaults to "default" unless you specify something different when connecting the client.

Note Note
You can override the default client namespace for specific operations via WorkerOptions, StartWorkflowOptions, ChildWorkflowOptions, ActivityOptions as well as via the WorkflowInterfaceAttribute, WorkflowMethodAttribute, ActivityInterfaceAttribute and ActivityMethodAttribute attributes decorating your workflow and activity interface definitions.

Once you have a connected TemporalClient, you can create and manage Temporal namespaces via methods like RegisterNamespaceAsync(String, String, String, Int32, Boolean), DescribeNamespaceAsync(String), and UpdateNamespaceAsync(String, UpdateNamespaceRequest).

Workflows and activities are implemented by creating a Worker via NewWorkerAsync(String, String, WorkerOptions), registering your workflow and activity implementations with the worker and then starting the worker via StartAsync. Temporal will begin scheduling pending workflows and activities on workers after they've been started.

The Worker class provides methods for registering individual workflow and activity implementations, including RegisterWorkflowAsyncTWorkflow(Boolean) and RegisterActivityAsyncTActivity(Boolean) as well as methods that register all workflow and activity implementation discovered in an assembly: RegisterAssemblyActivitiesAsync(Assembly, Boolean), RegisterAssemblyWorkflowsAsync(Assembly, Boolean), and RegisterAssemblyAsync(Assembly, Boolean) (which registers both workflow and assembly implementations).

Workflows are implemented by defining an interface describing the workflow methods and then writing a class the implements your interface and also inherits WorkflowBase. Your workflow interface must define at least one entry point method tagged by WorkflowMethodAttribute and may optionally include signal and query methods tagged by SignalMethodAttribute and QueryMethodAttribute.

Activities are implemented in the same way by defining an activity interface and then writing a class that implements this interface. and inherits ActivityBase. Your activity interface must define at least one entry point method.

You'll generally create stub classes to start and manage workflows and activities. These come in various flavors with the most important being typed and untyped stubs. Typed stubs are nice because they implement your workflow or activity interface so that the C# compiler can provide compile-time type checking. Untyped stubs provide a way to interact with workflows and activities written on other languages or for which you don't have source code.

You can create typed external workflow stubs via NewWorkflowStubTWorkflowInterface(String, String, String) and NewWorkflowStubTWorkflowInterface(StartWorkflowOptions, String).

Workflows can use their Workflow property to create child workflow as well as activity stubs.

Task Lists

Task lists are used by Temporal to identify the set of workflows and activities that are implemented by workers. For example, if you deploy a program called payments.exe that implements payment related workflows and activities like validate, debit, credit,... you could register these and then start a worker using taskqueue=payments.

You'll need to provide the correct task queue when executing a workflow or normal (non-local) activity. Temporal will schedule the workflow or activity on one of the workers that was started with the specified task queue. The most convienent way to specify the task queue is to tag your workflow and activity interfaces with [WorkflowInterface(TaskQueue = "payments")] and [ActivityInterface(TaskQueue = "payments")] attributes, specifying the target task queue.

Note Note
You may specify a default task queue when connecting a TemporalClient via TaskQueue (which defaults to null). This may be convienent for simple deployments.

You may also specify a custom task queue in the workflow and activity options used when executing a workflow or activity. A task queue specified in one of these options takes precedence over the task queue specified in an attribute.

Note Note
The .NET client will complain if a task queue is not specified in either an interface attribute via options and the there's no client default task queue set.
Note Note

IMPORTANT: You need to take care to ensure that the task lists you use for your workers uniquely identify the set of workflows and activities implemented by your the workers. For example, if you start two workers, worker-a and worker-b using the same task queue, but worker-a registers the foo workflow and worker-b registers the bar activity, you're going run into trouble.

The problem is that Cadence assumes that both workers implement the same workflows, both foo and bar in this case. Say you start a foo workflow. Temporal will select one of worker-a or worker-b to run the workflow. If Temporal happens to select worker-a everything will work as expected because foo is registered there. If Temporal selects worker-b the initial execution will fail because foo is not registered there. Temporal handles this a decision task failure and will attempt to reschedule the workflow on another worker (hopefully worker-a this time).

Temporal fault tolerance will probably end up being able to handle this sort misconfiguration, but at the cost of additional delays as well as unnecessary communication overhead to workers that will never be able to execute unregistered workflows and activities.

So the moral of this store is carefully choose your task lists to match the set of workflows and activities implemented by your application. One common approach is to name the task queue after the service or application that implements the workflow anbd activities.

Note Note

Activity and workflow stubs are generated and compiled on demand by default. This takes about 500ms for each stub. This generally works fine but may cause decision task timeouts for workflows that call a lot of different child workflows or activities.

The default workflow decision task timeout is 10 seconds, so a workflow that creates 22 stubs when its first called will have a decent chance of timing out due to the 500ms * 22 = 11 seconds it will take for the .NET client generate and build the backing classes.

Note Note
This is only an issue the first time a stub classes are built, so it'll be very likely that the workflow will proceed the second time it's invoked on the same worker because the generated stub classes are cached.

You can proactively address this by prebuilding stub classes before starting any workers by calling BuildActivityStubTActivity, BuildWorkflowStubTWorkflow, and/or BuildAssemblyStubs(Assembly). After doing this, the specified stubs will already be generated and compiled when the worker starts and begins invoking workflows and activities.

See Also