Click or drag to resize

CadenceClient Class

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

Namespace:  Neon.Cadence
Assembly:  Neon.Cadence (in Neon.Cadence.dll) Version: 2.14.0
public class CadenceClient : IDisposable

The CadenceClient 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 cadence-proxy.
Public propertyProxyUri
Returns the URI the associated cadence-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 send record activity heartbeat externally by WorkflowExecution and activity ID.
Public methodActivityHeartbeatByTokenAsync
Used to send record 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 Cadence 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\cadence-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 methodDescribeDomainAsync
Describes the named Cadence domain.
Public methodDescribeDomainByIdAsync
Describes a Cadence domain by UUID.
Public methodDescribeTaskListAsync
Returns information about pollers (AKA workers) that have communicated with the Cadence cluster in the last few minutes.
Public methodDescribeWorkflowExecutionAsync
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 memberExtractCadenceProxy

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: The Windows AMD64 executable
cadence-proxy.linux The Linux AMD64 executable
cadence-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 Cadence 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 methodListDomainsAsync
Lists the Cadence domains.
Protected methodMemberwiseClone
Creates a shallow copy of the current Object.
(Inherited from Object.)
Public methodNewUntypedWorkflowStub(String, WorkflowOptions)
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 methodNewWorkflowFutureStubTWorkflowInterface
Creates a stub suitable for starting an external workflow and then waiting for the result as separate operations.
Public methodNewWorkflowStub(String, WorkflowOptions)
Creates an untyped workflow stub to be used for launching a workflow.
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(WorkflowOptions, 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(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 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.
Public methodRegisterActivityAsyncTActivity
Registers an activity implementation with Cadence.
Public methodRegisterAssemblyActivitiesAsync
Scans the assembly passed looking for activity implementations derived from ActivityBase and tagged by ActivityAttribute and registers them with Cadence.
Public methodRegisterAssemblyAsync
Scans the assembly passed looking for workflow and activity implementations derived from and registers them with Cadence. This is equivalent to calling RegisterAssemblyWorkflowsAsync(Assembly, String) and RegisterAssemblyActivitiesAsync(Assembly, String),
Public methodRegisterAssemblyWorkflowsAsync
Scans the assembly passed looking for workflow implementations derived from WorkflowBase and tagged by WorkflowAttribute with AutoRegister set to true and registers them with Cadence.
Public methodRegisterDomainAsync
Registers a Cadence domain using the specified parameters.
Public methodRegisterWorkflowAsyncTWorkflow
Registers a workflow implementation with Cadence.
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, 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.

Public methodStartWorkerAsync
Signals Cadence that the application is capable of executing workflows and/or activities for a specific domain and task list.
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 methodUpdateDomainAsync
Updates the named Cadence domain.
Public methodWaitForWorkflowStartAsync
Waits for a resonable period of time for Cadence 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 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.

Note Note
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 CadenceClient. 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 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 CadenceClient, you can create and manage Cadence domains via methods like 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.

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.

Note Note

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".

If this huristic doesn't work, you'll need to explicitly specify the same type name in the WorkflowAttribute or ActivityAttribute tagging your interface and class definitions.

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

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.

Note Note
The .NET client will complain if a task list is not specified in either an interface attribute or the options.
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 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.

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