Thetype exposes the following members.
Returns the URI the client is listening on for requests from the cadence-proxy.
Returns the URI the associated cadence-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 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.
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.
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.
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.
Establishes a connection to a Cadence 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\cadence-debug.log so this currently only works on Windows.
Describes the named Cadence domain.
Describes a Cadence domain by UUID.
Returns information about pollers (AKA workers) that have communicated with the Cadence cluster in the last few minutes.
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 cadence-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 Cadence 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 Cadence domains.
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 cadence-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 cadence-proxy is still alive.
Registers an activity implementation with Cadence.
Registers a Cadence domain using the specified parameters.
Registers a workflow implementation with Cadence.
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, Cadence will may need to retrieve the entire workflow history from the Cadence cluster when a workflow is scheduled on the client's workers.
This defaults to 10K sticky workflows.
Signals Cadence that the application is capable of executing workflows and/or activities for a specific domain 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 Cadence domain.
Waits for a resonable period of time for Cadence 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 CadenceClientClosedArgs arguments passed to the handler.
To get started with Cadence, you'll need to deploy a Cadence 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.
First, you'll need to know the URI of at least one of the Cadence cluster nodes. Cadence listens on port 79133 by default so you cluster URIs will typically look like: http://CADENCE-NODE:7933.
|For production clusters with multiple Cadence nodes, you should specify multiple URIs when connecting just in case the one of the nodes may be offline for some reason.|
To establish a connection, you'll construct a CadenceSettings and add your node URIs to the Servers list and then call the static ConnectAsync(CadenceSettings) 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 Cadence 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 Cadence. Then you'll start workflow or activity workers so that Cadence 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.
Cadence supports the concept of domains and task lists. Domains and task lists are used to organize workflows and activities. Workflows and activities essentially reside in a registered domain, which is essentially just a namespace specified by a string. The combination of a domain along with a workflow or activity type name must be unique within a Cadence cluster. Once you have a connected RegisterDomainAsync(String, String, String, Int32, Boolean), DescribeDomainAsync(String), and UpdateDomainAsync(String, UpdateDomainRequest). Domains 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 Cadence domains via methods like
Cadence workers are started to indicate that the current process can execute workflows and activities from a Cadence domain, and optionally a task list (discussed further below). You'll call StartWorkerAsync(String, WorkerOptions, String) to indicate that Cadence 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 Cadence cluster, you'll need to call RegisterWorkflowAsyncTWorkflow(String, String) and/or RegisterActivityAsyncTActivity(String, String) to register your workflow and activity implementations with Cadence. 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 Cadence that the current process implements specific workflow and activity types. You'll call StartWorkerAsync(String, WorkerOptions, String). You can customize the Cadence domain 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 Cadence 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. Cadence 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. Cadence will select one of worker-a or worker-b to run the workflow. If Cadence happens to select worker-a everything will work as expected because foo is registered there. If Cadence selects worker-b the initial execution will fail because foo is not registered there. Cadence handles this a decision task failure and will attempt to reschedule the workflow on another worker (hopefully worker-a this time).
Cadence 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.
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.
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.