diff --git a/.env.example b/.env.example index 1450e51f..05712548 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,6 @@ CONDUCTOR_SERVER_URL="" + CONDUCTOR_AUTH_KEY="" -CONDUCTOR_AUTH_SECRET="" \ No newline at end of file +CONDUCTOR_AUTH_SECRET="" + +CONDUCTOR_MAX_HTTP2_CONNECTIONS= \ No newline at end of file diff --git a/DECISIONS.md b/DECISIONS.md index b1cf2f89..35b6eb72 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -15,18 +15,6 @@ I would suggest we maintain CJS compat for now, in the hope that there's either Because it's relatively simple to support interop between ESM and CJS, and the wide footprint. - -### Using `node-fetch` - -who: @nicktomlin - -I initially explored [`undici`](https://github.com/nodejs/undici) as a way of using the built-in `fetch` support in node. - -Unfortunately, at the time of writing there's no clean way to handle `tls` options. Additionally, `fetch` is experimental for node 16.x which results in warnings. - -At some point in the future, it would be nice to migrate over once undici's `fetch` implementation is a little more feature rich and things have stabalized. - - ### Using `jest` for testing `jest` can be a little magical, but it's relatively fast (with 28.x especially), ergonomic, and provides a simple maintenance story over a BYO setup. @@ -38,3 +26,15 @@ I considered `mocha` and `ava` (which i've also used and like) but `jest` struck who: @nicktomlin Typescript publication can be a wacky process and `tsup` simplifies a lot of this. + +### Using `undici` to make http2 requests (if possible) + +who: @dmitryborisov-sm + +Since Node.js uses Undici for its built-in fetch functionality, Undici supports HTTP/2 and meets all our requirements. If Undici fails to initialize, the SDK will fall back to the default fetch: HTTP/1.1 in Node 18 and HTTP/2 in browsers. It's also possible to provide a custom fetch function when creating the SDK, so in theory, the SDK could work on older Node versions using libraries like node-fetch. + +### OpenAPI generated code should not be modified directly + +who: @dmitryborisov-sm + +The SDK should follow a layered architecture, with all modifications made in the top layers. This approach enables easy updates to autogenerated code and ensures alignment with API changes, minimizing both effort and risk. diff --git a/README.md b/README.md index 8f7e31f0..8b97f250 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,828 @@ -# Conductor OSS Javascript/Typescript SDK +# Conductor OSS JavaScript/TypeScript SDK -The `conductor-javascript` repository provides the client SDKs to build task workers in javascript/typescript. +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. -Building the task workers in javascript mainly consists of the following steps: +[Conductor](https://www.conductor-oss.org/) is the leading open-source orchestration platform allowing developers to build highly scalable distributed applications. -1. Setup conductor-javascript package -2. [Create and run task workers](workers_sdk.md) -3. [Create workflows using code](workflow_sdk.md) - -### Setup Conductor Javascript Package +Check out the [official documentation for Conductor](https://orkes.io/content). -* Get the package from npm +## ⭐ Conductor OSS -```shell -npm i @io-orkes/conductor-javascript +Show support for the Conductor OSS. Please help spread the awareness by starring Conductor repo. + +[![GitHub stars](https://img.shields.io/github/stars/conductor-oss/conductor.svg?style=social&label=Star&maxAge=)](https://GitHub.com/conductor-oss/conductor/) + +## Table of Contents + +- [Installation](#installation) +- [Quick Start](#quick-start) +- [Authentication & Configuration](#authentication--configuration) + - [Access Control Setup](#access-control-setup) + - [Configuration Options](#configuration-options) + - [Environment Variables](#environment-variables) + - [Custom Fetch Function](#custom-fetch-function) +- [Core Concepts](#core-concepts) + - [What are Tasks?](#what-are-tasks) + - [What are Workflows?](#what-are-workflows) + - [What are Workers?](#what-are-workers) + - [What is the Scheduler?](#what-is-the-scheduler) +- [Task Types](#task-types) + - [System Tasks - Managed by Conductor Server](#system-tasks---managed-by-conductor-server) + - [SIMPLE Tasks - Require Custom Workers](#simple-tasks---require-custom-workers) +- [Workflows](#workflows) + - [The WorkflowExecutor and TaskClient](#the-workflowexecutor-and-taskclient) + - [Quick Start: Creating a Workflow](#quick-start-creating-a-workflow) + - [Step 1: Define Your Workflow Structure](#step-1-define-your-workflow-structure) + - [Step 2: Use Task Generators to Build Your Task List](#step-2-use-task-generators-to-build-your-task-list) + - [Step 3: Register and Start Your Workflow](#step-3-register-and-start-your-workflow) + - [Step 4: Manage and Monitor Execution](#step-4-manage-and-monitor-execution) + - [Use TaskClient to Monitor and Debug Tasks](#use-taskclient-to-monitor-and-debug-tasks) +- [Workers](#workers) + - [The TaskManager](#the-taskmanager) + - [Quick Start: Building a Worker](#quick-start-building-a-worker) + - [Step 1: Define the Worker's Logic](#step-1-define-the-workers-logic) + - [Step 2: Handle Task Outcomes and Errors](#step-2-handle-task-outcomes-and-errors) + - [Step 3: Run the Worker with TaskManager](#step-3-run-the-worker-with-taskmanager) + - [Worker Design Principles](#worker-design-principles) +- [Scheduling](#scheduling) + - [The SchedulerClient](#the-schedulerclient) + - [Quick Start: Scheduling a Workflow](#quick-start-scheduling-a-workflow) + - [Step 1: Create a SchedulerClient](#step-1-create-a-schedulerclient) + - [Step 2: Define the Schedule](#step-2-define-the-schedule) + - [Step 3: Manage the Schedule](#step-3-manage-the-schedule) +- [Service Registry](#service-registry) + - [The ServiceRegistryClient](#the-serviceregistryclient) + - [Quick Start: Using the Service Registry](#quick-start-using-the-service-registry) + - [Step 1: Create a ServiceRegistryClient](#step-1-create-a-serviceregistryclient) + - [Step 2: Register a Service](#step-2-register-a-service) + - [Step 3: Manage Services](#step-3-manage-services) +- [Metadata](#metadata) + - [The MetadataClient](#the-metadataclient) + - [Quick Start: Managing Metadata](#quick-start-managing-metadata) + - [Step 1: Create a MetadataClient](#step-1-create-a-metadataclient) + - [Step 2: Define and Register a Task](#step-2-define-and-register-a-task) + - [Step 3: Define and Register a Workflow](#step-3-define-and-register-a-workflow) +- [Human Tasks](#human-tasks) + - [The HumanExecutor and TemplateClient](#the-humanexecutor-and-templateclient) + - [Quick Start: Creating and Managing a Human Task](#quick-start-creating-and-managing-a-human-task) + - [Step 1: Create API Clients](#step-1-create-api-clients) + - [Step 2: Register a Form Template](#step-2-register-a-form-template) + - [Step 3: Create a Workflow with a Human Task](#step-3-create-a-workflow-with-a-human-task) + - [Step 4: Find and Complete the Task](#step-4-find-and-complete-the-task) + +## Installation + +Install the SDK using npm or yarn: + +```bash +npm install @io-orkes/conductor-javascript ``` + or -```shell +```bash yarn add @io-orkes/conductor-javascript ``` -## Configurations +## Quick Start -### Authentication Settings (Optional) -Configure the authentication settings if your Conductor server requires authentication. -* keyId: Key for authentication. -* keySecret: Secret for the key. +Here's a simple example to get you started: + +```typescript +import { + orkesConductorClient, + WorkflowExecutor, + TaskManager, + simpleTask, + workflow +} from "@io-orkes/conductor-javascript"; + +// 1. Create client +const client = await orkesConductorClient({ + serverUrl: "https://play.orkes.io/api", + keyId: "your-key-id", + keySecret: "your-key-secret" +}); + +// 2. Create workflow executor +const executor = new WorkflowExecutor(client); + +// 3. Define a simple workflow +const myWorkflow = workflow("hello_world", [ + simpleTask("greet_task", "greeting_task", { message: "Hello World!" }) +]); + +// 4. Register workflow +await executor.registerWorkflow(true, myWorkflow); + +// 5. Start workflow execution +const executionId = await executor.startWorkflow({ + name: "hello_world", + version: 1, + input: { name: "Developer" } +}); + +console.log(`Workflow started with ID: ${executionId}`); +``` + +## Authentication & Configuration ### Access Control Setup -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. -### Configure API Client +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. + +### Configuration Options ```typescript -/** - * Application keys generated from the Application menu > Create Application - * then edit and create Access Keys - * - */ import { OrkesApiConfig, orkesConductorClient } from "@io-orkes/conductor-javascript"; const config: Partial = { - keyId: "XXX", // optional - keySecret: "XXXX", // optional - refreshTokenInterval: 0, // optional (in milliseconds) | defaults to 30 minutes | 0 = no refresh - serverUrl: "https://play.orkes.io/api", + serverUrl: "https://play.orkes.io/api", // Required: server api url + keyId: "your-key-id", // Required for server with auth: authentication key + keySecret: "your-key-secret", // Required for server with auth: authentication secret + refreshTokenInterval: 0, // Optional: token refresh interval in ms (default: 30 minutes, 0 = no refresh) + maxHttp2Connections: 1 // Optional: max HTTP2 connections (default: 1) +}; + +const client = await orkesConductorClient(config); +``` + +### Environment Variables + +You can configure client using environment variables: + +```bash +CONDUCTOR_SERVER_URL=https://play.orkes.io/api +CONDUCTOR_AUTH_KEY=your-key-id +CONDUCTOR_AUTH_SECRET=your-key-secret +CONDUCTOR_REFRESH_TOKEN_INTERVAL=0 +CONDUCTOR_MAX_HTTP2_CONNECTIONS=1 +``` +Environment variables are prioritized over config variables. + +### Custom Fetch Function + +You can provide a custom fetch function for SDK HTTP requests: + +```typescript +const client = await orkesConductorClient(config, fetch); +``` + +## Core Concepts + +### What are Tasks? + +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. + +### What are Workflows? + +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. + +### What are Workers? + +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. + +### What is the Scheduler? +The scheduler allows you to schedule workflows to run at specific times or intervals, enabling automated workflow execution based on time-based triggers. + +## Task Types + +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**: + +### System Tasks - Managed by Conductor Server + +System tasks are fully managed by Conductor. No custom workers needed - just reference them in your workflow and they execute automatically. + +**Available System Tasks:** +- **HTTP** - Make HTTP/REST API calls +- **Inline** - Execute JavaScript expressions +- **JSON JQ Transform** - Transform JSON data using JQ expressions +- **Kafka Publish** - Publish messages to Kafka topics +- **Event** - Publish events to eventing systems +- **Switch** - Conditional branching based on input +- **Fork-Join** - Execute tasks in parallel and wait for completion +- **Dynamic Fork** - Dynamically create parallel task executions +- **Join** - Join point for forked tasks +- **Sub-Workflow** - Execute another workflow as a task +- **Do-While** - Loop execution with conditions +- **Set Variable** - Set workflow variables +- **Wait** - Pause workflow for a specified duration +- **Terminate** - End workflow with success or failure +- **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. + +### SIMPLE Tasks - Require Custom Workers + +SIMPLE tasks execute **your custom business logic**. You must implement workers to handle these tasks. + +**When to use:** +- Custom business logic specific to your application +- Integration with internal systems and databases +- File processing, data validation, notifications +- Any functionality not provided by system tasks + +**How they work:** +1. Define a SIMPLE task in your workflow +2. Implement a worker that polls Conductor for this task type +3. Worker executes your custom logic when task is assigned +4. Worker reports results back to Conductor +5. Workflow continues based on task result + +See the [Workers](#workers) section for implementation details. + +## Workflows + +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. + +### The WorkflowExecutor and TaskClient + +- **`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). +- **`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). + +### Quick Start: Creating a Workflow + +#### Step 1: Define Your Workflow Structure + +A workflow definition is a blueprint for your process. It outlines the workflow's properties and the sequence of tasks. + +```typescript +const workflowDef = { + name: "order_fulfillment", + version: 1, + description: "Process and fulfill customer orders", + ownerEmail: "team@example.com", + tasks: [ + // Tasks will be added in the next step + ], + inputParameters: ["orderId", "customerId", "productId", "quantity"], + outputParameters: { + status: "${route_order_ref.output.status}", + fulfillmentId: "${fulfill_order_ref.output.fulfillmentId}" + }, + timeoutSeconds: 3600, + timeoutPolicy: "ALERT_ONLY" +}; +``` + +#### Step 2: Use Task Generators to Build Your Task List + +Use **Task Generators** to populate the `tasks` array. These helper functions simplify the creation of different task types. + +```typescript +import { simpleTask, httpTask, switchTask } from "@io-orkes/conductor-javascript"; + +const tasks = [ + // Task 1: A custom task to validate the order + simpleTask( + "validate_order_ref", + "validate_order", + { + orderId: "${workflow.input.orderId}", + customerId: "${workflow.input.customerId}" + } + ), + + // Task 2: An HTTP task to check inventory + httpTask( + "check_inventory_ref", + { + uri: "https://api.inventory.com/check", + method: "POST", + body: { + productId: "${workflow.input.productId}", + quantity: "${workflow.input.quantity}" + } + } + ), + + // Task 3: A switch task for conditional logic + switchTask( + "route_order_ref", + "${check_inventory_ref.output.inStock}", + { + "true": [ + simpleTask("fulfill_order_ref", "fulfill_order", {}) + ], + "false": [ + simpleTask("backorder_ref", "create_backorder", {}) + ] + } + ) +]; + +// Add the tasks to your workflow definition +workflowDef.tasks = tasks; +``` + +**Key Concepts:** +- **`taskReferenceName`**: A unique identifier for a task instance within a workflow. Used for data flow (e.g., `${check_inventory_ref.output.inStock}`). +- **Input Parameters**: Use `${workflow.input.fieldName}` to access initial workflow inputs and `${task_ref.output.fieldName}` to access outputs from previous tasks. +- **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). + +#### Step 3: Register and Start Your Workflow + +With the definition complete, register it with Conductor and start an execution. + +```typescript +import { WorkflowExecutor } from "@io-orkes/conductor-javascript"; + +// Create WorkflowExecutor instance +const executor = new WorkflowExecutor(client); + +// Register the workflow definition (overwrite if it exists) +await executor.registerWorkflow(true, workflowDef); + +// Start a workflow execution +const executionId = await executor.startWorkflow({ + name: "order_fulfillment", + version: 1, + input: { + orderId: "ORDER-123", + customerId: "CUST-456", + productId: "PROD-789", + quantity: 2 + } +}); + +console.log(`Workflow started with ID: ${executionId}`); +``` + +#### Step 4: Manage and Monitor Execution + +Once a workflow is running, you can monitor its status, control its execution, and debug individual tasks. + +##### Check Workflow Status + +Retrieve the current status and output of a running workflow. + +```typescript +const status = await executor.getWorkflowStatus( + executionId, + true, // includeOutput + true // includeVariables +); +console.log(`Workflow status is: ${status.status}`); +``` + +##### Control Workflow Execution + +You can pause, resume, or terminate workflows as needed. + +```typescript +// Pause a running workflow +await executor.pause(executionId); + +// Resume a paused workflow +await executor.resume(executionId); + +// Terminate a workflow +await executor.terminate(executionId, "Aborted due to customer cancellation"); +``` + +##### Search for Workflows + +Search for workflow executions based on various criteria. + +```typescript +const searchResults = await executor.search( + 0, + 10, + "status:RUNNING AND workflowType:order_fulfillment", + "*", + "startTime:DESC" +); +``` + +##### Use TaskClient to Monitor and Debug Tasks + +For a deeper look into the tasks within a workflow, use the `TaskClient`. + +```typescript +import { TaskClient } from "@io-orkes/conductor-javascript"; + +const taskClient = new TaskClient(client); + +// Find all failed tasks for a specific workflow run +const failedTasks = await taskClient.search( + 0, + 100, + "startTime:DESC", + "*", + `status:FAILED AND workflowId:${executionId}` +); + +// Get details of a specific task by its ID +const taskDetails = await taskClient.getTask(failedTasks.results[0].taskId); +``` + +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). + +## Workers + +Workers are background processes that execute tasks in your workflows. Think of them as specialized functions that: + +1. **Poll** the Conductor server for tasks. +2. **Execute** your business logic when a task is assigned. +3. **Report** the results back to the Conductor server. + +**How Workers Fit In:** +``` +Workflow → Creates Tasks → Workers Poll for Tasks → Execute Logic → Return Results → Workflow Continues +``` + +The `TaskManager` class in this SDK simplifies the process of creating and managing workers. + +### The TaskManager + +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). + +### Quick Start: Building a Worker + +Building a robust worker involves defining its logic, handling outcomes, and managing its execution. + +#### Step 1: Define the Worker's Logic + +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. + +```typescript +import { ConductorWorker } from "@io-orkes/conductor-javascript"; + +const emailWorker: ConductorWorker = { + // 1. Specify the task name + taskDefName: "send_email", + + // 2. Implement the execution logic + execute: async (task) => { + const { to, subject, body } = task.inputData; + + console.log(`Sending email to ${to}: ${subject}`); + await emailService.send(to, subject, body); // Your business logic + + // 3. Return a result (covered in the next step) + return { + status: "COMPLETED", + outputData: { sent: true, timestamp: new Date().toISOString() } + }; + } +}; +``` + +#### Step 2: Handle Task Outcomes and Errors + +The `execute` function must return an object indicating the task's outcome. + +**✅ On Success:** +Return a `COMPLETED` status and any relevant output data. + +```typescript +return { + status: "COMPLETED", + outputData: { result: "success", data: processedData } }; +``` + +**❌ On Failure:** +You can control the retry behavior. `FAILED` allows for retries, while `FAILED_WITH_TERMINAL_ERROR` stops the workflow immediately. + +```typescript +try { + // Risky operation +} catch (error) { + return { + status: "FAILED", // Allows for retries + logs: [{ log: `Error executing task: ${error.message}` }] + }; +} +``` + +#### Step 3: Run the Worker with TaskManager + +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. + +```typescript +import { TaskManager } from "@io-orkes/conductor-javascript"; + +// You can pass a single worker or an array of workers +const workers = [emailWorker, anotherWorker, ...]; + +// Create the TaskManager +const manager = new TaskManager(client, workers, { + options: { + concurrency: 5, // Process up to 5 tasks concurrently + pollInterval: 100, // Poll every 100ms + } +}); + +// Start polling for tasks +await manager.startPolling(); +console.log("Worker is running!"); +``` + +For a complete method reference, see the [TaskManager API Reference](docs/api-reference/task-manager.md). + +### Worker Design Principles + +When designing workers, it's best to follow these principles: + +- **Stateless**: Workers should not rely on local state. +- **Idempotent**: The same task input should always produce the same result. +- **Single Responsibility**: Each worker should be responsible for one specific task type. + +## Scheduling + +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. + +### The SchedulerClient + +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). + +### Quick Start: Scheduling a Workflow + +Here’s how to schedule a workflow in three steps: + +#### Step 1: Create a SchedulerClient + +First, create an instance of the `SchedulerClient`: + +```typescript +import { SchedulerClient } from "@io-orkes/conductor-javascript"; + +const scheduler = new SchedulerClient(client); +``` + +#### Step 2: Define the Schedule + +Next, define the schedule, specifying the workflow to run and the CRON expression for its timing. + +```typescript +// Schedule a workflow to run every day at 9 AM +await scheduler.saveSchedule({ + name: "daily_report_schedule", + cronExpression: "0 0 9 * * ?", // Everyday at 9am + startWorkflowRequest: { + name: "generate_daily_report", + version: 1, + input: { + reportType: "SALES", + period: "DAILY" + }, + }, +}); +``` + +**Cron Expression Format:** +- Standard cron format: `second minute hour day month dayOfWeek` +- Examples: + - `"0 0 9 * * ?"` - Every day at 9 AM + - `"0 */30 * * * ?"` - Every 30 minutes + - `"0 0 0 1 * ?"` - First day of every month at midnight + - `"0 0 12 ? * MON-FRI"` - Weekdays at noon + +#### Step 3: Manage the Schedule + +You can easily manage your schedules: + +```typescript +// Pause a schedule +await scheduler.pauseSchedule("daily_report_schedule"); + +// Resume a paused schedule +await scheduler.resumeSchedule("daily_report_schedule"); + +// Delete a schedule +await scheduler.deleteSchedule("daily_report_schedule"); +``` + +For a complete method reference, see the [SchedulerClient API Reference](docs/api-reference/scheduler-client.md). + +## Service Registry + +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. + +### The ServiceRegistryClient + +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). + +### Quick Start: Using the Service Registry + +Here’s how to get started with the `ServiceRegistryClient`: + +#### Step 1: Create a ServiceRegistryClient + +First, create an instance of the `ServiceRegistryClient`: + +```typescript +import { ServiceRegistryClient } from "@io-orkes/conductor-javascript"; + +const serviceRegistry = new ServiceRegistryClient(client); +``` + +#### Step 2: Register a Service + +Next, register your service with Conductor. This example registers an HTTP service with a circuit breaker configuration. + +```typescript +// Register a service with circuit breaker config +await serviceRegistry.addOrUpdateService({ + name: "user-service", + type: "HTTP", + serviceURI: "https://api.example.com/users", + circuitBreakerConfig: { + failureRateThreshold: 50.0, + slidingWindowSize: 10, + minimumNumberOfCalls: 5, + waitDurationInOpenState: 60000, // 1 minute + }, +}); +``` + +#### Step 3: Manage Services + +You can easily manage your registered services: + +```typescript +// Get a list of all registered services +const services = await serviceRegistry.getRegisteredServices(); + +// Get details for a specific service +const service = await serviceRegistry.getService("user-service"); + +// Remove a service +await serviceRegistry.removeService("user-service"); +``` + +For a complete method reference, see the [ServiceRegistryClient API Reference](docs/api-reference/service-registry-client.md). + +## Metadata + +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. + +### The MetadataClient + +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). + +### Quick Start: Managing Metadata + +Here’s how to manage your task and workflow definitions: + +#### Step 1: Create a MetadataClient + +First, create an instance of the `MetadataClient`: + +```typescript +import { MetadataClient, taskDefinition, workflowDef } from "@io-orkes/conductor-javascript"; + +const metadataClient = new MetadataClient(client); +``` + +#### Step 2: Define and Register a Task + +Create a task definition and register it. The `taskDefinition` factory provides sensible defaults for optional fields. + +```typescript +// Define a task +const taskDef = taskDefinition({ + name: "my_sdk_task", + description: "A task created via the SDK", + ownerEmail: "dev@example.com", + retryCount: 3, +}); + +// Register the task definition +await metadataClient.registerTask(taskDef); +``` + +#### Step 3: Define and Register a Workflow + +Define your workflow using the task you just registered, and then register the workflow definition. + +```typescript +// Define a workflow that uses the task +const wf = { + name: "my_sdk_workflow", + version: 1, + ownerEmail: "dev@example.com", + tasks: [{ + name: "my_sdk_task", + taskReferenceName: "my_sdk_task_ref", + type: "SIMPLE", + }], + inputParameters: [], + timeoutSeconds: 0, +}; + +// Register the workflow definition +await metadataClient.registerWorkflowDef(wf); +``` + +For a complete method reference, see the [MetadataClient API Reference](docs/api-reference/metadata-client.md). + +## Human Tasks + +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. + +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. + +### The HumanExecutor and TemplateClient + +- **`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). +- **`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). + +### Quick Start: Creating and Managing a Human Task + +This guide walks through creating a simple approval workflow. + +#### Step 1: Create API Clients + +You'll need a `TemplateClient` to manage UI forms and a `HumanExecutor` to interact with the tasks themselves. + +```typescript +import { HumanExecutor, TemplateClient } from "@io-orkes/conductor-javascript"; + +const templateClient = new TemplateClient(client); +const humanExecutor = new HumanExecutor(client); +``` + +#### Step 2: Register a Form Template + +Define and register a form that will be presented to the user. + +```typescript +const formTemplate = { + name: "simple_approval_form", + version: 1, + description: "A simple form for approvals", + formTemplate: { + name: "Approval Form", + fields: [{ + name: "approved", + type: "boolean", + required: true, + label: "Approve Request", + }], + }, +}; + +await templateClient.registerTemplate(formTemplate); +``` + +#### Step 3: Create a Workflow with a Human Task + +Now, define a workflow that uses the `humanTask` generator. The `taskDefinition` for the human task should specify the template to use. + +```typescript +import { humanTask } from "@io-orkes/conductor-javascript"; + +// Define the human task +const approvalTask = humanTask( + "human_approval_ref", + "human_approval_task", + { template: "simple_approval_form" } +); + +// Define the workflow +const approvalWorkflow = { + name: "human_approval_workflow", + version: 1, + tasks: [approvalTask], + inputParameters: [], + ownerEmail: "dev@example.com", +}; + +// Register and start the workflow +await executor.registerWorkflow(true, approvalWorkflow); +const executionId = await executor.startWorkflow({ + name: "human_approval_workflow", + version: 1, +}); +``` + +#### Step 4: Find and Complete the Task + +In a real application, your backend or UI would search for pending tasks and present them to the user. + +```typescript +// Search for pending tasks for a user +const pendingTasks = await humanExecutor.search({ + states: ["PENDING"], + // assignees: [{ userType: "EXTERNAL_USER", user: "user@example.com" }], +}); + +if (pendingTasks.results.length > 0) { + const taskId = pendingTasks.results[0].taskId; + + // Claim the task + await humanExecutor.claimTaskAsExternalUser(taskId, "user@example.com"); -orkesConductorClient(config).then(client => ..... ); + // Complete the task with output + await humanExecutor.completeTask(taskId, { + output: { + approved: true, + comments: "Looks good, approved." + } + }); + console.log(`Task ${taskId} completed.`); +} ``` -### Next: [Create and run task workers](workers_sdk.md) +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). diff --git a/docs/api-reference/human-executor.md b/docs/api-reference/human-executor.md new file mode 100644 index 00000000..0689cd8c --- /dev/null +++ b/docs/api-reference/human-executor.md @@ -0,0 +1,272 @@ +# HumanExecutor API Reference + +The `HumanExecutor` class provides comprehensive human task management. + +## Constructor + +### `new HumanExecutor(client: ConductorClient)` + +Creates a new `HumanExecutor`. + +**Parameters:** + +- `client` (`ConductorClient`): An instance of `ConductorClient`. + +--- + +## Methods + +### `getTasksByFilter(state: "PENDING" | "ASSIGNED" | "IN_PROGRESS" | "COMPLETED" | "TIMED_OUT", assignee?: string, assigneeType?: "EXTERNAL_USER" | "EXTERNAL_GROUP" | "CONDUCTOR_USER" | "CONDUCTOR_GROUP", claimedBy?: string, taskName?: string, taskInputQuery?: string, taskOutputQuery?: string): Promise` + +Gets human tasks by a set of filter parameters. + +**Parameters:** + +- `state` (`"PENDING" | "ASSIGNED" | "IN_PROGRESS" | "COMPLETED" | "TIMED_OUT"`): The state of the tasks to filter by. +- `assignee` (`string`, optional): The assignee of the tasks. +- `assigneeType` (`"EXTERNAL_USER" | "EXTERNAL_GROUP" | "CONDUCTOR_USER" | "CONDUCTOR_GROUP"`, optional): The type of the assignee. +- `claimedBy` (`string`, optional): The user who has claimed the tasks. +- `taskName` (`string`, optional): The name of the tasks. +- `taskInputQuery` (`string`, optional): A query to filter tasks by their input data. +- `taskOutputQuery` (`string`, optional): A query to filter tasks by their output data. + +**Returns:** + +- `Promise`: An array of human task entries. + +--- + +### `search(searchParams: Partial): Promise` + +Searches for human tasks. + +**Parameters:** + +- `searchParams` (`Partial`): The search parameters. + +**Returns:** + +- `Promise`: An array of human task entries. + +--- + +### `pollSearch(searchParams: Partial, options: PollIntervalOptions = { pollInterval: 100, maxPollTimes: 20 }): Promise` + +Polls for human tasks until a result is returned. + +**Parameters:** + +- `searchParams` (`Partial`): The search parameters. +- `options` (`PollIntervalOptions`, optional): The polling options. + +**Returns:** + +- `Promise`: An array of human task entries. + +--- + +### `getTaskById(taskId: string): Promise` + +Gets a human task by its ID. + +**Parameters:** + +- `taskId` (`string`): The ID of the task. + +**Returns:** + +- `Promise`: The human task entry. + +--- + +### `claimTaskAsExternalUser(taskId: string, assignee: string, options?: Record): Promise` + +Claims a task as an external user. + +**Parameters:** + +- `taskId` (`string`): The ID of the task. +- `assignee` (`string`): The external user to assign the task to. +- `options` (`Record`, optional): Additional options. + +**Returns:** + +- `Promise`: The claimed human task entry. + +--- + +### `claimTaskAsConductorUser(taskId: string, options?: Record): Promise` + +Claims a task as a Conductor user. + +**Parameters:** + +- `taskId` (`string`): The ID of the task. +- `options` (`Record`, optional): Additional options. + +**Returns:** + +- `Promise`: The claimed human task entry. + +--- + +### `releaseTask(taskId: string): Promise` + +Releases a task. + +**Parameters:** + +- `taskId` (`string`): The ID of the task. + +**Returns:** + +- `Promise` + +--- + +### `getTemplateByNameVersion(name: string, version: number): Promise` + +Gets a human task template by name and version. + +**Parameters:** + +- `name` (`string`): The name of the template. +- `version` (`number`): The version of the template. + +**Returns:** + +- `Promise`: The human task template. + +--- + +### `getTemplateById(templateNameVersionOne: string): Promise` + +Gets a human task template by ID (name with version 1). + +**Parameters:** + +- `templateNameVersionOne` (`string`): The name of the template. + +**Returns:** + +- `Promise`: The human task template. + +--- + +### `updateTaskOutput(taskId: string, requestBody: Record>): Promise` + +Updates the output of a task. + +**Parameters:** + +- `taskId` (`string`): The ID of the task. +- `requestBody` (`Record>`): The new output data. + +**Returns:** + +- `Promise` + +--- + +### `completeTask(taskId: string, requestBody: Record> = {}): Promise` + +Completes a task. + +**Parameters:** + +- `taskId` (`string`): The ID of the task. +- `requestBody` (`Record>`, optional): The output data. + +**Returns:** + +- `Promise` + +--- + +## Type Definitions + +### `HumanTaskEntry` +| Property | Type | Description | +| --- | --- | --- | +| `assignee` | `HumanTaskUser` | The user assigned to the task. | +| `claimant`| `HumanTaskUser` | The user who has claimed the task. | +| `createdBy` | `string` | The user who created the task. | +| `createdOn` | `number` | The time the task was created. | +| `definitionName`| `string` | The name of the task definition. | +| `displayName` | `string` | The display name of the task. | +| `humanTaskDef`| `HumanTaskDefinition` | The task definition. | +| `input` | `Record` | The input data for the task. | +| `output`| `Record` | The output data for the task. | +| `state` | `'PENDING' \| 'ASSIGNED' \| 'IN_PROGRESS' \| 'COMPLETED' \| 'TIMED_OUT' \| 'DELETED'` | The state of the task. | +| `taskId`| `string` | The ID of the task. | +| `taskRefName` | `string` | The reference name of the task. | +| `updatedBy` | `string` | The user who last updated the task. | +| `updatedOn` | `number` | The time the task was last updated. | +| `workflowId`| `string` | The ID of the workflow instance. | +| `workflowName`| `string` | The name of the workflow. | + +### `HumanTaskUser` +| Property | Type | Description | +| --- | --- | --- | +| `user` | `string` | The user or group ID. | +| `userType`| `'EXTERNAL_USER' \| 'EXTERNAL_GROUP' \| 'CONDUCTOR_USER' \| 'CONDUCTOR_GROUP'` | The type of the user. | + +### `HumanTaskDefinition` +| Property | Type | Description | +| --- | --- | --- | +| `assignmentCompletionStrategy` | `'LEAVE_OPEN' \| 'TERMINATE'` | The strategy for completing the assignment. | +| `assignments` | `HumanTaskAssignment[]` | A list of assignments for the task. | +| `taskTriggers` | `HumanTaskTrigger[]` | A list of triggers for the task. | +| `userFormTemplate` | `UserFormTemplate` | The user form template for the task. | + +### `HumanTaskAssignment` +| Property | Type | Description | +| --- | --- | --- | +| `assignee` | `HumanTaskUser` | The user or group assigned to the task. | +| `slaMinutes` | `number` | The service level agreement in minutes. | + +### `HumanTaskTrigger` +| Property | Type | Description | +| --- | --- | --- | +| `startWorkflowRequest` | `StartWorkflowRequest` | The request to start a workflow. | +| `triggerType` | `'ASSIGNEE_CHANGED' \| 'PENDING' \| 'IN_PROGRESS' \| 'ASSIGNED' \| 'COMPLETED' \| 'TIMED_OUT'` | The type of the trigger. | + +### `UserFormTemplate` +| Property | Type | Description | +| --- | --- | --- | +| `name` | `string` | The name of the template. | +| `version` | `number` | The version of the template. | + +### `StartWorkflowRequest` +| Property | Type | Description | +| --- | --- | --- | +| `name` | `string` | The name of the workflow. | +| `version` | `number` | The version of the workflow. | +| `correlationId` | `string` | The correlation ID of the workflow. | +| `input` | `Record` | The input data for the workflow. | +| `taskToDomain` | `Record` | A map of task reference names to domains. | +| `workflowDef` | `WorkflowDef` | The workflow definition. | +| `externalInputPayloadStoragePath`| `string` | The path to the external input payload storage. | +| `idempotencyKey` | `string` | The idempotency key for the workflow. | +| `idempotencyStrategy` | `'FAIL' \| 'RETURN_EXISTING'` | The idempotency strategy for the workflow. | +| `priority` | `number` | The priority of the workflow. | +| `createdBy` | `string` | The user who created the workflow. | + +### `HumanTaskSearch` +| Property | Type | Description | +| --- | --- | --- | +| `size` | `number` | The number of results to return. | +| `states` | `string[]` | A list of states to filter by. | +| `taskInputQuery` | `string` | A query to filter tasks by their input data. | +| `taskOutputQuery` | `string` | A query to filter tasks by their output data. | +| `definitionNames` | `string[]` | A list of task definition names to filter by. | +| `taskRefNames` | `string[]` | A list of task reference names to filter by. | +| `claimants` | `HumanTaskUser[]` | A list of claimants to filter by. | +| `assignees` | `HumanTaskUser[]` | A list of assignees to filter by. | +| `start` | `number` | The starting offset. | + +### `PollIntervalOptions` +| Property | Type | Description | +| --- | --- | --- | +| `pollInterval` | `number` | The interval in milliseconds to poll for tasks. | +| `maxPollTimes` | `number` | The maximum number of times to poll for tasks. | diff --git a/docs/api-reference/metadata-client.md b/docs/api-reference/metadata-client.md new file mode 100644 index 00000000..faa3d4a0 --- /dev/null +++ b/docs/api-reference/metadata-client.md @@ -0,0 +1,119 @@ +# MetadataClient API Reference + +The `MetadataClient` class provides methods for managing task and workflow definitions in Conductor. + +## Constructor + +### `new MetadataClient(client: ConductorClient)` + +Creates a new `MetadataClient`. + +**Parameters:** + +- `client` (`ConductorClient`): An instance of `ConductorClient`. + +--- + +## Methods + +### `unregisterTask(name: string): Promise` + +Unregisters an existing task definition by name. + +**Parameters:** + +- `name` (`string`): The name of the task definition. + +**Returns:** + +- `Promise` + +--- + +### `registerTask(taskDef: TaskDef): Promise` + +Registers a new task definition. + +**Parameters:** + +- `taskDef` (`TaskDef`): The task definition to register. + +**Returns:** + +- `Promise` + +--- + +### `updateTask(taskDef: TaskDef): Promise` + +Updates an existing task definition. + +**Parameters:** + +- `taskDef` (`TaskDef`): The task definition to update. + +**Returns:** + +- `Promise` + +--- + +### `registerWorkflowDef(workflowDef: WorkflowDef, overwrite: boolean = false): Promise` + +Creates or updates a workflow definition. + +**Parameters:** + +- `workflowDef` (`WorkflowDef`): The workflow definition to register. +- `overwrite` (`boolean`, optional): Whether to overwrite an existing workflow definition. Defaults to `false`. + +**Returns:** + +- `Promise` + +--- + +### `unregisterWorkflow(workflowName: string, version: number = 1): Promise` + +Unregisters a workflow definition. + +**Parameters:** + +- `workflowName` (`string`): The name of the workflow to unregister. +- `version` (`number`, optional): The version of the workflow to unregister. Defaults to `1`. + +**Returns:** + +- `Promise` + +--- + +## Type Definitions + +### `TaskDef` +| Property | Type | Description | +| --- | --- | --- | +| `ownerApp` | `string` | The owner app of the task. | +| `createTime` | `number` | The creation time of the task. | +| `updateTime` | `number` | The last update time of the task. | +| `createdBy` | `string` | The user who created the task. | +| `updatedBy` | `string` | The user who last updated the task. | +| `name` | `string` | The name of the task. | +| `description` | `string` | The description of the task. | +| `retryCount` | `number` | The retry count. | +| `timeoutSeconds` | `number` | The timeout in seconds. | +| `inputKeys` | `string[]` | The input keys of the task. | +| `outputKeys` | `string[]` | The output keys of the task. | +| `timeoutPolicy` | `'RETRY' \| 'TIME_OUT_WF' \| 'ALERT_ONLY'` | The timeout policy of the task. | +| `retryLogic` | `'FIXED' \| 'EXPONENTIAL_BACKOFF' \| 'LINEAR_BACKOFF'` | The retry logic of the task. | +| `retryDelaySeconds` | `number` | The retry delay in seconds. | +| `responseTimeoutSeconds` | `number` | The response timeout in seconds. | +| `concurrentExecLimit` | `number` | The concurrent execution limit. | +| `inputTemplate` | `Record` | The input template of the task. | +| `rateLimitPerFrequency` | `number` | The rate limit per frequency. | +| `rateLimitFrequencyInSeconds` | `number` | The rate limit frequency in seconds. | +| `isolationGroupId` | `string` | The isolation group ID. | +| `executionNameSpace` | `string` | The execution namespace. | +| `ownerEmail` | `string` | The owner email of the task. | +| `pollTimeoutSeconds` | `number` | The poll timeout in seconds. | +| `backoffScaleFactor` | `number` | The backoff scale factor. | diff --git a/docs/api-reference/scheduler-client.md b/docs/api-reference/scheduler-client.md new file mode 100644 index 00000000..2c0ea5a0 --- /dev/null +++ b/docs/api-reference/scheduler-client.md @@ -0,0 +1,216 @@ +# SchedulerClient API Reference + +The `SchedulerClient` manages workflow scheduling and provides methods for creating, managing, and monitoring scheduled workflows. + +## Constructor + +### `new SchedulerClient(client: ConductorClient)` + +Creates a new `SchedulerClient`. + +**Parameters:** + +- `client` (`ConductorClient`): An instance of `ConductorClient`. + +--- + +## Methods + +### `saveSchedule(param: SaveScheduleRequest): Promise` + +Creates or updates a schedule for a specified workflow. + +**Parameters:** + +- `param` (`SaveScheduleRequest`): The request to save a schedule. + +**Returns:** + +- `Promise` + +--- + +### `search(start: number, size: number, sort: string = "", freeText: string, query: string): Promise` + +Searches for scheduler executions. + +**Parameters:** + +- `start` (`number`): The starting offset. +- `size` (`number`): The number of results to return. +- `sort` (`string`, optional): The sort order. +- `freeText` (`string`): The free text to search for. +- `query` (`string`): The search query. + +**Returns:** + +- `Promise`: The search results. + +--- + +### `getSchedule(name: string): Promise` + +Gets an existing schedule by name. + +**Parameters:** + +- `name` (`string`): The name of the schedule. + +**Returns:** + +- `Promise`: The schedule. + +--- + +### `pauseSchedule(name: string): Promise` + +Pauses an existing schedule by name. + +**Parameters:** + +- `name` (`string`): The name of the schedule. + +**Returns:** + +- `Promise` + +--- + +### `resumeSchedule(name: string): Promise` + +Resumes a paused schedule by name. + +**Parameters:** + +- `name` (`string`): The name of the schedule. + +**Returns:** + +- `Promise` + +--- + +### `deleteSchedule(name: string): Promise` + +Deletes an existing schedule by name. + +**Parameters:** + +- `name` (`string`): The name of the schedule. + +**Returns:** + +- `Promise` + +--- + +### `getAllSchedules(workflowName?: string): Promise>` + +Gets all existing workflow schedules, optionally filtering by workflow name. + +**Parameters:** + +- `workflowName` (`string`, optional): The name of the workflow. + +**Returns:** + +- `Promise>`: An array of workflow schedules. + +--- + +### `getNextFewSchedules(cronExpression: string, scheduleStartTime?: number, scheduleEndTime?: number, limit: number = 3): Promise>` + +Gets a list of the next execution times for a schedule. + +**Parameters:** + +- `cronExpression` (`string`): The cron expression for the schedule. +- `scheduleStartTime` (`number`, optional): The start time for the schedule. +- `scheduleEndTime` (`number`, optional): The end time for the schedule. +- `limit` (`number`, optional): The number of execution times to return. Defaults to 3. + +**Returns:** + +- `Promise>`: An array of the next execution times. + +--- + +### `pauseAllSchedules(): Promise` + +Pauses all scheduling in the Conductor server instance. + +**Returns:** + +- `Promise` + +--- + +### `requeueAllExecutionRecords(): Promise` + +Requeues all execution records. + +**Returns:** + +- `Promise` + +--- + +### `resumeAllSchedules(): Promise` + +Resumes all scheduling in the Conductor server instance. + +**Returns:** + +- `Promise` + +--- + +## Type Definitions + +### `SaveScheduleRequest` +| Property | Type | Description | +| --- | --- | --- | +| `name` | `string` | The name of the schedule. | +| `cronExpression` | `string` | The cron expression for the schedule. | +| `runCatchupScheduleInstances` | `boolean` | Whether to run catch-up schedule instances. | +| `paused` | `boolean` | Whether the schedule is paused. | +| `startWorkflowRequest` | `StartWorkflowRequest` | The request to start a workflow. | +| `createdBy` | `string` | The user who created the schedule. | +| `updatedBy` | `string` | The user who last updated the schedule. | +| `scheduleStartTime` | `number` | The start time for the schedule. | +| `scheduleEndTime` | `number` | The end time for the schedule. | + +### `SearchResultWorkflowScheduleExecutionModel` +| Property | Type | Description | +| --- | --- | --- | +| `totalHits` | `number` | The total number of hits. | +| `results` | `WorkflowScheduleExecutionModel[]` | The search results. | + +### `WorkflowSchedule` +| Property | Type | Description | +| --- | --- | --- | +| `name` | `string` | The name of the schedule. | +| `cronExpression` | `string` | The cron expression for the schedule. | +| `runCatchupScheduleInstances` | `boolean` | Whether to run catch-up schedule instances. | +| `paused` | `boolean` | Whether the schedule is paused. | +| `startWorkflowRequest` | `StartWorkflowRequest` | The request to start a workflow. | +| `scheduleStartTime` | `number` | The start time for the schedule. | +| `scheduleEndTime` | `number` | The end time for the schedule. | +| `createTime` | `number` | The creation time of the schedule. | +| `updatedTime` | `number` | The last update time of the schedule. | +| `createdBy` | `string` | The user who created the schedule. | +| `updatedBy` | `string` | The user who last updated the schedule. | + +### `WorkflowScheduleExecutionModel` +| Property | Type | Description | +| --- | --- | --- | +| `executionId` | `string` | The ID of the execution. | +| `scheduleName` | `string` | The name of the schedule. | +| `scheduledTime` | `number` | The scheduled time of the execution. | +| `executionTime` | `number` | The execution time. | +| `workflowName` | `string` | The name of the workflow. | +| `workflowId` | `string` | The ID of the workflow instance. | +| `reason` | `string` | The reason for the execution status. | +| `stackTrace` | `string` | The stack trace for a failed execution. | +| `startWorkflowRequest` | `StartWorkflowRequest` | The request to start a workflow. | +| `state` | `'POLLED' \| 'FAILED' \| 'EXECUTED'` | The state of the execution. | diff --git a/docs/api-reference/service-registry-client.md b/docs/api-reference/service-registry-client.md new file mode 100644 index 00000000..7d887f96 --- /dev/null +++ b/docs/api-reference/service-registry-client.md @@ -0,0 +1,293 @@ +# ServiceRegistryClient API Reference + +The `ServiceRegistryClient` manages service registrations and circuit breakers. + +## Constructor + +### `new ServiceRegistryClient(client: ConductorClient)` + +Creates a new `ServiceRegistryClient`. + +**Parameters:** + +- `client` (`ConductorClient`): An instance of `ConductorClient`. + +--- + +## Methods + +### `getRegisteredServices(): Promise` + +Retrieves all registered services. + +**Returns:** + +- `Promise`: An array of all registered services. + +--- + +### `removeService(name: string): Promise` + +Removes a service by name. + +**Parameters:** + +- `name` (`string`): The name of the service to remove. + +**Returns:** + +- `Promise` + +--- + +### `getService(name: string): Promise` + +Gets a service by name. + +**Parameters:** + +- `name` (`string`): The name of the service to retrieve. + +**Returns:** + +- `Promise`: The requested service registry. + +--- + +### `openCircuitBreaker(name: string): Promise` + +Opens the circuit breaker for a service. + +**Parameters:** + +- `name` (`string`): The name of the service. + +**Returns:** + +- `Promise`: A response with the circuit breaker status. + +--- + +### `closeCircuitBreaker(name: string): Promise` + +Closes the circuit breaker for a service. + +**Parameters:** + +- `name` (`string`): The name of the service. + +**Returns:** + +- `Promise`: A response with the circuit breaker status. + +--- + +### `getCircuitBreakerStatus(name: string): Promise` + +Gets the circuit breaker status for a service. + +**Parameters:** + +- `name` (`string`): The name of the service. + +**Returns:** + +- `Promise`: A response with the circuit breaker status. + +--- + +### `addOrUpdateService(serviceRegistry: ServiceRegistry): Promise` + +Adds or updates a service registry. + +**Parameters:** + +- `serviceRegistry` (`ServiceRegistry`): The service registry to add or update. + +**Returns:** + +- `Promise` + +--- + +### `addOrUpdateServiceMethod(registryName: string, method: ServiceMethod): Promise` + +Adds or updates a service method. + +**Parameters:** + +- `registryName` (`string`): The name of the registry. +- `method` (`ServiceMethod`): The service method to add or update. + +**Returns:** + +- `Promise` + +--- + +### `removeMethod(registryName: string, serviceName: string, method: string, methodType: string): Promise` + +Removes a service method. + +**Parameters:** + +- `registryName` (`string`): The name of the registry. +- `serviceName` (`string`): The name of the service. +- `method` (`string`): The name of the method. +- `methodType` (`string`): The type of the method. + +**Returns:** + +- `Promise` + +--- + +### `getProtoData(registryName: string, filename: string): Promise` + +Gets proto data. + +**Parameters:** + +- `registryName` (`string`): The name of the registry. +- `filename` (`string`): The name of the proto file. + +**Returns:** + +- `Promise`: The proto file data as a `Blob`. + +--- + +### `setProtoData(registryName: string, filename: string, data: Blob): Promise` + +Sets proto data. + +**Parameters:** + +- `registryName` (`string`): The name of the registry. +- `filename` (`string`): The name of the proto file. +- `data` (`Blob`): The proto file data. + +**Returns:** + +- `Promise` + +--- + +### `deleteProto(registryName: string, filename: string): Promise` + +Deletes a proto file. + +**Parameters:** + +- `registryName` (`string`): The name of the registry. +- `filename` (`string`): The name of the proto file. + +**Returns:** + +- `Promise` + +--- + +### `getAllProtos(registryName: string): Promise` + +Gets all proto files for a registry. + +**Parameters:** + +- `registryName` (`string`): The name of the registry. + +**Returns:** + +- `Promise`: A list of proto registry entries. + +--- + +### `discover(name: string, create: boolean = false): Promise` + +Discovers service methods. + +**Parameters:** + +- `name` (`string`): The name of the service. +- `create` (`boolean`, optional): Whether to create the discovered methods. Defaults to `false`. + +**Returns:** + +- `Promise`: The discovered service methods. + +--- + +## Type Definitions + +### `ServiceRegistry` +| Property | Type | Description | +| --- | --- | --- | +| `name` | `string` | The name of the service. | +| `type` | `ServiceType` | The type of the service. | +| `serviceURI` | `string` | The URI of the service. | +| `methods` | `ServiceMethod[]` | The methods of the service. | +| `requestParams` | `RequestParam[]` | The request parameters of the service. | +| `config` | `ServiceRegistryConfig` | The configuration of the service. | + +### `ServiceType` +`ServiceType` is an enum that can be one of the following values: `'HTTP'`, `'gRPC'`. + +### `ServiceMethod` +| Property | Type | Description | +| --- | --- | --- | +| `id` | `number` | The ID of the method. | +| `operationName` | `string` | The name of the operation. | +| `methodName` | `string` | The name of the method. | +| `methodType` | `string` | The type of the method. | +| `inputType` | `string` | The input type of the method. | +| `outputType` | `string` | The output type of the method. | +| `requestParams` | `RequestParam[]` | The request parameters of the method. | +| `exampleInput` | `Record` | An example input for the method. | + +### `RequestParam` +| Property | Type | Description | +| --- | --- | --- | +| `name` | `string` | The name of the parameter. | +| `type` | `string` | The type of the parameter. | +| `required` | `boolean` | Whether the parameter is required. | +| `schema` | `RequestParamSchema` | The schema of the parameter. | + +### `RequestParamSchema` +| Property | Type | Description | +| --- | --- | --- | +| `type` | `string` | The type of the schema. | +| `format` | `string` | The format of the schema. | +| `defaultValue` | `any` | The default value of the schema. | + +### `ServiceRegistryConfig` +| Property | Type | Description | +| --- | --- | --- | +| `circuitBreakerConfig` | `OrkesCircuitBreakerConfig` | The circuit breaker configuration. | + +### `OrkesCircuitBreakerConfig` +| Property | Type | Description | +| --- | --- | --- | +| `failureRateThreshold` | `number` | The failure rate threshold. | +| `slidingWindowSize` | `number` | The sliding window size. | +| `minimumNumberOfCalls` | `number` | The minimum number of calls. | +| `waitDurationInOpenState` | `number` | The wait duration in the open state. | +| `permittedNumberOfCallsInHalfOpenState`| `number` | The permitted number of calls in the half-open state. | +| `slowCallRateThreshold` | `number` | The slow call rate threshold. | +| `slowCallDurationThreshold` | `number` | The slow call duration threshold. | +| `automaticTransitionFromOpenToHalfOpenEnabled` | `boolean` | Whether automatic transition from open to half-open is enabled. | +| `maxWaitDurationInHalfOpenState` | `number` | The maximum wait duration in the half-open state. | + +### `CircuitBreakerTransitionResponse` +| Property | Type | Description | +| --- | --- | --- | +| `service` | `string` | The name of the service. | +| `previousState` | `string` | The previous state of the circuit breaker. | +| `currentState` | `string` | The current state of the circuit breaker. | +| `transitionTimestamp` | `number` | The timestamp of the transition. | +| `message` | `string` | The transition message. | + +### `ProtoRegistryEntry` +| Property | Type | Description | +| --- | --- | --- | +| `filename` | `string` | The name of the proto file. | +| `lastUpdated` | `number` | The last update time of the proto file. | diff --git a/docs/api-reference/task-client.md b/docs/api-reference/task-client.md new file mode 100644 index 00000000..7ec8431c --- /dev/null +++ b/docs/api-reference/task-client.md @@ -0,0 +1,95 @@ +# TaskClient API Reference + +The `TaskClient` provides capabilities for monitoring and debugging tasks within your workflow executions. + +## Constructor + +### `new TaskClient(client: ConductorClient)` + +Creates a new TaskClient. + +**Parameters:** + +- `client` (`ConductorClient`): An instance of `ConductorClient`. + +--- + +## Methods + +### `search(start: number, size: number, sort: string = "", freeText: string, query: string): Promise` + +Searches for tasks. + +**Parameters:** + +- `start` (`number`): The starting offset. +- `size` (`number`): The number of results to return. +- `sort` (`string`, optional): The sort order. +- `freeText` (`string`): The free text to search for. +- `query` (`string`): The search query. + +**Returns:** + +- `Promise`: The search results. + +--- + +### `getTask(taskId: string): Promise` + +Gets a task by its ID. + +**Parameters:** + +- `taskId` (`string`): The ID of the task. + +**Returns:** + +- `Promise`: The task. + +--- + +### `updateTaskResult(workflowId: string, taskReferenceName: string, status: TaskResultStatus, outputData: Record): Promise` + +Updates the result of a task. + +**Parameters:** + +- `workflowId` (`string`): The ID of the workflow instance. +- `taskReferenceName` (`string`): The reference name of the task. +- `status` (`TaskResultStatus`): The new status of the task. +- `outputData` (`Record`): The output data of the task. + +**Returns:** + +- `Promise`: The result of the task update. + +--- + +## Type Definitions + +### `SearchResultTask` +| Property | Type | Description | +| --- | --- | --- | +| `totalHits` | `number` | The total number of hits. | +| `results` | `Task[]` | The search results. | + +### `TaskResult` +| Property | Type | Description | +| --- | --- | --- | +| `workflowInstanceId` | `string` | The ID of the workflow instance. | +| `taskId` | `string` | The ID of the task. | +| `reasonForIncompletion` | `string` | The reason for incompletion. | +| `callbackAfterSeconds` | `number` | The callback after seconds. | +| `workerId` | `string` | The ID of the worker. | +| `status` | `'IN_PROGRESS' \| 'FAILED' \| 'FAILED_WITH_TERMINAL_ERROR' \| 'COMPLETED'` | The status of the task. | +| `outputData` | `Record` | The output data of the task. | +| `logs` | `TaskExecLog[]` | The execution logs of the task. | +| `externalOutputPayloadStoragePath`| `string` | The path to the external output payload storage. | +| `subWorkflowId` | `string` | The ID of the sub-workflow. | + +### `TaskExecLog` +| Property | Type | Description | +| --- | --- | --- | +| `log` | `string` | The log message. | +| `taskId` | `string` | The ID of the task. | +| `createdTime` | `number` | The creation time of the log. | diff --git a/docs/api-reference/task-generators.md b/docs/api-reference/task-generators.md new file mode 100644 index 00000000..b5e66e5d --- /dev/null +++ b/docs/api-reference/task-generators.md @@ -0,0 +1,251 @@ +### Task Generators Reference + +This section provides code examples for each task type generator. Use these to build your workflow task lists. + +**Note:** These generators create workflow task references. To register task metadata (retry policies, timeouts, rate limits), use `taskDefinition()` or `MetadataClient` (see [Metadata](#metadata)). + +#### Simple Task + +*Requires Custom Workers* - Executes custom business logic via workers you implement. + +```typescript +import { simpleTask } from "@io-orkes/conductor-javascript"; + +const task = simpleTask( + "task_ref", // taskReferenceName (required) + "task_name", // name (required): must match worker's taskDefName + { // inputParameters (required) + inputParam: "value" + }, + false // optional (optional): if true, workflow continues on failure +); +``` + +#### HTTP Task + +*System Task* - Makes HTTP/REST API calls. + +```typescript +import { httpTask } from "@io-orkes/conductor-javascript"; + +const task = httpTask( + "http_ref", + { + uri: "http://api.example.com/data", + method: "GET", + headers: { "Authorization": "Bearer token" }, + connectionTimeOut: 5000, + readTimeOut: 10000 + }, + false, // asyncComplete (optional) + false // optional (optional): workflow continues on failure +); +``` + +#### Switch Task + +*System Task* - Provides conditional branching based on input values. + +```typescript +import { switchTask } from "@io-orkes/conductor-javascript"; + +const task = switchTask( + "switch_ref", + "input.status", // expression to evaluate + { + "active": [simpleTask("active_task", "process_active", {})], + "inactive": [simpleTask("inactive_task", "process_inactive", {})] + }, + [simpleTask("default_task", "process_default", {})], // defaultCase (optional) + false // optional (optional): workflow continues on failure +); +``` + +#### Fork-Join Task + +*System Task* - Executes multiple task branches in parallel and waits for all to complete. + +```typescript +import { forkJoinTask } from "@io-orkes/conductor-javascript"; + +const task = forkJoinTask("fork_ref", [ + [simpleTask("task1", "process_1", {})], + [simpleTask("task2", "process_2", {})], + [simpleTask("task3", "process_3", {})] +]); +``` + +#### Do-While Task + +*System Task* - Executes a loop with a condition evaluated after each iteration. + +```typescript +import { doWhileTask } from "@io-orkes/conductor-javascript"; + +const task = doWhileTask("while_ref", "workflow.variables.counter < 10", [ + simpleTask("loop_task", "process_item", { + index: "${workflow.variables.counter}" + }), + setVariableTask("increment", { + variableName: "counter", + value: "${workflow.variables.counter + 1}" + }) +]); +``` + +#### Sub-Workflow Task + +*System Task* - Executes another workflow as a task. + +```typescript +import { subWorkflowTask } from "@io-orkes/conductor-javascript"; + +const task = subWorkflowTask( + "sub_ref", + "child_workflow", // workflowName + 1, // version (optional): uses latest if not specified + false // optional (optional) +); + +// Set input parameters +task.inputParameters = { inputParam: "value" }; +``` + +#### Event Task + +*System Task* - Publishes events to external eventing systems. + +```typescript +import { eventTask } from "@io-orkes/conductor-javascript"; + +const task = eventTask("event_ref", "event_name", { + sink: "event_sink", + asyncComplete: true +}); +``` + +#### Wait Task + +*System Task* - Pauses workflow execution for a specified duration or until a specific time. + +```typescript +import { waitTaskDuration, waitTaskUntil } from "@io-orkes/conductor-javascript"; + +// Wait for a duration (e.g., "30s", "5m", "1h", "2d") +const taskDuration = waitTaskDuration( + "wait_ref", + "30s", // duration string + false // optional (optional) +); + +// Wait until a specific time (ISO 8601 format) +const taskUntil = waitTaskUntil( + "wait_until_ref", + "2025-12-31T23:59:59Z", // ISO 8601 timestamp + false // optional (optional) +); +``` + +#### Terminate Task + +*System Task* - Terminates workflow execution with a specified status. + +```typescript +import { terminateTask } from "@io-orkes/conductor-javascript"; + +const task = terminateTask( + "terminate_ref", + "FAILED", // status: "COMPLETED" or "FAILED" + "Error message" // terminationReason (optional) +); +``` + +#### Set Variable Task + +*System Task* - Sets or updates workflow variables. + +```typescript +import { setVariableTask } from "@io-orkes/conductor-javascript"; + +const task = setVariableTask("var_ref", { + variableName: "result", + value: "computed_value" +}); +``` + +#### JSON JQ Transform Task + +*System Task* - Transforms JSON data using JQ expressions. + +```typescript +import { jsonJqTask } from "@io-orkes/conductor-javascript"; + +const task = jsonJqTask("transform_ref", ".data.items[] | {id: .id, name: .name}"); +``` + +#### Kafka Publish Task + +*System Task* - Publishes messages to Kafka topics. + +```typescript +import { kafkaPublishTask } from "@io-orkes/conductor-javascript"; + +const task = kafkaPublishTask("kafka_ref", "topic_name", { + message: "Hello Kafka!" +}, { + key: "message_key", + partition: 0 +}); +``` + +#### Inline Task + +*System Task* - Executes JavaScript code inline within the workflow. + +```typescript +import { inlineTask } from "@io-orkes/conductor-javascript"; + +const task = inlineTask("inline_ref", ` + function execute(input) { + return { result: input.value * 2 }; + } +`); +``` + +#### Dynamic Fork Task + +*System Task* - Dynamically creates parallel task executions based on input. + +```typescript +import { dynamicForkTask } from "@io-orkes/conductor-javascript"; + +const task = dynamicForkTask("dynamic_ref", "input.tasks", "task_name"); +``` + +#### Join Task + +*System Task* - Synchronization point for forked tasks. + +```typescript +import { joinTask } from "@io-orkes/conductor-javascript"; + +const task = joinTask("join_ref"); +``` + +#### Human Task + +*System Task* - Pauses workflow until a person completes an action (approval, form submission, etc.). + +```typescript +import { humanTask } from "@io-orkes/conductor-javascript"; + +const task = humanTask("human_ref", "approval_task", { + assignee: "user@example.com", + form: { + fields: [ + { name: "approved", type: "boolean", required: true }, + { name: "comments", type: "text", required: false } + ] + } +}); +``` diff --git a/docs/api-reference/task-manager.md b/docs/api-reference/task-manager.md new file mode 100644 index 00000000..c5b19e0f --- /dev/null +++ b/docs/api-reference/task-manager.md @@ -0,0 +1,98 @@ +# TaskManager API Reference + +The `TaskManager` is responsible for initializing and managing the runners that poll and work different task queues. + +## Constructor + +### `new TaskManager(client: ConductorClient, workers: Array, config: TaskManagerConfig = {})` + +Creates a new TaskManager. + +**Parameters:** + +- `client` (`ConductorClient`): An instance of `ConductorClient`. +- `workers` (`Array`): An array of `ConductorWorker` instances. +- `config` (`TaskManagerConfig`, optional): Configuration for the `TaskManager`. + +--- + +## Properties + +### `isPolling: boolean` + +Returns whether the `TaskManager` is currently polling for tasks. + +--- + +## Methods + +### `updatePollingOptionForWorker(workerTaskDefName: string, options: Partial): void` + +Updates the polling options for a specific worker. + +**Parameters:** + +- `workerTaskDefName` (`string`): The task definition name of the worker. +- `options` (`Partial`): The new polling options. + +--- + +### `updatePollingOptions(options: Partial): void` + +Updates the polling options for all workers. + +**Parameters:** + +- `options` (`Partial`): The new polling options. + +--- + +### `startPolling(): void` + +Starts polling for tasks for all workers. + +--- + +### `stopPolling(): Promise` + +Stops polling for tasks for all workers. + +--- + +### `sanityCheck(): void` + +Performs a sanity check on the workers, ensuring there are no duplicates and that at least one worker is present. Throws an error if the check fails. + +--- + +## Type Definitions + +### `ConductorWorker` +| Property | Type | Description | +| --- | --- | --- | +| `taskDefName` | `string` | The name of the task definition. | +| `execute` | `(task: Task) => Promise>` | The function that executes the task. | +| `domain` | `string` | The domain of the worker. | +| `concurrency` | `number` | The number of polling instances to run concurrently. | +| `pollInterval` | `number` | The interval in milliseconds to poll for tasks. | + +### `TaskManagerConfig` +| Property | Type | Description | +| --- | --- | --- | +| `logger` | `ConductorLogger` | A logger instance. | +| `options` | `Partial` | The options for the `TaskManager`. | +| `onError` | `TaskErrorHandler` | A function to handle errors. | +| `maxRetries` | `number` | The maximum number of retries for a task. | + +### `TaskManagerOptions` +| Property | Type | Description | +| --- | --- | --- | +| `workerID` | `string` | The ID of the worker. | +| `domain` | `string` | The domain of the worker. | +| `pollInterval` | `number` | The interval in milliseconds to poll for tasks. | +| `concurrency` | `number` | The number of polling instances to run concurrently. | +| `batchPollingTimeout` | `number` | The timeout in milliseconds for batch polling. | + +### `TaskErrorHandler` +`TaskErrorHandler` is a function that takes an `Error` and an optional `Task` and handles the error. +`(error: Error, task?: Task) => void` diff --git a/docs/api-reference/template-client.md b/docs/api-reference/template-client.md new file mode 100644 index 00000000..5d06fc3c --- /dev/null +++ b/docs/api-reference/template-client.md @@ -0,0 +1,46 @@ +# TemplateClient API Reference + +The `TemplateClient` class provides methods for managing human task templates (forms and UI). + +## Constructor + +### `new TemplateClient(client: ConductorClient)` + +Creates a new `TemplateClient`. + +**Parameters:** + +- `client` (`ConductorClient`): An instance of `ConductorClient`. + +--- + +## Methods + +### `registerTemplate(template: HumanTaskTemplate, asNewVersion: boolean = false): Promise` + +Registers a new human task template. + +**Parameters:** + +- `template` (`HumanTaskTemplate`): The template to register. +- `asNewVersion` (`boolean`, optional): Whether to register the template as a new version. Defaults to `false`. + +**Returns:** + +- `Promise`: The registered template. + +--- + +## Type Definitions + +### `HumanTaskTemplate` +| Property | Type | Description | +| --- | --- | --- | +| `createdBy` | `string` | The user who created the template. | +| `createdOn` | `number` | The creation time of the template. | +| `jsonSchema` | `Record` | The JSON schema of the template. | +| `name` | `string` | The name of the template. | +| `templateUI` | `Record` | The UI of the template. | +| `updatedBy` | `string` | The user who last updated the template. | +| `updatedOn` | `number` | The last update time of the template. | +| `version` | `number` | The version of the template. | diff --git a/docs/api-reference/workflow-executor.md b/docs/api-reference/workflow-executor.md new file mode 100644 index 00000000..2a5e316b --- /dev/null +++ b/docs/api-reference/workflow-executor.md @@ -0,0 +1,576 @@ +# WorkflowExecutor API Reference + +The `WorkflowExecutor` class is your main interface for managing workflows. It provides methods to register, start, monitor, and control workflow execution. + +## Constructor + +### `new WorkflowExecutor(client: ConductorClient)` + +Creates a new WorkflowExecutor. + +**Parameters:** + +- `client` (`ConductorClient`): An instance of `ConductorClient`. + +--- + +## Methods + +### `registerWorkflow(override: boolean, workflow: WorkflowDef): Promise` + +Registers a workflow definition. + +**Parameters:** + +- `override` (`boolean`): Whether to override the existing workflow definition. +- `workflow` (`WorkflowDef`): The workflow definition. + +**Returns:** + +- `Promise` + +--- + +### `startWorkflow(workflowRequest: StartWorkflowRequest): Promise` + +Starts a new workflow execution. + +**Parameters:** + +- `workflowRequest` (`StartWorkflowRequest`): The request to start a workflow. + +**Returns:** + +- `Promise`: The ID of the workflow instance. + +--- + +### `executeWorkflow(workflowRequest: StartWorkflowRequest, name: string, version: number, requestId: string, waitUntilTaskRef?: string): Promise` +### `executeWorkflow(workflowRequest: StartWorkflowRequest, name: string, version: number, requestId: string, waitUntilTaskRef: string, waitForSeconds: number, consistency: Consistency, returnStrategy: ReturnStrategy): Promise` + +Executes a workflow synchronously and waits for completion. Can return different responses based on the provided parameters. + +**Parameters:** + +- `workflowRequest` (`StartWorkflowRequest`): The request to start a workflow. +- `name` (`string`): The name of the workflow. +- `version` (`number`): The version of the workflow. +- `requestId` (`string`): A unique ID for the request. +- `waitUntilTaskRef` (`string`, optional): The reference name of the task to wait for. +- `waitForSeconds` (`number`, optional): The number of seconds to wait for the task. +- `consistency` (`Consistency`, optional): The consistency level for the read operations. +- `returnStrategy` (`ReturnStrategy`, optional): The strategy for what data to return. + +**Returns:** + +- `Promise`: A `WorkflowRun` object or a `SignalResponse` object. + +--- + +### `startWorkflows(workflowsRequest: StartWorkflowRequest[]): Promise[]` + +Starts multiple workflows at once. + +**Parameters:** + +- `workflowsRequest` (`StartWorkflowRequest[]`): An array of workflow start requests. + +**Returns:** + +- `Promise[]`: An array of promises that resolve to the workflow instance IDs. + +--- + +### `goBackToTask(workflowInstanceId: string, taskFinderPredicate: TaskFinderPredicate, rerunWorkflowRequestOverrides: Partial = {}): Promise` + +Reruns a workflow from a specific task. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `taskFinderPredicate` (`TaskFinderPredicate`): A function to find the task to rerun from. +- `rerunWorkflowRequestOverrides` (`Partial`, optional): Overrides for the rerun request. + +**Returns:** + +- `Promise` + +--- + +### `goBackToFirstTaskMatchingType(workflowInstanceId: string, taskType: string): Promise` + +Reruns a workflow from the first task of a specific type. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `taskType` (`string`): The type of the task to rerun from. + +**Returns:** + +- `Promise` + +--- + +### `getWorkflow(workflowInstanceId: string, includeTasks: boolean, retry: number = 0): Promise` + +Gets the execution status of a workflow. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `includeTasks` (`boolean`): Whether to include the tasks in the response. +- `retry` (`number`, optional): The number of times to retry on failure. + +**Returns:** + +- `Promise`: The workflow execution status. + +--- + +### `getWorkflowStatus(workflowInstanceId: string, includeOutput: boolean, includeVariables: boolean): Promise` + +Gets a summary of the current workflow status. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `includeOutput` (`boolean`): Whether to include the output in the response. +- `includeVariables` (`boolean`): Whether to include the variables in the response. + +**Returns:** + +- `Promise`: The workflow status summary. + +--- + +### `getExecution(workflowInstanceId: string, includeTasks: boolean = true): Promise` + +Gets the execution status of a workflow, including tasks by default. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `includeTasks` (`boolean`, optional): Whether to include the tasks in the response. Defaults to `true`. + +**Returns:** + +- `Promise`: The workflow execution status. + +--- + +### `pause(workflowInstanceId: string): Promise` + +Pauses a running workflow. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. + +**Returns:** + +- `Promise` + +--- + +### `reRun(workflowInstanceId: string, rerunWorkflowRequest: Partial = {}): Promise` + +Reruns a workflow with new parameters. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `rerunWorkflowRequest` (`Partial`, optional): Overrides for the rerun request. + +**Returns:** + +- `Promise`: The ID of the new workflow instance. + +--- + +### `restart(workflowInstanceId: string, useLatestDefinitions: boolean): Promise` + +Restarts a workflow. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `useLatestDefinitions` (`boolean`): Whether to use the latest workflow definition. + +**Returns:** + +- `Promise` + +--- + +### `resume(workflowInstanceId: string): Promise` + +Resumes a paused workflow. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. + +**Returns:** + +- `Promise` + +--- + +### `retry(workflowInstanceId: string, resumeSubworkflowTasks: boolean): Promise` + +Retries a workflow from the last failing task. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `resumeSubworkflowTasks` (`boolean`): Whether to resume tasks in sub-workflows. + +**Returns:** + +- `Promise` + +--- + +### `search(start: number, size: number, query: string, freeText: string, sort: string = "", skipCache: boolean = false): Promise` + +Searches for workflows. + +**Parameters:** + +- `start` (`number`): The starting offset. +- `size` (`number`): The number of results to return. +- `query` (`string`): The search query. +- `freeText` (`string`): The free text to search for. +- `sort` (`string`, optional): The sort order. +- `skipCache` (`boolean`, optional): Whether to skip the cache. + +**Returns:** + +- `Promise`: The search results. + +--- + +### `skipTasksFromWorkflow(workflowInstanceId: string, taskReferenceName: string, skipTaskRequest: Partial): Promise` + +Skips a task in a running workflow. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `taskReferenceName` (`string`): The reference name of the task to skip. +- `skipTaskRequest` (`Partial`): The request to skip the task. + +**Returns:** + +- `Promise` + +--- + +### `terminate(workflowInstanceId: string, reason: string): Promise` + +Terminates a running workflow. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `reason` (`string`): The reason for termination. + +**Returns:** + +- `Promise` + +--- + +### `updateTask(taskId: string, workflowInstanceId: string, taskStatus: TaskResultStatus, outputData: Record): Promise` + +Updates a task by its ID. + +**Parameters:** + +- `taskId` (`string`): The ID of the task. +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `taskStatus` (`TaskResultStatus`): The new status of the task. +- `outputData` (`Record`): The output data of the task. + +**Returns:** + +- `Promise` + +--- + +### `updateTaskByRefName(taskReferenceName: string, workflowInstanceId: string, status: TaskResultStatus, taskOutput: Record): Promise` + +Updates a task by its reference name. + +**Parameters:** + +- `taskReferenceName` (`string`): The reference name of the task. +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `status` (`TaskResultStatus`): The new status of the task. +- `taskOutput` (`Record`): The output data of the task. + +**Returns:** + +- `Promise` + +--- + +### `getTask(taskId: string): Promise` + +Gets a task by its ID. + +**Parameters:** + +- `taskId` (`string`): The ID of the task. + +**Returns:** + +- `Promise`: The task. + +--- + +### `updateTaskSync(taskReferenceName: string, workflowInstanceId: string, status: TaskResultStatusEnum, taskOutput: Record, workerId?: string): Promise` + +Updates a task by its reference name synchronously and returns the complete workflow. + +**Parameters:** + +- `taskReferenceName` (`string`): The reference name of the task. +- `workflowInstanceId` (`string`): The ID of the workflow instance. +- `status` (`TaskResultStatusEnum`): The new status of the task. +- `taskOutput` (`Record`): The output data of the task. +- `workerId` (`string`, optional): The ID of the worker. + +**Returns:** + +- `Promise`: The updated workflow. + +--- + +### `signal(workflowInstanceId: string, status: TaskResultStatusEnum, taskOutput: Record, returnStrategy: ReturnStrategy = ReturnStrategy.TARGET_WORKFLOW): Promise` + +Signals a workflow task and returns data based on the specified return strategy. + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance to signal. +- `status` (`TaskResultStatusEnum`): The task status to set. +- `taskOutput` (`Record`): The output data for the task. +- `returnStrategy` (`ReturnStrategy`, optional): The strategy for what data to return. Defaults to `TARGET_WORKFLOW`. + +**Returns:** + +- `Promise`: The response from the signal. + +--- + +### `signalAsync(workflowInstanceId: string, status: TaskResultStatusEnum, taskOutput: Record): Promise` + +Signals a workflow task asynchronously (fire-and-forget). + +**Parameters:** + +- `workflowInstanceId` (`string`): The ID of the workflow instance to signal. +- `status` (`TaskResultStatusEnum`): The task status to set. +- `taskOutput` (`Record`): The output data for the task. + +**Returns:** + +- `Promise` + +--- + +## Type Definitions + +### `WorkflowDef` +| Property | Type | Description | +| --- | --- | --- | +| `ownerApp` | `string` | The owner app of the workflow. | +| `createTime` | `number` | The creation time of the workflow. | +| `updateTime` | `number` | The last update time of the workflow. | +| `createdBy` | `string` | The user who created the workflow. | +| `updatedBy` | `string` | The user who last updated the workflow. | +| `name` | `string` | The name of the workflow. | +| `description` | `string` | The description of the workflow. | +| `version` | `number` | The version of the workflow. | +| `tasks` | `WorkflowTask[]` | The tasks in the workflow. | +| `inputParameters` | `string[]` | The input parameters of the workflow. | +| `outputParameters` | `Record` | The output parameters of the workflow. | +| `failureWorkflow` | `string` | The failure workflow. | +| `schemaVersion` | `number` | The schema version of the workflow. | +| `restartable` | `boolean` | Whether the workflow is restartable. | +| `workflowStatusListenerEnabled` | `boolean` | Whether the workflow status listener is enabled. | +| `ownerEmail` | `string` | The owner email of the workflow. | +| `timeoutPolicy` | `'TIME_OUT_WF' \| 'ALERT_ONLY'` | The timeout policy of the workflow. | +| `timeoutSeconds` | `number` | The timeout in seconds of the workflow. | +| `variables` | `Record` | The variables of the workflow. | +| `inputTemplate` | `Record` | The input template of the workflow. | + +### `WorkflowTask` +| Property | Type | Description | +| --- | --- | --- | +| `name` | `string` | The name of the task. | +| `taskReferenceName` | `string` | The reference name of the task. | +| `description` | `string` | The description of the task. | +| `inputParameters` | `Record` | The input parameters of the task. | +| `type` | `string` | The type of the task. | +| `dynamicTaskNameParam` | `string` | The dynamic task name parameter. | +| `caseValueParam` | `string` | The case value parameter. | +| `caseExpression` | `string` | The case expression. | +| `scriptExpression` | `string` | The script expression. | +| `decisionCases` | `Record>` | The decision cases. | +| `dynamicForkJoinTasksParam`| `string` | The dynamic fork join tasks parameter. | +| `dynamicForkTasksParam` | `string` | The dynamic fork tasks parameter. | +| `dynamicForkTasksInputParamName` | `string` | The dynamic fork tasks input parameter name. | +| `defaultCase` | `WorkflowTask[]` | The default case. | +| `forkTasks` | `WorkflowTask[][]` | The fork tasks. | +| `startDelay` | `number` | The start delay in seconds. | +| `subWorkflowParam` | `SubWorkflowParams` | The sub-workflow parameters. | +| `joinOn` | `string[]` | The join on tasks. | +| `sink` | `string` | The sink. | +| `optional` | `boolean` | Whether the task is optional. | +| `taskDefinition` | `TaskDef` | The task definition. | +| `rateLimited` | `boolean` | Whether the task is rate limited. | +| `defaultExclusiveJoinTask` | `string[]` | The default exclusive join task. | +| `asyncComplete` | `boolean` | Whether the task is async complete. | +| `loopCondition` | `string` | The loop condition. | +| `loopOver` | `WorkflowTask[]` | The loop over tasks. | +| `retryCount` | `number` | The retry count. | +| `evaluatorType` | `string` | The evaluator type. | +| `expression` | `string` | The expression. | +| `workflowTaskType` | `'SIMPLE' \| 'DYNAMIC' \| 'FORK_JOIN' \| 'FORK_JOIN_DYNAMIC' \| 'DECISION' \| 'SWITCH' \| 'JOIN' \| 'DO_WHILE' \| 'SUB_WORKFLOW' \| 'START_WORKFLOW' \| 'EVENT' \| 'WAIT' \| 'HUMAN' \| 'USER_DEFINED' \| 'HTTP' \| 'LAMBDA' \| 'INLINE' \| 'EXCLUSIVE_JOIN' \| 'TERMINATE' \| 'KAFKA_PUBLISH' \| 'JSON_JQ_TRANSFORM' \| 'SET_VARIABLE'` | The type of the workflow task. | + +### `WorkflowRun` +| Property | Type | Description | +| --- | --- | --- | +| `correlationId` | `string` | The correlation ID of the workflow. | +| `createTime` | `number` | The creation time of the workflow. | +| `createdBy` | `string` | The user who created the workflow. | +| `priority` | `number` | The priority of the workflow. | +| `requestId` | `string` | The request ID of the workflow. | +| `status` | `string` | The status of the workflow. | +| `tasks` | `Task[]` | The tasks in the workflow. | +| `updateTime` | `number` | The last update time of the workflow. | +| `workflowId` | `string` | The ID of the workflow instance. | +| `variables` | `Record` | The variables of the workflow. | +| `input` | `Record` | The input data for the workflow. | +| `output` | `Record` | The output data for the workflow. | + +### `SignalResponse` +`SignalResponse` represents a unified response from the signal API. It contains different fields depending on the `returnStrategy` used. It also has helper methods to extract the workflow or task details from the response. + +### `TaskFinderPredicate` +`TaskFinderPredicate` is a function that takes a `Task` and returns a boolean. It is used to find a specific task in a workflow. +` (task: Task) => boolean` + +### `RerunWorkflowRequest` +| Property | Type | Description | +| --- | --- | --- | +| `reRunFromWorkflowId` | `string` | The ID of the workflow to rerun from. | +| `workflowInput` | `Record` | The input data for the workflow. | +| `reRunFromTaskId` | `string` | The ID of the task to rerun from. | +| `taskInput` | `Record` | The input data for the task. | +| `correlationId` | `string` | The correlation ID of the workflow. | + +### `Workflow` +| Property | Type | Description | +| --- | --- | --- | +| `ownerApp` | `string` | The owner app of the workflow. | +| `createTime` | `number` | The creation time of the workflow. | +| `updateTime` | `number` | The last update time of the workflow. | +| `createdBy` | `string` | The user who created the workflow. | +| `updatedBy` | `string` | The user who last updated the workflow. | +| `status` | `'RUNNING' \| 'COMPLETED' \| 'FAILED' \| 'TIMED_OUT' \| 'TERMINATED' \| 'PAUSED'` | The status of the workflow. | +| `idempotencyKey` | `string` | The idempotency key for the workflow. | +| `endTime` | `number` | The end time of the workflow. | +| `workflowId` | `string` | The ID of the workflow instance. | +| `parentWorkflowId` | `string` | The ID of the parent workflow instance. | +| `parentWorkflowTaskId` | `string` | The ID of the parent workflow task. | +| `tasks` | `Task[]` | The tasks in the workflow. | +| `input` | `Record` | The input data for the workflow. | +| `output` | `Record` | The output data for the workflow. | +| `correlationId` | `string` | The correlation ID of the workflow. | +| `reRunFromWorkflowId` | `string` | The ID of the workflow to rerun from. | +| `reasonForIncompletion` | `string` | The reason for incompletion. | +| `event` | `string` | The event that triggered the workflow. | +| `taskToDomain` | `Record` | A map of task reference names to domains. | +| `failedReferenceTaskNames` | `string[]` | A list of failed task reference names. | +| `workflowDefinition` | `WorkflowDef` | The workflow definition. | +| `externalInputPayloadStoragePath`| `string` | The path to the external input payload storage. | +| `externalOutputPayloadStoragePath`| `string` | The path to the external output payload storage. | +| `priority` | `number` | The priority of the workflow. | +| `variables` | `Record` | The variables of the workflow. | +| `lastRetriedTime` | `number` | The last time the workflow was retried. | +| `startTime` | `number` | The start time of the workflow. | +| `workflowVersion` | `number` | The version of the workflow. | +| `workflowName` | `string` | The name of the workflow. | + +### `WorkflowStatus` +| Property | Type | Description | +| --- | --- | --- | +| `workflowId` | `string` | The ID of the workflow instance. | +| `correlationId` | `string` | The correlation ID of the workflow. | +| `output` | `Record` | The output data for the workflow. | +| `variables` | `Record` | The variables of the workflow. | +| `status` | `'RUNNING' \| 'COMPLETED' \| 'FAILED' \| 'TIMED_OUT' \| 'TERMINATED' \| 'PAUSED'` | The status of the workflow. | + +### `ScrollableSearchResultWorkflowSummary` +| Property | Type | Description | +| --- | --- | --- | +| `results` | `WorkflowSummary[]` | The search results. | +| `totalHits` | `number` | The total number of hits. | + +### `SkipTaskRequest` +| Property | Type | Description | +| --- | --- | --- | +| `taskInput` | `Record` | The input data for the task. | +| `taskOutput` | `Record` | The output data for the task. | + +### `TaskResultStatus` +`TaskResultStatus` is a string that represents the status of a task result. It can be one of the following values: `'IN_PROGRESS'`, `'FAILED'`, `'FAILED_WITH_TERMINAL_ERROR'`, `'COMPLETED'`. + +### `Task` +| Property | Type | Description | +| --- | --- | --- | +| `taskType` | `string` | The type of the task. | +| `status` | `'IN_PROGRESS' \| 'CANCELED' \| 'FAILED' \| 'FAILED_WITH_TERMINAL_ERROR' \| 'COMPLETED' \| 'COMPLETED_WITH_ERRORS' \| 'SCHEDULED' \| 'TIMED_OUT' \| 'SKIPPED'` | The status of the task. | +| `inputData` | `Record` | The input data for the task. | +| `referenceTaskName` | `string` | The reference name of the task. | +| `retryCount` | `number` | The retry count. | +| `seq` | `number` | The sequence number of the task. | +| `correlationId` | `string` | The correlation ID of the task. | +| `pollCount` | `number` | The poll count. | +| `taskDefName` | `string` | The name of the task definition. | +| `scheduledTime` | `number` | The scheduled time of the task. | +| `startTime` | `number` | The start time of the task. | +| `endTime` | `number` | The end time of the task. | +| `updateTime` | `number` | The last update time of the task. | +| `startDelayInSeconds` | `number` | The start delay in seconds. | +| `retriedTaskId` | `string` | The ID of the retried task. | +| `retried` | `boolean` | Whether the task was retried. | +| `executed` | `boolean` | Whether the task was executed. | +| `callbackFromWorker` | `boolean` | Whether the callback is from a worker. | +| `responseTimeoutSeconds` | `number` | The response timeout in seconds. | +| `workflowInstanceId` | `string` | The ID of the workflow instance. | +| `workflowType` | `string` | The type of the workflow. | +| `taskId` | `string` | The ID of the task. | +| `reasonForIncompletion` | `string` | The reason for incompletion. | +| `callbackAfterSeconds` | `number` | The callback after seconds. | +| `workerId` | `string` | The ID of the worker. | +| `outputData` | `Record` | The output data of the task. | +| `workflowTask` | `WorkflowTask` | The workflow task. | +| `domain` | `string` | The domain of the task. | +| `rateLimitPerFrequency` | `number` | The rate limit per frequency. | +| `rateLimitFrequencyInSeconds` | `number` | The rate limit frequency in seconds. | +| `externalInputPayloadStoragePath`| `string` | The path to the external input payload storage. | +| `externalOutputPayloadStoragePath`| `string` | The path to the external output payload storage. | +| `workflowPriority` | `number` | The priority of the workflow. | +| `executionNameSpace` | `string` | The execution namespace. | +| `isolationGroupId` | `string` | The isolation group ID. | +| `iteration` | `number` | The iteration number. | +| `subWorkflowId` | `string` | The ID of the sub-workflow. | +| `subworkflowChanged` | `boolean` | Whether the sub-workflow was changed. | +| `queueWaitTime` | `number` | The queue wait time. | +| `taskDefinition` | `TaskDef` | The task definition. | +| `loopOverTask` | `boolean` | Whether the task is a loop over task. | diff --git a/src/common/OPEN-API-README.md b/src/common/OPEN-API-README.md index be9dcadf..92df1ee1 100644 --- a/src/common/OPEN-API-README.md +++ b/src/common/OPEN-API-README.md @@ -1,36 +1,17 @@ The client is generated using [this library](https://github.com/ferdikoomen/openapi-typescript-codegen). -## Overrides - -To enable TLS, we have overriden some of the types and options in the generated `core` files. - -Changes are commented with `conductor-client-modification` - -## Updating definitions +1. Run the latest conductor OSS server locally +2. Run the npm commands: +#### Updating definitions To update `service` and `model` definitions: -1. Run the latest conductor OSS server locally -2. Run the npm commands - ```text npm run generateClient:models ``` -You may need to restore `open-api/ConductorClient` if there is a diff after this command. - -## Updating the core +#### Updating the core ``` npm run generateClient:core ``` - -NOTE: There will be a diff on generation and you will manually need to restore those changes. Typically, this mean restoring the client and the core. Typically that will involve something like this: - -``` -# review diff and see if there are any meaningful changes you want to keep -# If there are no changes then check out -git checkout src/common/open-api/ConductorClient.ts -git checkout src/common/open-api/core -# Otherwise, selectively check out the old parts -``` diff --git a/src/orkes/OrkesConductorClient.ts b/src/orkes/OrkesConductorClient.ts index 1e9145c7..4454b762 100644 --- a/src/orkes/OrkesConductorClient.ts +++ b/src/orkes/OrkesConductorClient.ts @@ -16,8 +16,13 @@ export const orkesConductorClient = async ( config?: Partial, customFetch?: FetchFn ) => { - const { serverUrl, keyId, keySecret, maxHttp2Connections } = - resolveOrkesConfig(config); + const { + serverUrl, + keyId, + keySecret, + maxHttp2Connections, + refreshTokenInterval, + } = resolveOrkesConfig(config); if (!serverUrl) throw new Error("Conductor server URL is not set"); @@ -32,7 +37,7 @@ export const orkesConductorClient = async ( await conductorClientWithAuth.authorize( keyId, keySecret, - config?.refreshTokenInterval || REFRESH_TOKEN_IN_MILLISECONDS + refreshTokenInterval || REFRESH_TOKEN_IN_MILLISECONDS ); } diff --git a/src/orkes/helpers/resolveOrkesConfig.ts b/src/orkes/helpers/resolveOrkesConfig.ts index bb652a59..3cbb958a 100644 --- a/src/orkes/helpers/resolveOrkesConfig.ts +++ b/src/orkes/helpers/resolveOrkesConfig.ts @@ -5,7 +5,11 @@ export const resolveOrkesConfig = (config?: Partial) => { serverUrl: process.env.CONDUCTOR_SERVER_URL || config?.serverUrl, keyId: process.env.CONDUCTOR_AUTH_KEY || config?.keyId, keySecret: process.env.CONDUCTOR_AUTH_SECRET || config?.keySecret, + refreshTokenInterval: + Number(process.env.CONDUCTOR_REFRESH_TOKEN_INTERVAL) || + config?.maxHttp2Connections, maxHttp2Connections: - Number(process.env.CONDUCTOR_MAX_HTTP2_CONNECTIONS) || config?.maxHttp2Connections, + Number(process.env.CONDUCTOR_MAX_HTTP2_CONNECTIONS) || + config?.maxHttp2Connections, }; }; diff --git a/workers_sdk.md b/workers_sdk.md deleted file mode 100644 index f37be0e3..00000000 --- a/workers_sdk.md +++ /dev/null @@ -1,174 +0,0 @@ -# Writing Workers with the Javascript SDK - -A worker is responsible for executing a task. -Operator and System tasks are handled by the Conductor server, while user defined tasks needs to have a worker created that awaits the work to be scheduled by the server for it to be executed. - -Worker framework provides features such as polling threads, metrics and server communication. - -### Design Principles for Workers - -Each worker embodies design pattern and follows certain basic principles: - -1. Workers are stateless and do not implement a workflow specific logic. -2. Each worker executes a very specific task and produces well-defined output given specific inputs. -3. Workers are meant to be idempotent (or should handle cases where the task that is partially executed gets rescheduled due to timeouts etc.) -4. Workers do not implement the logic to handle retries etc, that is taken care by the Conductor server. - -### Creating Task Workers - -Task worker is implemented using a function that confirms to the following function - -```typescript -import { ConductorWorker, Task } from "@io-orkes/conductor-javascript"; - -const worker: ConductorWorker = { - taskDefName: "task-def-name", - execute: async ( - task: Task - ): Promise> => {}, -}; -``` - -Worker returns a object as the output of the task execution. The object is just a json that follows the TaskResult interface. -If an `error` is returned, the task is marked as `FAILED` - -#### Task worker that returns an object - -```typescript -import { ConductorWorker, Task } from "@io-orkes/conductor-javascript"; - -const worker: ConductorWorker = { - taskDefName: "task-def-name", - execute: async (task: Task) => { - // Sample output - return { - outputData: { - hello: "From your worker", - }, - status: "COMPLETED", - }; - }, -}; -``` - -#### Controlling execution for long-running tasks - -For the long-running tasks you might want to spawn another process/routine and update the status of the task at a later point and complete the -execution function without actually marking the task as `COMPLETED`. Use `TaskResult` Interface that allows you to specify more fined grained control. - -Here is an example of a task execution function that returns with `IN_PROGRESS` status asking server to push the task again in 60 seconds. - -```typescript -const worker: ConductorWorker = { - taskDefName: "task-def-name", - execute: async (task: Task) => { - // Sample output - return { - outputData: {}, - status: "IN_PROGRESS", - callbackAfterSeconds: 60, - }; - }, - pollInterval: 100, // optional - concurrency: 2, // optional -}; -``` - -## Starting Workers - -`TaskRunner` interface is used to start the workers, which takes care of polling server for the work, executing worker code and updating the results back to the server. - -```typescript -import { - OrkesApiConfig, - orkesConductorClient, - TaskRunner, -} from "@io-orkes/conductor-javascript"; - -const clientPromise = orkesConductorClient({ - keyId: "XXX", // optional - keySecret: "XXXX", // optional - serverUrl: "https://play.orkes.io/api", -}); - -const client = await clientPromise; - -const taskDefName = "HelloWorldWorker"; - -const customWorker: ConductorWorker = { -taskDefName, - execute: async ({ inputData, taskId }) => { - return { - outputData: { - greeting: "Hello World", - }, - status: "COMPLETED", - }; - }, -}; -// Worker Options will take precedence over options defined in the manager - -const manager = new TaskManager(client, [customWorker], { - options: { pollInterval: 100, concurrency: 1 }, -}); - -manager.startPolling(); -// You can update all worker settings at once using -manager.updatePollingOptions({ pollInterval: 100, concurrency: 1 }); - -// You can update a single worker setting using : -manager.updatePollingOptionForWorker(taskDefName, { - pollInterval: 100, - concurrency: 1, -}); - -manager.isPolling // Will resolve to true - -await manager.stopPolling(); - -manager.isPolling // Will resolve to false - -``` - -## Task Management APIs - -### Get Task Details - -```typescript -import { - WorkflowExecutor, - TaskResultStatus, -} from "@io-orkes/conductor-javascript"; - -const clientPromise = orkesConductorClient({ - keyId: "XXX", // optional - keySecret: "XXXX", // optional - serverUrl: "https://play.orkes.io/api", -}); - -const client = await clientPromise; -const executor = new WorkflowExecutor(client); - -const taskDetails = await executor.getTask(someTaskId); -``` - -### Updating the Task result outside the worker implementation - -#### Update task by Reference Name - -```typescript -executor.updateTaskByRefName( - taskReferenceName, - workflowInstanceId, - "COMPLETED", - { some: { output: "value" } } -); -``` - -#### Update task by id - -```typescript -await executor.updateTask(taskId, executionId, "COMPLETED", newChange); -``` - -### Next: [Create and Execute Workflows](workflow_sdk.md) diff --git a/workflow_sdk.md b/workflow_sdk.md deleted file mode 100644 index 40d88c86..00000000 --- a/workflow_sdk.md +++ /dev/null @@ -1,135 +0,0 @@ -# Authoring Workflows with the Javascript SDK - -## A simple two-step workflow - -```typescript -import { - OrkesApiConfig, - orkesConductorClient, - TaskRunner, - simpleTask, -} from "@io-orkes/conductor-javascript"; - -//API client instance with server address and authentication details -const clientPromise = orkesConductorClient({ - keyId: "XXX", // optional - keySecret: "XXXX", // optional - serverUrl: "https://play.orkes.io/api", -}); - -const client = await clientPromise; - -//Create new workflow executor -const executor = new WorkflowExecutor(client); - -// Using Factory function -const factoryWf = { - name: "my_first_workflow", - version: 1, - ownerEmail: "developers@orkes.io", - tasks: [simpleTask("simple_task_ref", "simple_task", {})], - inputParameters: [], - outputParameters: {}, - timeoutSeconds: 0, -}; -const workflow = executor.registerWorkflow(true, factoryWf); -``` - -### Execute Workflow - -#### Using Workflow Executor to start previously registered workflow - -```typescript -const executor = new WorkflowExecutor(client); -const executionId = await executor.startWorkflow({ name, version, input: {} }); -``` - -#### Using Workflow Executor to execute a workflow and get the output as a result - -```typescript -import { - orkesConductorClient, - WorkflowExecutor, - ConductorClient, - TaskType, -} from "@io-orkes/conductor-javascript"; - -//API client instance with server address and authentication details -const clientPromise = orkesConductorClient({ - keyId: "XXX", // optional - keySecret: "XXXX", // optional - serverUrl: "https://play.orkes.io/api", -}); - -const client = await clientPromise; - -//Create new workflow executor -const executor = new WorkflowExecutor(client); - -// Create a workflow -const factoryWf = { - name: "my_first_workflow", - version: 1, - ownerEmail: "developers@orkes.io", - tasks: [simpleTask("simple_task_ref", "simple_task", {})], - inputParameters: [], - outputParameters: {}, - timeoutSeconds: 0, -}; - -// Register workflow -const workflow = executor.registerWorkflow(true, factoryWf); - -// Start Workflow -const executionId = await executor.startWorkflow({ - name: factoryWf.name, - version: 1, - input: {}, -}); - -// Query Workflow status -const workflowStatus = await executor.getWorkflow(executionId, true); - -// The workflow status returns the following type -export type Workflow = { - ownerApp?: string; - createTime?: number; - updateTime?: number; - createdBy?: string; - updatedBy?: string; - status?: - | "RUNNING" - | "COMPLETED" - | "FAILED" - | "TIMED_OUT" - | "TERMINATED" - | "PAUSED"; - endTime?: number; - workflowId?: string; - parentWorkflowId?: string; - parentWorkflowTaskId?: string; - tasks?: Array; - input?: Record; - output?: Record; - correlationId?: string; - reRunFromWorkflowId?: string; - reasonForIncompletion?: string; - event?: string; - taskToDomain?: Record; - failedReferenceTaskNames?: Array; - workflowDefinition?: WorkflowDef; - externalInputPayloadStoragePath?: string; - externalOutputPayloadStoragePath?: string; - priority?: number; - variables?: Record; - lastRetriedTime?: number; - startTime?: number; - workflowVersion?: number; - workflowName?: string; -}; -``` - -### More Examples - -You can find more examples at the following GitHub repository: -https://github.com/conductor-sdk/javascript-sdk-examples