@io-orkes/conductor-javascript 2.1.5 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,55 +1,828 @@
1
- # Conductor OSS Javascript/Typescript SDK
1
+ # Conductor OSS JavaScript/TypeScript SDK
2
2
 
3
- The `conductor-javascript` repository provides the client SDKs to build task workers in javascript/typescript.
3
+ A comprehensive TypeScript/JavaScript client for [Conductor OSS](https://github.com/conductor-oss/conductor), enabling developers to build, orchestrate, and monitor distributed workflows with ease.
4
4
 
5
- Building the task workers in javascript mainly consists of the following steps:
5
+ [Conductor](https://www.conductor-oss.org/) is the leading open-source orchestration platform allowing developers to build highly scalable distributed applications.
6
6
 
7
- 1. Setup conductor-javascript package
8
- 2. [Create and run task workers](workers_sdk.md)
9
- 3. [Create workflows using code](workflow_sdk.md)
10
-
11
- ### Setup Conductor Javascript Package
7
+ Check out the [official documentation for Conductor](https://orkes.io/content).
12
8
 
13
- * Get the package from npm
9
+ ## Conductor OSS
14
10
 
15
- ```shell
16
- npm i @io-orkes/conductor-javascript
11
+ Show support for the Conductor OSS. Please help spread the awareness by starring Conductor repo.
12
+
13
+ [![GitHub stars](https://img.shields.io/github/stars/conductor-oss/conductor.svg?style=social&label=Star&maxAge=)](https://GitHub.com/conductor-oss/conductor/)
14
+
15
+ ## Table of Contents
16
+
17
+ - [Installation](#installation)
18
+ - [Quick Start](#quick-start)
19
+ - [Authentication & Configuration](#authentication--configuration)
20
+ - [Access Control Setup](#access-control-setup)
21
+ - [Configuration Options](#configuration-options)
22
+ - [Environment Variables](#environment-variables)
23
+ - [Custom Fetch Function](#custom-fetch-function)
24
+ - [Core Concepts](#core-concepts)
25
+ - [What are Tasks?](#what-are-tasks)
26
+ - [What are Workflows?](#what-are-workflows)
27
+ - [What are Workers?](#what-are-workers)
28
+ - [What is the Scheduler?](#what-is-the-scheduler)
29
+ - [Task Types](#task-types)
30
+ - [System Tasks - Managed by Conductor Server](#system-tasks---managed-by-conductor-server)
31
+ - [SIMPLE Tasks - Require Custom Workers](#simple-tasks---require-custom-workers)
32
+ - [Workflows](#workflows)
33
+ - [The WorkflowExecutor and TaskClient](#the-workflowexecutor-and-taskclient)
34
+ - [Quick Start: Creating a Workflow](#quick-start-creating-a-workflow)
35
+ - [Step 1: Define Your Workflow Structure](#step-1-define-your-workflow-structure)
36
+ - [Step 2: Use Task Generators to Build Your Task List](#step-2-use-task-generators-to-build-your-task-list)
37
+ - [Step 3: Register and Start Your Workflow](#step-3-register-and-start-your-workflow)
38
+ - [Step 4: Manage and Monitor Execution](#step-4-manage-and-monitor-execution)
39
+ - [Use TaskClient to Monitor and Debug Tasks](#use-taskclient-to-monitor-and-debug-tasks)
40
+ - [Workers](#workers)
41
+ - [The TaskManager](#the-taskmanager)
42
+ - [Quick Start: Building a Worker](#quick-start-building-a-worker)
43
+ - [Step 1: Define the Worker's Logic](#step-1-define-the-workers-logic)
44
+ - [Step 2: Handle Task Outcomes and Errors](#step-2-handle-task-outcomes-and-errors)
45
+ - [Step 3: Run the Worker with TaskManager](#step-3-run-the-worker-with-taskmanager)
46
+ - [Worker Design Principles](#worker-design-principles)
47
+ - [Scheduling](#scheduling)
48
+ - [The SchedulerClient](#the-schedulerclient)
49
+ - [Quick Start: Scheduling a Workflow](#quick-start-scheduling-a-workflow)
50
+ - [Step 1: Create a SchedulerClient](#step-1-create-a-schedulerclient)
51
+ - [Step 2: Define the Schedule](#step-2-define-the-schedule)
52
+ - [Step 3: Manage the Schedule](#step-3-manage-the-schedule)
53
+ - [Service Registry](#service-registry)
54
+ - [The ServiceRegistryClient](#the-serviceregistryclient)
55
+ - [Quick Start: Using the Service Registry](#quick-start-using-the-service-registry)
56
+ - [Step 1: Create a ServiceRegistryClient](#step-1-create-a-serviceregistryclient)
57
+ - [Step 2: Register a Service](#step-2-register-a-service)
58
+ - [Step 3: Manage Services](#step-3-manage-services)
59
+ - [Metadata](#metadata)
60
+ - [The MetadataClient](#the-metadataclient)
61
+ - [Quick Start: Managing Metadata](#quick-start-managing-metadata)
62
+ - [Step 1: Create a MetadataClient](#step-1-create-a-metadataclient)
63
+ - [Step 2: Define and Register a Task](#step-2-define-and-register-a-task)
64
+ - [Step 3: Define and Register a Workflow](#step-3-define-and-register-a-workflow)
65
+ - [Human Tasks](#human-tasks)
66
+ - [The HumanExecutor and TemplateClient](#the-humanexecutor-and-templateclient)
67
+ - [Quick Start: Creating and Managing a Human Task](#quick-start-creating-and-managing-a-human-task)
68
+ - [Step 1: Create API Clients](#step-1-create-api-clients)
69
+ - [Step 2: Register a Form Template](#step-2-register-a-form-template)
70
+ - [Step 3: Create a Workflow with a Human Task](#step-3-create-a-workflow-with-a-human-task)
71
+ - [Step 4: Find and Complete the Task](#step-4-find-and-complete-the-task)
72
+
73
+ ## Installation
74
+
75
+ Install the SDK using npm or yarn:
76
+
77
+ ```bash
78
+ npm install @io-orkes/conductor-javascript
17
79
  ```
80
+
18
81
  or
19
82
 
20
- ```shell
83
+ ```bash
21
84
  yarn add @io-orkes/conductor-javascript
22
85
  ```
23
86
 
24
- ## Configurations
87
+ ## Quick Start
25
88
 
26
- ### Authentication Settings (Optional)
27
- Configure the authentication settings if your Conductor server requires authentication.
28
- * keyId: Key for authentication.
29
- * keySecret: Secret for the key.
89
+ Here's a simple example to get you started:
90
+
91
+ ```typescript
92
+ import {
93
+ orkesConductorClient,
94
+ WorkflowExecutor,
95
+ TaskManager,
96
+ simpleTask,
97
+ workflow
98
+ } from "@io-orkes/conductor-javascript";
99
+
100
+ // 1. Create client
101
+ const client = await orkesConductorClient({
102
+ serverUrl: "https://play.orkes.io/api",
103
+ keyId: "your-key-id",
104
+ keySecret: "your-key-secret"
105
+ });
106
+
107
+ // 2. Create workflow executor
108
+ const executor = new WorkflowExecutor(client);
109
+
110
+ // 3. Define a simple workflow
111
+ const myWorkflow = workflow("hello_world", [
112
+ simpleTask("greet_task", "greeting_task", { message: "Hello World!" })
113
+ ]);
114
+
115
+ // 4. Register workflow
116
+ await executor.registerWorkflow(true, myWorkflow);
117
+
118
+ // 5. Start workflow execution
119
+ const executionId = await executor.startWorkflow({
120
+ name: "hello_world",
121
+ version: 1,
122
+ input: { name: "Developer" }
123
+ });
124
+
125
+ console.log(`Workflow started with ID: ${executionId}`);
126
+ ```
127
+
128
+ ## Authentication & Configuration
30
129
 
31
130
  ### Access Control Setup
32
- See [Access Control](https://orkes.io/content/docs/getting-started/concepts/access-control) for more details on role-based access control with Conductor and generating API keys for your environment.
33
131
 
34
- ### Configure API Client
132
+ The SDK supports authentication using API keys. See [Access Control](https://orkes.io/content/docs/getting-started/concepts/access-control) for more details on role-based access control with Conductor and generating API keys.
133
+
134
+ ### Configuration Options
35
135
 
36
136
  ```typescript
37
- /**
38
- * Application keys generated from the Application menu > Create Application
39
- * then edit and create Access Keys
40
- *
41
- */
42
137
  import { OrkesApiConfig, orkesConductorClient } from "@io-orkes/conductor-javascript";
43
138
 
44
139
  const config: Partial<OrkesApiConfig> = {
45
- keyId: "XXX", // optional
46
- keySecret: "XXXX", // optional
47
- refreshTokenInterval: 0, // optional (in milliseconds) defaults to 30 minutes (30 * 60 * 1000). 0 no refresh
48
- serverUrl: "https://play.orkes.io/api",
140
+ serverUrl: "https://play.orkes.io/api", // Required: server api url
141
+ keyId: "your-key-id", // Required for server with auth: authentication key
142
+ keySecret: "your-key-secret", // Required for server with auth: authentication secret
143
+ refreshTokenInterval: 0, // Optional: token refresh interval in ms (default: 30 minutes, 0 = no refresh)
144
+ maxHttp2Connections: 1 // Optional: max HTTP2 connections (default: 1)
145
+ };
146
+
147
+ const client = await orkesConductorClient(config);
148
+ ```
149
+
150
+ ### Environment Variables
151
+
152
+ You can configure client using environment variables:
153
+
154
+ ```bash
155
+ CONDUCTOR_SERVER_URL=https://play.orkes.io/api
156
+ CONDUCTOR_AUTH_KEY=your-key-id
157
+ CONDUCTOR_AUTH_SECRET=your-key-secret
158
+ CONDUCTOR_REFRESH_TOKEN_INTERVAL=0
159
+ CONDUCTOR_MAX_HTTP2_CONNECTIONS=1
160
+ ```
161
+ Environment variables are prioritized over config variables.
162
+
163
+ ### Custom Fetch Function
164
+
165
+ You can provide a custom fetch function for SDK HTTP requests:
166
+
167
+ ```typescript
168
+ const client = await orkesConductorClient(config, fetch);
169
+ ```
170
+
171
+ ## Core Concepts
172
+
173
+ ### What are Tasks?
174
+
175
+ Tasks are individual units of work in Conductor workflows. Each task performs a specific operation, such as making an HTTP call, transforming data, executing custom business logic, or waiting for human approval. Tasks can be executed automatically by Conductor's built-in workers or by custom workers you implement.
176
+
177
+ ### What are Workflows?
178
+
179
+ Workflows are the main orchestration units in Conductor. They define a sequence of tasks and their dependencies, creating automated business processes. Workflows coordinate task execution, handle failures, manage retries, and ensure your business logic flows correctly from start to finish.
180
+
181
+ ### What are Workers?
182
+
183
+ Workers are applications that poll Conductor for tasks and execute them. Conductor has built-in workers for common operations (HTTP calls, data transforms, etc.), and you can implement custom workers to execute your business-specific logic. This SDK provides tools to build and manage custom workers.
184
+
185
+ ### What is the Scheduler?
186
+ The scheduler allows you to schedule workflows to run at specific times or intervals, enabling automated workflow execution based on time-based triggers.
187
+
188
+ ## Task Types
189
+
190
+ Conductor provides various task types to build workflows. Understanding which tasks require custom workers and which are managed by Conductor is essential for effective workflow design. Tasks in Conductor are divided into two main categories based on **who executes them**:
191
+
192
+ ### System Tasks - Managed by Conductor Server
193
+
194
+ System tasks are fully managed by Conductor. No custom workers needed - just reference them in your workflow and they execute automatically.
195
+
196
+ **Available System Tasks:**
197
+ - **HTTP** - Make HTTP/REST API calls
198
+ - **Inline** - Execute JavaScript expressions
199
+ - **JSON JQ Transform** - Transform JSON data using JQ expressions
200
+ - **Kafka Publish** - Publish messages to Kafka topics
201
+ - **Event** - Publish events to eventing systems
202
+ - **Switch** - Conditional branching based on input
203
+ - **Fork-Join** - Execute tasks in parallel and wait for completion
204
+ - **Dynamic Fork** - Dynamically create parallel task executions
205
+ - **Join** - Join point for forked tasks
206
+ - **Sub-Workflow** - Execute another workflow as a task
207
+ - **Do-While** - Loop execution with conditions
208
+ - **Set Variable** - Set workflow variables
209
+ - **Wait** - Pause workflow for a specified duration
210
+ - **Terminate** - End workflow with success or failure
211
+ - **Human** - Pause workflow until a person completes an action (approval, form submission, etc.). Managed via the `HumanExecutor` API. See [Human Tasks](#human-tasks) section for details.
212
+
213
+ ### SIMPLE Tasks - Require Custom Workers
214
+
215
+ SIMPLE tasks execute **your custom business logic**. You must implement workers to handle these tasks.
216
+
217
+ **When to use:**
218
+ - Custom business logic specific to your application
219
+ - Integration with internal systems and databases
220
+ - File processing, data validation, notifications
221
+ - Any functionality not provided by system tasks
222
+
223
+ **How they work:**
224
+ 1. Define a SIMPLE task in your workflow
225
+ 2. Implement a worker that polls Conductor for this task type
226
+ 3. Worker executes your custom logic when task is assigned
227
+ 4. Worker reports results back to Conductor
228
+ 5. Workflow continues based on task result
229
+
230
+ See the [Workers](#workers) section for implementation details.
231
+
232
+ ## Workflows
233
+
234
+ Workflows are the heart of Conductor, orchestrating tasks to perform complex processes. This guide walks you through the entire lifecycle of a workflow, from creation to monitoring.
235
+
236
+ ### The WorkflowExecutor and TaskClient
237
+
238
+ - **`WorkflowExecutor`**: The primary tool for managing the workflow lifecycle (e.g., registering, starting, and stopping). For a complete method reference, see the [WorkflowExecutor API Reference](docs/api-reference/workflow-executor.md).
239
+ - **`TaskClient`**: Used for searching and retrieving details of individual tasks within a workflow execution. For a complete method reference, see the [TaskClient API Reference](docs/api-reference/task-client.md).
240
+
241
+ ### Quick Start: Creating a Workflow
242
+
243
+ #### Step 1: Define Your Workflow Structure
244
+
245
+ A workflow definition is a blueprint for your process. It outlines the workflow's properties and the sequence of tasks.
246
+
247
+ ```typescript
248
+ const workflowDef = {
249
+ name: "order_fulfillment",
250
+ version: 1,
251
+ description: "Process and fulfill customer orders",
252
+ ownerEmail: "team@example.com",
253
+ tasks: [
254
+ // Tasks will be added in the next step
255
+ ],
256
+ inputParameters: ["orderId", "customerId", "productId", "quantity"],
257
+ outputParameters: {
258
+ status: "${route_order_ref.output.status}",
259
+ fulfillmentId: "${fulfill_order_ref.output.fulfillmentId}"
260
+ },
261
+ timeoutSeconds: 3600,
262
+ timeoutPolicy: "ALERT_ONLY"
263
+ };
264
+ ```
265
+
266
+ #### Step 2: Use Task Generators to Build Your Task List
267
+
268
+ Use **Task Generators** to populate the `tasks` array. These helper functions simplify the creation of different task types.
269
+
270
+ ```typescript
271
+ import { simpleTask, httpTask, switchTask } from "@io-orkes/conductor-javascript";
272
+
273
+ const tasks = [
274
+ // Task 1: A custom task to validate the order
275
+ simpleTask(
276
+ "validate_order_ref",
277
+ "validate_order",
278
+ {
279
+ orderId: "${workflow.input.orderId}",
280
+ customerId: "${workflow.input.customerId}"
281
+ }
282
+ ),
283
+
284
+ // Task 2: An HTTP task to check inventory
285
+ httpTask(
286
+ "check_inventory_ref",
287
+ {
288
+ uri: "https://api.inventory.com/check",
289
+ method: "POST",
290
+ body: {
291
+ productId: "${workflow.input.productId}",
292
+ quantity: "${workflow.input.quantity}"
293
+ }
294
+ }
295
+ ),
296
+
297
+ // Task 3: A switch task for conditional logic
298
+ switchTask(
299
+ "route_order_ref",
300
+ "${check_inventory_ref.output.inStock}",
301
+ {
302
+ "true": [
303
+ simpleTask("fulfill_order_ref", "fulfill_order", {})
304
+ ],
305
+ "false": [
306
+ simpleTask("backorder_ref", "create_backorder", {})
307
+ ]
308
+ }
309
+ )
310
+ ];
311
+
312
+ // Add the tasks to your workflow definition
313
+ workflowDef.tasks = tasks;
314
+ ```
315
+
316
+ **Key Concepts:**
317
+ - **`taskReferenceName`**: A unique identifier for a task instance within a workflow. Used for data flow (e.g., `${check_inventory_ref.output.inStock}`).
318
+ - **Input Parameters**: Use `${workflow.input.fieldName}` to access initial workflow inputs and `${task_ref.output.fieldName}` to access outputs from previous tasks.
319
+ - **Task Generators**: Helper functions like `simpleTask`, `httpTask`, etc., that create task definitions. For a complete list, see the [Task Generators Reference](docs/api-reference/task-generators.md).
320
+
321
+ #### Step 3: Register and Start Your Workflow
322
+
323
+ With the definition complete, register it with Conductor and start an execution.
324
+
325
+ ```typescript
326
+ import { WorkflowExecutor } from "@io-orkes/conductor-javascript";
327
+
328
+ // Create WorkflowExecutor instance
329
+ const executor = new WorkflowExecutor(client);
330
+
331
+ // Register the workflow definition (overwrite if it exists)
332
+ await executor.registerWorkflow(true, workflowDef);
333
+
334
+ // Start a workflow execution
335
+ const executionId = await executor.startWorkflow({
336
+ name: "order_fulfillment",
337
+ version: 1,
338
+ input: {
339
+ orderId: "ORDER-123",
340
+ customerId: "CUST-456",
341
+ productId: "PROD-789",
342
+ quantity: 2
343
+ }
344
+ });
345
+
346
+ console.log(`Workflow started with ID: ${executionId}`);
347
+ ```
348
+
349
+ #### Step 4: Manage and Monitor Execution
350
+
351
+ Once a workflow is running, you can monitor its status, control its execution, and debug individual tasks.
352
+
353
+ ##### Check Workflow Status
354
+
355
+ Retrieve the current status and output of a running workflow.
356
+
357
+ ```typescript
358
+ const status = await executor.getWorkflowStatus(
359
+ executionId,
360
+ true, // includeOutput
361
+ true // includeVariables
362
+ );
363
+ console.log(`Workflow status is: ${status.status}`);
364
+ ```
365
+
366
+ ##### Control Workflow Execution
367
+
368
+ You can pause, resume, or terminate workflows as needed.
369
+
370
+ ```typescript
371
+ // Pause a running workflow
372
+ await executor.pause(executionId);
373
+
374
+ // Resume a paused workflow
375
+ await executor.resume(executionId);
376
+
377
+ // Terminate a workflow
378
+ await executor.terminate(executionId, "Aborted due to customer cancellation");
379
+ ```
380
+
381
+ ##### Search for Workflows
382
+
383
+ Search for workflow executions based on various criteria.
384
+
385
+ ```typescript
386
+ const searchResults = await executor.search(
387
+ 0,
388
+ 10,
389
+ "status:RUNNING AND workflowType:order_fulfillment",
390
+ "*",
391
+ "startTime:DESC"
392
+ );
393
+ ```
394
+
395
+ ##### Use TaskClient to Monitor and Debug Tasks
396
+
397
+ For a deeper look into the tasks within a workflow, use the `TaskClient`.
398
+
399
+ ```typescript
400
+ import { TaskClient } from "@io-orkes/conductor-javascript";
401
+
402
+ const taskClient = new TaskClient(client);
403
+
404
+ // Find all failed tasks for a specific workflow run
405
+ const failedTasks = await taskClient.search(
406
+ 0,
407
+ 100,
408
+ "startTime:DESC",
409
+ "*",
410
+ `status:FAILED AND workflowId:${executionId}`
411
+ );
412
+
413
+ // Get details of a specific task by its ID
414
+ const taskDetails = await taskClient.getTask(failedTasks.results[0].taskId);
415
+ ```
416
+
417
+ For a complete list of methods, see the [WorkflowExecutor API Reference](docs/api-reference/workflow-executor.md) and the [TaskClient API Reference](docs/api-reference/task-client.md).
418
+
419
+ ## Workers
420
+
421
+ Workers are background processes that execute tasks in your workflows. Think of them as specialized functions that:
422
+
423
+ 1. **Poll** the Conductor server for tasks.
424
+ 2. **Execute** your business logic when a task is assigned.
425
+ 3. **Report** the results back to the Conductor server.
426
+
427
+ **How Workers Fit In:**
428
+ ```
429
+ Workflow → Creates Tasks → Workers Poll for Tasks → Execute Logic → Return Results → Workflow Continues
430
+ ```
431
+
432
+ The `TaskManager` class in this SDK simplifies the process of creating and managing workers.
433
+
434
+ ### The TaskManager
435
+
436
+ The `TaskManager` is the primary tool for managing workers. It handles polling, task execution, and result reporting, allowing you to run multiple workers concurrently. For a complete method reference, see the [TaskManager API Reference](docs/api-reference/task-manager.md).
437
+
438
+ ### Quick Start: Building a Worker
439
+
440
+ Building a robust worker involves defining its logic, handling outcomes, and managing its execution.
441
+
442
+ #### Step 1: Define the Worker's Logic
443
+
444
+ A worker is an object that defines a `taskDefName` (which must match the task name in your workflow) and an `execute` function containing your business logic.
445
+
446
+ ```typescript
447
+ import { ConductorWorker } from "@io-orkes/conductor-javascript";
448
+
449
+ const emailWorker: ConductorWorker = {
450
+ // 1. Specify the task name
451
+ taskDefName: "send_email",
452
+
453
+ // 2. Implement the execution logic
454
+ execute: async (task) => {
455
+ const { to, subject, body } = task.inputData;
456
+
457
+ console.log(`Sending email to ${to}: ${subject}`);
458
+ await emailService.send(to, subject, body); // Your business logic
459
+
460
+ // 3. Return a result (covered in the next step)
461
+ return {
462
+ status: "COMPLETED",
463
+ outputData: { sent: true, timestamp: new Date().toISOString() }
464
+ };
465
+ }
466
+ };
467
+ ```
468
+
469
+ #### Step 2: Handle Task Outcomes and Errors
470
+
471
+ The `execute` function must return an object indicating the task's outcome.
472
+
473
+ **✅ On Success:**
474
+ Return a `COMPLETED` status and any relevant output data.
475
+
476
+ ```typescript
477
+ return {
478
+ status: "COMPLETED",
479
+ outputData: { result: "success", data: processedData }
49
480
  };
481
+ ```
482
+
483
+ **❌ On Failure:**
484
+ You can control the retry behavior. `FAILED` allows for retries, while `FAILED_WITH_TERMINAL_ERROR` stops the workflow immediately.
485
+
486
+ ```typescript
487
+ try {
488
+ // Risky operation
489
+ } catch (error) {
490
+ return {
491
+ status: "FAILED", // Allows for retries
492
+ logs: [{ log: `Error executing task: ${error.message}` }]
493
+ };
494
+ }
495
+ ```
496
+
497
+ #### Step 3: Run the Worker with TaskManager
498
+
499
+ The `TaskManager` is responsible for polling Conductor, managing task execution, and reporting back results. You can run a single worker or multiple workers with one manager.
500
+
501
+ ```typescript
502
+ import { TaskManager } from "@io-orkes/conductor-javascript";
503
+
504
+ // You can pass a single worker or an array of workers
505
+ const workers = [emailWorker, anotherWorker, ...];
506
+
507
+ // Create the TaskManager
508
+ const manager = new TaskManager(client, workers, {
509
+ options: {
510
+ concurrency: 5, // Process up to 5 tasks concurrently
511
+ pollInterval: 100, // Poll every 100ms
512
+ }
513
+ });
514
+
515
+ // Start polling for tasks
516
+ await manager.startPolling();
517
+ console.log("Worker is running!");
518
+ ```
519
+
520
+ For a complete method reference, see the [TaskManager API Reference](docs/api-reference/task-manager.md).
521
+
522
+ ### Worker Design Principles
523
+
524
+ When designing workers, it's best to follow these principles:
525
+
526
+ - **Stateless**: Workers should not rely on local state.
527
+ - **Idempotent**: The same task input should always produce the same result.
528
+ - **Single Responsibility**: Each worker should be responsible for one specific task type.
529
+
530
+ ## Scheduling
531
+
532
+ The Conductor Scheduler allows you to run workflows at specific times or intervals, defined by a CRON expression. This is useful for tasks like nightly data processing, weekly reports, or any time-based automation.
533
+
534
+ ### The SchedulerClient
535
+
536
+ The `SchedulerClient` is used to create, manage, and delete workflow schedules. For a complete method reference, see the [SchedulerClient API Reference](docs/api-reference/scheduler-client.md).
537
+
538
+ ### Quick Start: Scheduling a Workflow
539
+
540
+ Here’s how to schedule a workflow in three steps:
541
+
542
+ #### Step 1: Create a SchedulerClient
543
+
544
+ First, create an instance of the `SchedulerClient`:
545
+
546
+ ```typescript
547
+ import { SchedulerClient } from "@io-orkes/conductor-javascript";
548
+
549
+ const scheduler = new SchedulerClient(client);
550
+ ```
551
+
552
+ #### Step 2: Define the Schedule
553
+
554
+ Next, define the schedule, specifying the workflow to run and the CRON expression for its timing.
555
+
556
+ ```typescript
557
+ // Schedule a workflow to run every day at 9 AM
558
+ await scheduler.saveSchedule({
559
+ name: "daily_report_schedule",
560
+ cronExpression: "0 0 9 * * ?", // Everyday at 9am
561
+ startWorkflowRequest: {
562
+ name: "generate_daily_report",
563
+ version: 1,
564
+ input: {
565
+ reportType: "SALES",
566
+ period: "DAILY"
567
+ },
568
+ },
569
+ });
570
+ ```
571
+
572
+ **Cron Expression Format:**
573
+ - Standard cron format: `second minute hour day month dayOfWeek`
574
+ - Examples:
575
+ - `"0 0 9 * * ?"` - Every day at 9 AM
576
+ - `"0 */30 * * * ?"` - Every 30 minutes
577
+ - `"0 0 0 1 * ?"` - First day of every month at midnight
578
+ - `"0 0 12 ? * MON-FRI"` - Weekdays at noon
579
+
580
+ #### Step 3: Manage the Schedule
581
+
582
+ You can easily manage your schedules:
583
+
584
+ ```typescript
585
+ // Pause a schedule
586
+ await scheduler.pauseSchedule("daily_report_schedule");
587
+
588
+ // Resume a paused schedule
589
+ await scheduler.resumeSchedule("daily_report_schedule");
590
+
591
+ // Delete a schedule
592
+ await scheduler.deleteSchedule("daily_report_schedule");
593
+ ```
594
+
595
+ For a complete method reference, see the [SchedulerClient API Reference](docs/api-reference/scheduler-client.md).
596
+
597
+ ## Service Registry
598
+
599
+ The Service Registry in Conductor allows you to manage and discover microservices. It also provides built-in circuit breaker functionality to improve the resilience of your distributed system.
600
+
601
+ ### The ServiceRegistryClient
602
+
603
+ The `ServiceRegistryClient` is used to register, manage, and discover services. For a complete method reference, see the [ServiceRegistryClient API Reference](docs/api-reference/service-registry-client.md).
604
+
605
+ ### Quick Start: Using the Service Registry
606
+
607
+ Here’s how to get started with the `ServiceRegistryClient`:
608
+
609
+ #### Step 1: Create a ServiceRegistryClient
610
+
611
+ First, create an instance of the `ServiceRegistryClient`:
612
+
613
+ ```typescript
614
+ import { ServiceRegistryClient } from "@io-orkes/conductor-javascript";
615
+
616
+ const serviceRegistry = new ServiceRegistryClient(client);
617
+ ```
618
+
619
+ #### Step 2: Register a Service
620
+
621
+ Next, register your service with Conductor. This example registers an HTTP service with a circuit breaker configuration.
622
+
623
+ ```typescript
624
+ // Register a service with circuit breaker config
625
+ await serviceRegistry.addOrUpdateService({
626
+ name: "user-service",
627
+ type: "HTTP",
628
+ serviceURI: "https://api.example.com/users",
629
+ circuitBreakerConfig: {
630
+ failureRateThreshold: 50.0,
631
+ slidingWindowSize: 10,
632
+ minimumNumberOfCalls: 5,
633
+ waitDurationInOpenState: 60000, // 1 minute
634
+ },
635
+ });
636
+ ```
637
+
638
+ #### Step 3: Manage Services
639
+
640
+ You can easily manage your registered services:
641
+
642
+ ```typescript
643
+ // Get a list of all registered services
644
+ const services = await serviceRegistry.getRegisteredServices();
645
+
646
+ // Get details for a specific service
647
+ const service = await serviceRegistry.getService("user-service");
648
+
649
+ // Remove a service
650
+ await serviceRegistry.removeService("user-service");
651
+ ```
652
+
653
+ For a complete method reference, see the [ServiceRegistryClient API Reference](docs/api-reference/service-registry-client.md).
654
+
655
+ ## Metadata
656
+
657
+ In Conductor, "metadata" refers to the definitions of your tasks and workflows. Before you can execute a workflow, you must register its definition with Conductor. The `MetadataClient` provides the tools to manage these definitions.
658
+
659
+ ### The MetadataClient
660
+
661
+ The `MetadataClient` is used to register and manage task and workflow definitions. For a complete method reference, see the [MetadataClient API Reference](docs/api-reference/metadata-client.md).
662
+
663
+ ### Quick Start: Managing Metadata
664
+
665
+ Here’s how to manage your task and workflow definitions:
666
+
667
+ #### Step 1: Create a MetadataClient
668
+
669
+ First, create an instance of the `MetadataClient`:
670
+
671
+ ```typescript
672
+ import { MetadataClient, taskDefinition, workflowDef } from "@io-orkes/conductor-javascript";
673
+
674
+ const metadataClient = new MetadataClient(client);
675
+ ```
676
+
677
+ #### Step 2: Define and Register a Task
678
+
679
+ Create a task definition and register it. The `taskDefinition` factory provides sensible defaults for optional fields.
680
+
681
+ ```typescript
682
+ // Define a task
683
+ const taskDef = taskDefinition({
684
+ name: "my_sdk_task",
685
+ description: "A task created via the SDK",
686
+ ownerEmail: "dev@example.com",
687
+ retryCount: 3,
688
+ });
689
+
690
+ // Register the task definition
691
+ await metadataClient.registerTask(taskDef);
692
+ ```
693
+
694
+ #### Step 3: Define and Register a Workflow
695
+
696
+ Define your workflow using the task you just registered, and then register the workflow definition.
697
+
698
+ ```typescript
699
+ // Define a workflow that uses the task
700
+ const wf = {
701
+ name: "my_sdk_workflow",
702
+ version: 1,
703
+ ownerEmail: "dev@example.com",
704
+ tasks: [{
705
+ name: "my_sdk_task",
706
+ taskReferenceName: "my_sdk_task_ref",
707
+ type: "SIMPLE",
708
+ }],
709
+ inputParameters: [],
710
+ timeoutSeconds: 0,
711
+ };
712
+
713
+ // Register the workflow definition
714
+ await metadataClient.registerWorkflowDef(wf);
715
+ ```
716
+
717
+ For a complete method reference, see the [MetadataClient API Reference](docs/api-reference/metadata-client.md).
718
+
719
+ ## Human Tasks
720
+
721
+ Human tasks integrate human interaction into your automated workflows. They pause a workflow until a person provides input, such as an approval, a correction, or additional information.
722
+
723
+ Unlike other tasks, human tasks are managed through a dedicated API (`HumanExecutor`) and often involve UI forms (`TemplateClient`). Because they are a type of **system task**, you don't need to create a custom worker to handle them.
724
+
725
+ ### The HumanExecutor and TemplateClient
726
+
727
+ - **`HumanExecutor`**: Manages the lifecycle of human tasks—searching, claiming, and completing them. For a complete method reference, see the [HumanExecutor API Reference](docs/api-reference/human-executor.md).
728
+ - **`TemplateClient`**: Manages the UI forms and templates that are presented to users. For a complete method reference, see the [TemplateClient API Reference](docs/api-reference/template-client.md).
729
+
730
+ ### Quick Start: Creating and Managing a Human Task
731
+
732
+ This guide walks through creating a simple approval workflow.
733
+
734
+ #### Step 1: Create API Clients
735
+
736
+ You'll need a `TemplateClient` to manage UI forms and a `HumanExecutor` to interact with the tasks themselves.
737
+
738
+ ```typescript
739
+ import { HumanExecutor, TemplateClient } from "@io-orkes/conductor-javascript";
740
+
741
+ const templateClient = new TemplateClient(client);
742
+ const humanExecutor = new HumanExecutor(client);
743
+ ```
744
+
745
+ #### Step 2: Register a Form Template
746
+
747
+ Define and register a form that will be presented to the user.
748
+
749
+ ```typescript
750
+ const formTemplate = {
751
+ name: "simple_approval_form",
752
+ version: 1,
753
+ description: "A simple form for approvals",
754
+ formTemplate: {
755
+ name: "Approval Form",
756
+ fields: [{
757
+ name: "approved",
758
+ type: "boolean",
759
+ required: true,
760
+ label: "Approve Request",
761
+ }],
762
+ },
763
+ };
764
+
765
+ await templateClient.registerTemplate(formTemplate);
766
+ ```
767
+
768
+ #### Step 3: Create a Workflow with a Human Task
769
+
770
+ Now, define a workflow that uses the `humanTask` generator. The `taskDefinition` for the human task should specify the template to use.
771
+
772
+ ```typescript
773
+ import { humanTask } from "@io-orkes/conductor-javascript";
774
+
775
+ // Define the human task
776
+ const approvalTask = humanTask(
777
+ "human_approval_ref",
778
+ "human_approval_task",
779
+ { template: "simple_approval_form" }
780
+ );
781
+
782
+ // Define the workflow
783
+ const approvalWorkflow = {
784
+ name: "human_approval_workflow",
785
+ version: 1,
786
+ tasks: [approvalTask],
787
+ inputParameters: [],
788
+ ownerEmail: "dev@example.com",
789
+ };
790
+
791
+ // Register and start the workflow
792
+ await executor.registerWorkflow(true, approvalWorkflow);
793
+ const executionId = await executor.startWorkflow({
794
+ name: "human_approval_workflow",
795
+ version: 1,
796
+ });
797
+ ```
798
+
799
+ #### Step 4: Find and Complete the Task
800
+
801
+ In a real application, your backend or UI would search for pending tasks and present them to the user.
802
+
803
+ ```typescript
804
+ // Search for pending tasks for a user
805
+ const pendingTasks = await humanExecutor.search({
806
+ states: ["PENDING"],
807
+ // assignees: [{ userType: "EXTERNAL_USER", user: "user@example.com" }],
808
+ });
809
+
810
+ if (pendingTasks.results.length > 0) {
811
+ const taskId = pendingTasks.results[0].taskId;
812
+
813
+ // Claim the task
814
+ await humanExecutor.claimTaskAsExternalUser(taskId, "user@example.com");
50
815
 
51
- orkesConductorClient(config).then(client => ..... );
816
+ // Complete the task with output
817
+ await humanExecutor.completeTask(taskId, {
818
+ output: {
819
+ approved: true,
820
+ comments: "Looks good, approved."
821
+ }
822
+ });
52
823
 
824
+ console.log(`Task ${taskId} completed.`);
825
+ }
53
826
  ```
54
827
 
55
- ### Next: [Create and run task workers](workers_sdk.md)
828
+ For a complete list of methods, see the [HumanExecutor API Reference](docs/api-reference/human-executor.md) and the [TemplateClient API Reference](docs/api-reference/template-client.md).