Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Prepare Azure environments for new workloads—subscriptions, networking, identity, and landing zones
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/services/durable-task-scheduler/javascript.md
1# Durable Task Scheduler — JavaScript23## Learn More45- [Durable Task Scheduler documentation](https://learn.microsoft.com/azure/durable-task-scheduler/)6- [Durable Functions JavaScript guide](https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview?tabs=javascript)78## Durable Functions Setup910### Required npm Packages1112```json13{14"dependencies": {15"@azure/functions": "^4.0.0",16"durable-functions": "^3.0.0"17}18}19```2021> **💡 Finding latest versions**: Run `npm view durable-functions version` or check [npmjs.com/package/durable-functions](https://www.npmjs.com/package/durable-functions) for the latest stable release.2223### host.json2425```json26{27"version": "2.0",28"extensions": {29"durableTask": {30"hubName": "default",31"storageProvider": {32"type": "durabletask-scheduler",33"connectionStringName": "DURABLE_TASK_SCHEDULER_CONNECTION_STRING"34}35}36},37"extensionBundle": {38"id": "Microsoft.Azure.Functions.ExtensionBundle",39"version": "[4.*, 5.0.0)"40}41}42```4344### local.settings.json4546```json47{48"IsEncrypted": false,49"Values": {50"FUNCTIONS_WORKER_RUNTIME": "node",51"AzureWebJobsStorage": "UseDevelopmentStorage=true",52"DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None"53}54}55```5657## Minimal Example5859```javascript60const { app } = require("@azure/functions");61const df = require("durable-functions");6263// Activity64df.app.activity("sayHello", {65handler: (city) => `Hello ${city}!`,66});6768// Orchestrator69df.app.orchestration("myOrchestration", function* (context) {70const result1 = yield context.df.callActivity("sayHello", "Tokyo");71const result2 = yield context.df.callActivity("sayHello", "Seattle");72return `${result1}, ${result2}`;73});7475// HTTP Starter76app.http("HttpStart", {77route: "orchestrators/{orchestrationName}",78methods: ["POST"],79authLevel: "function",80extraInputs: [df.input.durableClient()],81handler: async (request, context) => {82const client = df.getClient(context);83const instanceId = await client.startNew(request.params.orchestrationName);84return client.createCheckStatusResponse(request, instanceId);85},86});87```8889## Workflow Patterns9091### Fan-Out/Fan-In9293```javascript94df.app.orchestration("fanOutFanIn", function* (context) {95const cities = ["Tokyo", "Seattle", "London", "Paris", "Berlin"];9697// Fan-out: schedule all activities in parallel98const tasks = cities.map((city) => context.df.callActivity("sayHello", city));99100// Fan-in: wait for all to complete101const results = yield context.df.Task.all(tasks);102return results;103});104```105106### Human Interaction107108```javascript109df.app.orchestration("approvalWorkflow", function* (context) {110yield context.df.callActivity("sendApprovalRequest", context.df.getInput());111112// Wait for approval event with timeout113const expiration = new Date(context.df.currentUtcDateTime);114expiration.setDate(expiration.getDate() + 3);115116const approvalTask = context.df.waitForExternalEvent("ApprovalEvent");117const timeoutTask = context.df.createTimer(expiration);118119const winner = yield context.df.Task.any([approvalTask, timeoutTask]);120121if (winner === approvalTask) {122return approvalTask.result ? "Approved" : "Rejected";123}124return "Timed out";125});126```127128## Orchestration Determinism129130| ❌ NEVER | ✅ ALWAYS USE |131|----------|--------------|132| `new Date()` | `context.df.currentUtcDateTime` |133| `Math.random()` | Pass random values from activities |134| `setTimeout()` | `context.df.createTimer()` |135| Direct I/O, HTTP, database | `context.df.callActivity()` |136137### Replay-Safe Logging138139```javascript140df.app.orchestration("myOrchestration", function* (context) {141if (!context.df.isReplaying) {142console.log("Started"); // Only logs once, not on replay143}144const result = yield context.df.callActivity("myActivity", "input");145return result;146});147```148149## Error Handling & Retry150151```javascript152df.app.orchestration("workflowWithRetry", function* (context) {153const retryOptions = new df.RetryOptions(5000, 3); // firstRetryInterval, maxAttempts154retryOptions.backoffCoefficient = 2.0;155retryOptions.maxRetryIntervalInMilliseconds = 60000;156157try {158const result = yield context.df.callActivityWithRetry(159"unreliableService",160retryOptions,161context.df.getInput()162);163return result;164} catch (ex) {165context.df.setCustomStatus({ error: ex.message });166yield context.df.callActivity("compensationActivity", context.df.getInput());167return "Compensated";168}169});170```171172## Durable Task SDK (Non-Functions)173174For applications running outside Azure Functions (containers, VMs, Azure Container Apps, Azure Kubernetes Service):175176```javascript177const { createAzureManagedWorkerBuilder, createAzureManagedClient } = require("@microsoft/durabletask-js-azuremanaged");178179const connectionString = "Endpoint=http://localhost:8080;Authentication=None;TaskHub=default";180181// Activity182const sayHello = async (_ctx, name) => `Hello ${name}!`;183184// Orchestrator185const myOrchestration = async function* (ctx, name) {186const result = yield ctx.callActivity(sayHello, name);187return result;188};189190async function main() {191// Worker192const worker = createAzureManagedWorkerBuilder(connectionString)193.addOrchestrator(myOrchestration)194.addActivity(sayHello)195.build();196197await worker.start();198199// Client200const client = createAzureManagedClient(connectionString);201const instanceId = await client.scheduleNewOrchestration("myOrchestration", "World");202const state = await client.waitForOrchestrationCompletion(instanceId, true, 30);203console.log("Output:", state.serializedOutput);204205await client.stop();206await worker.stop();207}208209main().catch(console.error);210```211212