Meet Cadence: Workflow Engine for Taming Complex Processes
The Cadence code platform and workflow engine can abstract away the most difficult complexities in developing high-scale distributed applications.
Jan 27th, 2022 4:00am by
Feature image via Pixabay
Instaclustr sponsored this post.
Ben Bromhead
Ben Bromhead is co-founder and chief technology officer at Instaclustr, which provides a platform around open source data technologies.
Emrah Seker
Emrah is a staff software engineer at Uber. His software development experience covers a wide span from kernel-level programming to distributed web services. He loves working on cloud computing and highly scalable systems. Emrah’s previous companies include Box, Microsoft and Siemens.
How Does Cadence Work?
Cadence preserves the entire state of an application in durable virtual memory not associated with any specific process. The stored application state includes all call parameters and returned results for user-defined activities. It then uses that information to catch up and replay workflows that get interrupted. Cadence has libraries that enable developers to create and coordinate workflows using popular languages such as Java, Go, Python and Ruby. Cadence services, such as workers, are largely stateless and leverage a data store for task/workflow persistence. Supported storage options include open source Cassandra and MySQL/PostgreSQL, and an adapter is available for any database featuring multi-row single shard transactions. Multiple service deployment models are available as well. For example, Uber uses multitenant Cadence clusters shared by hundreds of applications. In this way, Cadence empowers developers with a new tool for writing and managing distributed applications while maintaining application durability, availability and scalability.How Does Cadence Help Developers?
Cadence offers a lot of value to development teams that work with microservices-based architectures that require fault tolerance, as well as applications that include myriad multistep concurrent workflows or interact with multiple third-party APIs. But Cadence’s versatility lends itself to nearly any scenario involving multiple requests and replies. Developers can use Cadence to create applications that serve as workflow and orchestration platforms, and get back tremendous boosts to developer productivity by replacing traditional strategies for leveraging databases and task queues.- Periodic execution (distributed cron). Cadence guarantees the execution of periodically-scheduled business logic, complete with complex error handling, retry policies and asynchronous history event replication. Importantly, Cadence supports the execution of jobs in parallel and at a massive scale, with the capability to execute millions of workflows concurrently.
- Microservice orchestration. Business processes implemented as multiple microservices calls must have all those calls succeed, even if downstream services fail. Cadence guarantees completion of workflow code, supporting unlimited retries and making compensation logic simple to develop, such as the SAGA pattern.
- Polling. Polling jobs that periodically check for a state change — often used for monitoring or file processing — are particularly well-matched with Cadence’s support for long-running activities and unlimited retries.
- Event-driven applications. Cadence directly supports asynchronous events and abstracts away the complexity of state persistence for developers, making it simple to implement applications that listen to multiple event sources.
- Storage scanning. Cadence enables scalable, resilient and complete scans of large partitioned datasets, even across billions of files.
- Batch jobs. For batch jobs where external API calls may fail, Cadence guarantees durability.
- Infrastructure provisioning. Long-running provisioning operations can suffer from intermittent failures; Cadence prevents this from happening. The platform further supports routing of activity execution to specific processes or hosts, as well as scalable fault-tolerant locking behavior to execute a single mutation on a resource at a time.
- CI/CD pipelines and application deployment. By enabling developers’ focus on business logic, Cadence offers an ideal platform for building deployment solutions.
- Operational management. Cadence enables automated management and recovery for creating self-operating databases and more.
- Interactive applications. Cadence’s performance and scalability enable UI session state tracking and simultaneous background operation execution.
- DSL workflows. The Cadence SDK allows developers to write fault-tolerant, scalable, durable applications that interpret DSL process definitions.
- Big data and ML. Cadence offers a powerful control plane for big data and machine learning solutions, providing task execution routing to control how ML models and other files are allocated.
How Can You Get Started?
To get started using Cadence, grab the GitHub repo for the Cadence server or the Docker image.Cadence: Java Hello World example
The following example demonstrates how to create and run a Hello World application in Cadence using Java. First, get the latest Cadence Java client here. Include it as a dependency in your Java project, which looks like this in Gradle.
compile group: 'com.uber.cadence', name: 'cadence-client', version: '<latest_version>'
compile group: 'commons-configuration', name: 'commons-configuration', version: '1.9'
compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'
import com.uber.cadence.workflow.Workflow;
import com.uber.cadence.workflow.WorkflowMethod;
import org.slf4j.Logger;
public class GettingStarted {
private static Logger logger = Workflow.getLogger(GettingStarted.class);
public interface HelloWorld {
@WorkflowMethod
void sayHello(String name);
}
}
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="io.netty" level="INFO"/>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
HelloWorldImpl with the sayHello method:
import com.uber.cadence.worker.Worker;
import com.uber.cadence.workflow.Workflow;
import com.uber.cadence.workflow.WorkflowMethod;
import org.slf4j.Logger;
public class GettingStarted {
private static Logger logger = Workflow.getLogger(GettingStarted.class);
public interface HelloWorld {
@WorkflowMethod
void sayHello(String name);
}
public static class HelloWorldImpl implements HelloWorld {
@Override
public void sayHello(String name) {
logger.info("Hello " + name + "!");
}
}
}
public static void main(String[] args) {
WorkflowClient workflowClient =
WorkflowClient.newInstance(
new WorkflowServiceTChannel(ClientOptions.defaultInstance()),
WorkflowClientOptions.newBuilder().setDomain(DOMAIN).build());
// Get worker to poll the task list.
WorkerFactory factory = WorkerFactory.newInstance(workflowClient);
Worker worker = factory.newWorker(TASK_LIST);
worker.registerWorkflowImplementationTypes(HelloWorldImpl.class);
factory.start();
}
> docker run --network=host --rm ubercadence/cli:master --do test-domain workflow start --tasklist HelloWorldTaskList --workflow_type HelloWorld::sayHello --execution_timeout 3600 --input \"World\"
Started Workflow Id: bcacfabd-9f9a-46ac-9b25-83bcea5d7fd7, run Id: e7c40431-8e23-485b-9649-e8f161219efe
13:40:28.308 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - Hello World!
YOUTUBE.COM/THENEWSTACK
Tech moves fast, don't miss an episode. Subscribe to our YouTube
channel to stream all our podcasts, interviews, demos, and more.