Thetype exposes the following members.
Returns the URI the client is listening on for requests from the temporal-proxy.
Returns the URI the associated temporal-proxy instance is listening on.
Returns the settings used to create the client.
Controls how synchronous signals operations are polled until the signal operation is completed. This defaults to something reasonable.
Used to externally cancel an activity identified by WorkflowExecution and activity ID.
Used to externally cancel an activity identified by task token.
Used to externally complete an activity identified by WorkflowExecution and activity ID.
Used to externally complete an activity identified by task token.
Used to externally fail an activity by WorkflowExecution and activity ID.
Used to externally fail an activity by task token.
Used to send record activity heartbeat externally by WorkflowExecution and activity ID.
Used to send record activity heartbeat externally by task token.
Establishes a connection to a Temporal cluster.
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.
Describes the named Temporal namespace.
Describes a Temporal namespace by UUID.
Returns information about pollers (AKA workers) that have communicated with the Temporal cluster in the last few minutes.
Returns the current state of a running workflow.
|DescribeWorkflowExecutionAsync(String, String, String)|
Describes a workflow execution by explicit IDs.
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
Releases all associated resources.
Determines whether the specified object is equal to the current object.(Inherited from Object.)
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:
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.
Serves as the default hash function.(Inherited from Object.)
Gets the Type of the current instance.(Inherited from Object.)
Returns the current maximum number of sticky workflows for which history will be retained as a performance optimization.
Lists the Temporal namespaces.
Creates a shallow copy of the current Object.(Inherited from Object.)
Creates an untyped stub that can be used to start a single workflow execution.
Creates an untyped stub for a known workflow execution.
|NewUntypedWorkflowStub(String, String, String)|
Creates an untyped stub for a known workflow execution.
Creates a stub suitable for starting an external workflow and then waiting for the result as separate operations.
Creates an untyped workflow stub to be used for launching a workflow.
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.
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.
|NewWorkflowStubTWorkflowInterface(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.
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.
Registers an activity implementation with Temporal.
Registers a Temporal namespace using the specified parameters.
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.
Signals Temporal that the application is capable of executing workflows and/or activities for a specific namespace and task list.
Terminates a workflow if it has not already finished.
Returns a string that represents the current object.(Inherited from Object.)
Updates the named Temporal namespace.
Waits for a resonable period of time for Temporal to start a workflow.
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 . 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.
|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. These are used to organize workflows and activities. Workflows and activities essentially reside in a registered namespace, which is essentially just a namespace specified by a string. The combination of a namespace along with a workflow or activity type name must be unique within a Temporal cluster. Once you have a connected RegisterNamespaceAsync(String, String, String, Int32, Boolean), DescribeNamespaceAsync(String), and UpdateNamespaceAsync(String, UpdateNamespaceRequest). Namespaces can be used provide isolated areas for different teams and/or different environments (e.g. production, staging, and test). We discuss task lists in detail further below., you can create and manage Temporal namespaces via methods like
Temporal workers are started to indicate that the current process can execute workflows and activities from a Temporal namespace, and optionally a task list (discussed further below). You'll call StartWorkerAsync(String, WorkerOptions, String) to indicate that Temporal can begin scheduling workflow and activity executions from the current client.
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.
After establishing a connection ot a Temporal cluster, you'll need to call RegisterWorkflowAsyncTWorkflow(String, String) and/or RegisterActivityAsyncTActivity(String, String) to register your workflow and activity implementations with Temporal. These calls combined with the workers described above determine which workflows and activities may be scheduled on the current client/process.
For situations where you have a lot of workflow and activity classes, it can become cumbersome to register each implementation class individually (generally because you forget to register new classes after they've been implemented). To assist with this, you can also tag your workflow and activity classes with WorkflowAttribute or ActivityAttribute with AutoRegister or AutoRegister set to true and then call RegisterAssemblyWorkflowsAsync(Assembly, String) and/or RegisterAssemblyActivitiesAsync(Assembly, String) to scan an assembly and automatically register the tagged implementation classes it finds.
The .NET client uses a simple huristic to try to ensure that the default workflow and activity type names applied when the Name and Name properties are not set for the interface and implementation classes. If the interface name starts with an "I", the "I" will be stripped out before generating the fully qualified type name. This handles the common C# convention where interface names started with an "I" and the implementing class uses the same name as the interface, but without the "I".
Next you'll need to start workflow and/or activity workers. These indicate to Temporal that the current process implements specific workflow and activity types. You'll call StartWorkerAsync(String, WorkerOptions, String). You can customize the Temporal namespace and task list the worker will listen on as well as whether activities, workflows, or both are to be processed.
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(WorkflowOptions, String).
Workflows can use their Workflow property to create child workflow as well as activity stubs.
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 tasklist=payments.
You'll need to provide the correct task list 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 list. The most convienent way to specify the task list is to tag your workflow and activity interfaces with [WorkflowInterface(TaskList = "payments")] and [ActivityInterface(TaskList = "payments")] attributes, specifying the target task list.
You may also specify a custom task list in the workflow and activity options used when executing a workflow or activity. A task list specified in one of these options takes precedence over the task list specified in an attribute.
|The .NET client will complain if a task list is not specified in either an interface attribute or the options.|
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 registered for the workers. For example, if you start two workers, worker-a and worker-b using the same task list, 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 list after the service or application that implements the workflow anbd activities.