Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
c342a89
Initial plan
Copilot Jan 20, 2026
b3b5a40
Add Durable Task Scheduler support for Azure-managed orchestration
Copilot Jan 20, 2026
8ad77cd
Improve type safety in scheduler module based on code review
Copilot Jan 20, 2026
1a727d8
Rename scheduler to azuremanaged and move to separate npm package
Copilot Jan 21, 2026
1e79da0
Exclude packages from root jest configuration
Copilot Jan 21, 2026
79d0d30
Fix grammar in error messages for connection string validation
Copilot Jan 21, 2026
e8edf4b
Rename packages to extensions and update package name to durabletask-…
Copilot Jan 21, 2026
7823521
Fix typo in jest.config.js comment
Copilot Jan 21, 2026
5905636
Add .npmignore to exclude extensions folder from main package
Copilot Jan 21, 2026
ca517d4
save
YunchuWang Jan 21, 2026
f953166
same eslint
YunchuWang Jan 21, 2026
8ad398c
save
YunchuWang Jan 22, 2026
4877a34
workerid
YunchuWang Jan 22, 2026
7bbcb5e
save
YunchuWang Jan 22, 2026
676d25e
save
YunchuWang Jan 22, 2026
feac6f9
save
YunchuWang Jan 22, 2026
0426630
save
YunchuWang Jan 22, 2026
5523d00
save
YunchuWang Jan 22, 2026
79ee784
save
YunchuWang Jan 22, 2026
77a5d32
align clientretryoptions
YunchuWang Jan 22, 2026
fb3a468
add code ref
YunchuWang Jan 22, 2026
22381a4
test sample
YunchuWang Jan 22, 2026
422c39c
Merge branch 'main' of https://github.com/microsoft/durabletask-js in…
YunchuWang Jan 22, 2026
b3b0105
save
YunchuWang Jan 22, 2026
ca901ac
fix incorrect grpc gen script
YunchuWang Jan 22, 2026
bb357c4
save
YunchuWang Jan 22, 2026
ed357b4
add completion token
YunchuWang Jan 22, 2026
5857ea4
update sample
YunchuWang Jan 22, 2026
cb763d9
use default messagesize
YunchuWang Jan 22, 2026
4995519
make output folder consistent
YunchuWang Jan 22, 2026
8bd1ed8
use files instead of npmignore for cleaner packaging
YunchuWang Jan 23, 2026
017e839
multipackage workspace layout
YunchuWang Jan 23, 2026
8cca56c
cleanup
YunchuWang Jan 23, 2026
f13f7c7
update pr ci
YunchuWang Jan 23, 2026
b14e95a
fix e2e tests
YunchuWang Jan 23, 2026
0048b8b
fix codeql
YunchuWang Jan 23, 2026
b7ee967
codeql
YunchuWang Jan 23, 2026
9327d09
step 1
YunchuWang Jan 26, 2026
ba31622
add to json
YunchuWang Jan 26, 2026
b4a38f9
step 2
YunchuWang Jan 26, 2026
a9d5acf
step 3
YunchuWang Jan 26, 2026
ba6e062
step 4
YunchuWang Jan 27, 2026
3dcc52c
step 5
YunchuWang Jan 27, 2026
55e52d1
step 6
YunchuWang Jan 27, 2026
e5d9754
step 7
YunchuWang Jan 27, 2026
5a8a4f3
step 8
YunchuWang Jan 27, 2026
6d4d6cf
step 10
YunchuWang Jan 27, 2026
a50a281
step 11
YunchuWang Jan 28, 2026
225d12e
add sample/update readme
YunchuWang Jan 28, 2026
e5499e3
Merge branch 'main' of https://github.com/microsoft/durabletask-js in…
YunchuWang Jan 28, 2026
c46fded
Merge branch 'main' of https://github.com/microsoft/durabletask-js in…
YunchuWang Jan 28, 2026
a94d177
cleanup
YunchuWang Jan 28, 2026
7dd8222
fix import
YunchuWang Jan 28, 2026
782a342
cleanup
YunchuWang Jan 28, 2026
018e20a
linting
YunchuWang Jan 28, 2026
ab5604c
cleanup
YunchuWang Jan 28, 2026
97b2a10
save
YunchuWang Jan 29, 2026
7526f6c
save
YunchuWang Jan 29, 2026
67a6239
test fix
YunchuWang Jan 29, 2026
600b386
more entity e2e tests
YunchuWang Jan 29, 2026
0e2edb3
locking tests
YunchuWang Jan 29, 2026
c406c12
more tests
YunchuWang Jan 29, 2026
97c34e6
linting
YunchuWang Jan 29, 2026
2e01158
test supporting real dts
YunchuWang Jan 29, 2026
2da8a06
cleanup
YunchuWang Jan 29, 2026
54b9183
test update
YunchuWang Jan 29, 2026
5570512
getentities advanced async page iteration
YunchuWang Jan 29, 2026
026b7b7
set parentexecutionid when callentity
YunchuWang Jan 29, 2026
4f1f2b3
failure test
YunchuWang Jan 29, 2026
cd27ac4
remove commitactions
YunchuWang Jan 30, 2026
4363151
fix unittest
YunchuWang Jan 30, 2026
3fb9198
Update examples/hello-world/entity-counter.ts
YunchuWang Jan 30, 2026
b0c1eb0
Restructure entity examples as standalone apps with DTS emulator supp…
Copilot Feb 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,3 @@ jobs:
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

category: "/language:${{matrix.language}}"
145 changes: 145 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,34 @@ const orchestrator: TOrchestrator = async function* (ctx: OrchestrationContext,
As an aside, you'll also notice that the example orchestration above works with custom business objects. Support for custom business objects includes support for custom classes, custom data classes, and named tuples. Serialization and deserialization of these objects is handled automatically by the SDK.

You can find the full sample [here](./examples/human_interaction.ts).
### Durable Entities (Stateful Actors)

Durable entities provide a way to manage small pieces of state with a simple object-oriented programming model:

```typescript
import { TaskEntity, EntityInstanceId } from "durabletask-js";

// Define an entity by extending TaskEntity
class CounterEntity extends TaskEntity<{ value: number }> {
add(amount: number): number {
this.state.value += amount;
return this.state.value;
}

protected initializeState() {
return { value: 0 };
}
}

// From an orchestration, call the entity
const orchestrator: TOrchestrator = async function* (ctx: OrchestrationContext): any {
const entityId = new EntityInstanceId("Counter", "myCounter");
const value: number = yield* ctx.entities.callEntity(entityId, "add", 5);
return value;
};
```

You can find full entity samples [here](./examples/hello-world/entity-counter.ts) and [here](./examples/hello-world/entity-orchestration.ts).
## Feature overview

The following features are currently supported:
Expand Down Expand Up @@ -122,6 +149,10 @@ Orchestrations can wait for external events using the `wait_for_external_event`

Orchestrations can be continued as new using the `continue_as_new` API. This API allows an orchestration to restart itself from scratch, optionally with a new input.

### Durable Entities

Durable entities are stateful objects that can be accessed from orchestrations or directly from clients. They support operations that can read/modify state, and multiple entities can be locked together for atomic cross-entity transactions. See the detailed section below for more information.

### Suspend, resume, and terminate

Orchestrations can be suspended using the `suspend_orchestration` client API and will remain suspended until resumed using the `resume_orchestration` client API. A suspended orchestration will stop processing new events, but will continue to buffer any that happen to arrive until resumed, ensuring that no data is lost. An orchestration can also be terminated using the `terminate_orchestration` client API. Terminated orchestrations will stop processing new events and will discard any buffered events.
Expand All @@ -130,6 +161,120 @@ Orchestrations can be suspended using the `suspend_orchestration` client API and

Orchestrations can specify retry policies for activities and sub-orchestrations. These policies control how many times and how frequently an activity or sub-orchestration will be retried in the event of a transient error.

### Durable Entities

Durable entities are stateful objects that can be accessed and manipulated from orchestrations or directly from clients. Entities provide a way to manage small pieces of state that need to be accessed and updated reliably.

#### Defining an Entity

Entities are defined by extending the `TaskEntity` class:

```typescript
import { TaskEntity } from "durabletask-js";

interface CounterState {
value: number;
}

class CounterEntity extends TaskEntity<CounterState> {
// Operations are just methods on the class
add(amount: number): number {
this.state.value += amount;
return this.state.value;
}

get(): number {
return this.state.value;
}

reset(): void {
this.state.value = 0;
}

// Required: Initialize the entity state
protected initializeState(): CounterState {
return { value: 0 };
}
}

// Register with the worker
worker.addEntity("Counter", () => new CounterEntity());
```

#### Accessing Entities from a Client

Entities can be signaled (fire-and-forget) or queried from a client:

```typescript
import { TaskHubGrpcClient, EntityInstanceId } from "durabletask-js";

const client = new TaskHubGrpcClient("localhost:4001");
const entityId = new EntityInstanceId("Counter", "myCounter");

// Signal an operation (fire-and-forget)
await client.signalEntity(entityId, "add", 5);

// Get the entity state
const response = await client.getEntity<CounterState>(entityId);
console.log(`Current value: ${response.state?.value}`);
```

#### Calling Entities from Orchestrations

Orchestrations can call entities and wait for results:

```typescript
const orchestrator: TOrchestrator = async function* (ctx: OrchestrationContext): any {
const entityId = new EntityInstanceId("Counter", "myCounter");

// Call entity and wait for result
const currentValue: number = yield* ctx.entities.callEntity(entityId, "get");

// Signal entity (fire-and-forget)
ctx.entities.signalEntity(entityId, "add", 10);

return currentValue;
};
```

#### Entity Locking (Critical Sections)

Multiple entities can be locked together for atomic operations:

```typescript
const transferOrchestration: TOrchestrator = async function* (
ctx: OrchestrationContext,
input: { from: string; to: string; amount: number }
): any {
const fromEntity = new EntityInstanceId("Account", input.from);
const toEntity = new EntityInstanceId("Account", input.to);

// Lock both entities atomically (sorted to prevent deadlocks)
const lock = yield* ctx.entities.lockEntities(fromEntity, toEntity);

try {
const fromBalance: number = yield* ctx.entities.callEntity(fromEntity, "getBalance");
if (fromBalance >= input.amount) {
yield* ctx.entities.callEntity(fromEntity, "withdraw", input.amount);
yield* ctx.entities.callEntity(toEntity, "deposit", input.amount);
}
} finally {
lock.release();
}
};
```

#### Entity Management

Clean up empty or unused entities:

```typescript
// Clean up entities that have been empty for 30 days
await client.cleanEntityStorage({ removeEmptyEntities: true });
```

You can find full entity examples [here](./examples/hello-world/entity-counter.ts) and [here](./examples/hello-world/entity-orchestration.ts).

## Getting Started

### Prerequisites
Expand Down
133 changes: 133 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Durable Task JavaScript SDK - Examples

This directory contains examples demonstrating various features of the Durable Task JavaScript SDK.

## Example Applications

Each example is a standalone application with its own README and can be run independently.

### Basic Orchestration Examples

Located in `hello-world/`:

- **[Activity Sequence](./hello-world/activity-sequence.ts)**: Basic orchestration that calls three activities in sequence.
- **[Fan-out/Fan-in](./hello-world/fanout-fanin.ts)**: Orchestration that schedules multiple activities in parallel and aggregates results.
- **[Human Interaction](./hello-world/human_interaction.ts)**: Demonstrates waiting for external events in orchestrations.

### Durable Entities Examples

Durable Entities are stateful objects with built-in concurrency control:

- **[Entity Counter](./entity-counter/)**: Simple counter entity demonstrating basic entity operations, signaling, and state management.
- **[Entity Orchestration](./entity-orchestration/)**: Bank transfer scenario using entity locking for atomic cross-entity operations.

### Azure Integration Examples

- **[Azure Managed DTS](./azure-managed/)**: Integration with Azure Managed Durable Task Scheduler using Azure authentication.
- **[Azure Managed DTS (Simple)](./azure-managed-dts.ts)**: Simplified version showing Azure DTS connection setup.

## Prerequisites

Examples require a Durable Task-compatible backend. Choose one:

### Option 1: DTS Emulator (Recommended for Testing)

The DTS Emulator is ideal for local development and testing:

```bash
docker run --name dts-emulator -i -p 8080:8080 -d --rm mcr.microsoft.com/dts/dts-emulator:latest
```

Most standalone examples can run against the emulator using:

```bash
cd examples/entity-counter
npm run start:emulator
```

### Option 2: Local Sidecar

Install and run locally (requires Go 1.18+):

```bash
# Install Dapr CLI (includes Durable Task sidecar)
https://docs.dapr.io/getting-started/install-dapr-cli/

# Or build from source
git clone https://github.com/microsoft/durabletask-go
cd durabletask-go
go run . start --backend Emulator
```

The sidecar runs on `localhost:4001` by default.

### Option 3: Unofficial Sidecar Docker Image

For quick local development:

```bash
docker run \
--name durabletask-sidecar -d --rm \
-p 4001:4001 \
--env 'DURABLETASK_SIDECAR_LOGLEVEL=Debug' \
kaibocai/durabletask-sidecar:latest start \
--backend Emulator
```

## Running Examples

### Standalone Applications (Recommended)

Standalone applications include `entity-counter` and `entity-orchestration`. Each has its own `package.json`:

```bash
cd examples/entity-counter
npm run start:emulator # Run against DTS emulator
# OR
npm run start # Run against local sidecar on localhost:4001
```

See individual README files for detailed instructions.

### Single-File Examples

Basic orchestration examples in `hello-world/` can be run directly:

```bash
npm run example ./examples/hello-world/activity-sequence.ts
```

## Testing Against DTS Emulator

All entity examples are designed to work with the DTS emulator:

1. Start the DTS emulator:
```bash
docker run --name dts-emulator -i -p 8080:8080 -d --rm mcr.microsoft.com/dts/dts-emulator:latest
```

2. Run the example:
```bash
cd examples/entity-counter
npm run start:emulator
```

The emulator provides a clean, isolated environment for testing without requiring external dependencies.

## Azure Managed DTS

For production scenarios with Azure, see the [Azure Managed DTS example](./azure-managed/) which demonstrates:
- Connection string configuration
- Azure authentication with DefaultAzureCredential
- Environment-based configuration

## Documentation

For more information about Durable Task concepts:

- **Orchestrations**: Workflow definitions that coordinate activities
- **Activities**: Units of work executed by orchestrations
- **Entities**: Stateful actors with automatic concurrency control
- **Entity Locking**: Critical sections for atomic multi-entity operations

See the main [README](../README.md) for comprehensive documentation.
Loading