|
| 1 | +--- |
| 2 | +type: docs |
| 3 | +title: "How to: Author and manage Dapr Workflow in the JavaScript SDK" |
| 4 | +linkTitle: "How to: Author and manage workflows" |
| 5 | +weight: 20000 |
| 6 | +description: How to get up and running with workflows using the Dapr JavaScript SDK |
| 7 | +--- |
| 8 | + |
| 9 | +{{% alert title="Note" color="primary" %}} |
| 10 | +Dapr Workflow is currently in beta. [See known limitations for {{% dapr-latest-version cli="true" %}}]({{< ref "workflow-overview.md#limitations" >}}). |
| 11 | +{{% /alert %}} |
| 12 | + |
| 13 | +Let’s create a Dapr workflow and invoke it using the console. With the [provided workflow example](https://github.com/dapr/js-sdk/tree/main/examples/workflow), you will: |
| 14 | + |
| 15 | +- Execute the workflow instance using the [JavaScript workflow worker](https://github.com/dapr/js-sdk/tree/main/src/workflow/runtime/WorkflowRuntime.ts) |
| 16 | +- Utilize the JavaScript workflow client and API calls to [start and terminate workflow instances](https://github.com/dapr/js-sdk/tree/main/src/workflow/client/DaprWorkflowClient.ts) |
| 17 | + |
| 18 | +This example uses the default configuration from `dapr init` in [self-hosted mode](https://github.com/dapr/cli#install-dapr-on-your-local-machine-self-hosted). |
| 19 | + |
| 20 | +## Prerequisites |
| 21 | + |
| 22 | +- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started). |
| 23 | +- [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm), |
| 24 | +- [Docker Desktop](https://www.docker.com/products/docker-desktop) |
| 25 | +<!-- END_IGNORE --> |
| 26 | +- Verify you're using the latest proto bindings |
| 27 | + |
| 28 | +## Set up the environment |
| 29 | + |
| 30 | +Clone the JavaScript SDK repo and navigate into it. |
| 31 | + |
| 32 | +```bash |
| 33 | +git clone https://github.com/dapr/js-sdk |
| 34 | +cd js-sdk |
| 35 | +``` |
| 36 | + |
| 37 | +From the JavaScript SDK root directory, navigate to the Dapr Workflow example. |
| 38 | + |
| 39 | +```bash |
| 40 | +cd examples/workflow/authoring |
| 41 | +``` |
| 42 | + |
| 43 | +Run the following command to install the requirements for running this workflow sample with the Dapr JavaScript SDK. |
| 44 | + |
| 45 | +```bash |
| 46 | +npm install |
| 47 | +``` |
| 48 | + |
| 49 | +## Run the `activity-sequence.ts` |
| 50 | + |
| 51 | +The `activity-sequence` file registers a workflow and an activity with the Dapr Workflow runtime. The workflow is a sequence of activities that are executed in order. We use DaprWorkflowClient to schedule a new workflow instance and wait for it to complete. |
| 52 | + |
| 53 | +```typescript |
| 54 | +const daprHost = "localhost"; |
| 55 | +const daprPort = "50001"; |
| 56 | +const workflowClient = new DaprWorkflowClient({ |
| 57 | + daprHost, |
| 58 | + daprPort, |
| 59 | +}); |
| 60 | +const workflowRuntime = new WorkflowRuntime({ |
| 61 | + daprHost, |
| 62 | + daprPort, |
| 63 | +}); |
| 64 | + |
| 65 | +const hello = async (_: WorkflowActivityContext, name: string) => { |
| 66 | + return `Hello ${name}!`; |
| 67 | +}; |
| 68 | + |
| 69 | +const sequence: TWorkflow = async function* (ctx: WorkflowContext): any { |
| 70 | + const cities: string[] = []; |
| 71 | + |
| 72 | + const result1 = yield ctx.callActivity(hello, "Tokyo"); |
| 73 | + cities.push(result1); |
| 74 | + const result2 = yield ctx.callActivity(hello, "Seattle"); |
| 75 | + cities.push(result2); |
| 76 | + const result3 = yield ctx.callActivity(hello, "London"); |
| 77 | + cities.push(result3); |
| 78 | + |
| 79 | + return cities; |
| 80 | +}; |
| 81 | + |
| 82 | +workflowRuntime.registerWorkflow(sequence).registerActivity(hello); |
| 83 | + |
| 84 | +// Wrap the worker startup in a try-catch block to handle any errors during startup |
| 85 | +try { |
| 86 | + await workflowRuntime.start(); |
| 87 | + console.log("Workflow runtime started successfully"); |
| 88 | +} catch (error) { |
| 89 | + console.error("Error starting workflow runtime:", error); |
| 90 | +} |
| 91 | + |
| 92 | +// Schedule a new orchestration |
| 93 | +try { |
| 94 | + const id = await workflowClient.scheduleNewWorkflow(sequence); |
| 95 | + console.log(`Orchestration scheduled with ID: ${id}`); |
| 96 | + |
| 97 | + // Wait for orchestration completion |
| 98 | + const state = await workflowClient.waitForWorkflowCompletion(id, undefined, 30); |
| 99 | + |
| 100 | + console.log(`Orchestration completed! Result: ${state?.serializedOutput}`); |
| 101 | +} catch (error) { |
| 102 | + console.error("Error scheduling or waiting for orchestration:", error); |
| 103 | +} |
| 104 | +``` |
| 105 | + |
| 106 | +In the code above: |
| 107 | + |
| 108 | +- `workflowRuntime.registerWorkflow(sequence)` registers `sequence` as a workflow in the Dapr Workflow runtime. |
| 109 | +- `await workflowRuntime.start();` builds and starts the engine within the Dapr Workflow runtime. |
| 110 | +- `await workflowClient.scheduleNewWorkflow(sequence)` schedules a new workflow instance with the Dapr Workflow runtime. |
| 111 | +- `await workflowClient.waitForWorkflowCompletion(id, undefined, 30)` waits for the workflow instance to complete. |
| 112 | + |
| 113 | +In the terminal, execute the following command to kick off the `activity-sequence.ts`: |
| 114 | + |
| 115 | +```sh |
| 116 | +npm run start:dapr:activity-sequence |
| 117 | +``` |
| 118 | + |
| 119 | +**Expected output** |
| 120 | + |
| 121 | +``` |
| 122 | +You're up and running! Both Dapr and your app logs will appear here. |
| 123 | +
|
| 124 | +... |
| 125 | +
|
| 126 | +== APP == Orchestration scheduled with ID: dc040bea-6436-4051-9166-c9294f9d2201 |
| 127 | +== APP == Waiting 30 seconds for instance dc040bea-6436-4051-9166-c9294f9d2201 to complete... |
| 128 | +== APP == Received "Orchestrator Request" work item with instance id 'dc040bea-6436-4051-9166-c9294f9d2201' |
| 129 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Rebuilding local state with 0 history event... |
| 130 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Processing 2 new history event(s): [ORCHESTRATORSTARTED=1, EXECUTIONSTARTED=1] |
| 131 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Waiting for 1 task(s) and 0 event(s) to complete... |
| 132 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Returning 1 action(s) |
| 133 | +== APP == Received "Activity Request" work item |
| 134 | +== APP == Activity hello completed with output "Hello Tokyo!" (14 chars) |
| 135 | +== APP == Received "Orchestrator Request" work item with instance id 'dc040bea-6436-4051-9166-c9294f9d2201' |
| 136 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Rebuilding local state with 3 history event... |
| 137 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Processing 2 new history event(s): [ORCHESTRATORSTARTED=1, TASKCOMPLETED=1] |
| 138 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Waiting for 1 task(s) and 0 event(s) to complete... |
| 139 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Returning 1 action(s) |
| 140 | +== APP == Received "Activity Request" work item |
| 141 | +== APP == Activity hello completed with output "Hello Seattle!" (16 chars) |
| 142 | +== APP == Received "Orchestrator Request" work item with instance id 'dc040bea-6436-4051-9166-c9294f9d2201' |
| 143 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Rebuilding local state with 6 history event... |
| 144 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Processing 2 new history event(s): [ORCHESTRATORSTARTED=1, TASKCOMPLETED=1] |
| 145 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Waiting for 1 task(s) and 0 event(s) to complete... |
| 146 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Returning 1 action(s) |
| 147 | +== APP == Received "Activity Request" work item |
| 148 | +== APP == Activity hello completed with output "Hello London!" (15 chars) |
| 149 | +== APP == Received "Orchestrator Request" work item with instance id 'dc040bea-6436-4051-9166-c9294f9d2201' |
| 150 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Rebuilding local state with 9 history event... |
| 151 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Processing 2 new history event(s): [ORCHESTRATORSTARTED=1, TASKCOMPLETED=1] |
| 152 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Orchestration completed with status COMPLETED |
| 153 | +== APP == dc040bea-6436-4051-9166-c9294f9d2201: Returning 1 action(s) |
| 154 | +INFO[0006] dc040bea-6436-4051-9166-c9294f9d2201: 'sequence' completed with a COMPLETED status. app_id=activity-sequence-workflow instance=kaibocai-devbox scope=wfengine.backend type=log ver=1.12.3 |
| 155 | +== APP == Instance dc040bea-6436-4051-9166-c9294f9d2201 completed |
| 156 | +== APP == Orchestration completed! Result: ["Hello Tokyo!","Hello Seattle!","Hello London!"] |
| 157 | +``` |
| 158 | + |
| 159 | +## Next steps |
| 160 | + |
| 161 | +- [Learn more about Dapr workflow]({{< ref workflow-overview.md >}}) |
| 162 | +- [Workflow API reference]({{< ref workflow_api.md >}}) |
0 commit comments