INTEGRITY Документация

API Workers

В этом руководстве подробно описан Workflows API в составе Cloudflare Workers, включая методы, типы и примеры использования.

WorkflowEntrypoint

WorkflowEntrypoint класс является основным элементом определения Workflow. Workflow должен расширять этот класс и определять run метод как минимум с одним step вызов, чтобы Workflow считался действительным.

export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
	async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
		// Steps here
	}
}

запустить

run метод может по желанию возвращать данные, которые доступны при запросе статуса инстанса через API Workers, REST API и панели управления Workflows. Это может быть полезно, если ваш Workflow вычисляет результат, возвращает ключ к данным, хранящимся в объектном хранилище, или создаёт какой-либо идентификатор, с которым вам нужно будет работать.

export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
	async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
		// Steps here
		let someComputedState = await step.do("my step", async () => {});

		// Optional: return state from our run() method
		return someComputedState;
	}
}

WorkflowEvent тип принимает необязательный параметр типа ↗ который позволяет указать тип для payload свойство внутри WorkflowEvent.

См. события и параметры документацию о том, как обрабатывать события в коде Workflow.

Наконец, любые примитивы управления потоком выполнения JS (условия if, циклы, try...catch блоки, Promise и другое) можно использовать для управления шагами внутри run метод.

WorkflowEvent

export type WorkflowCronSchedule = {
	/** Cron expression that triggered this event. */
	cron: string;
	/** Timestamp of the scheduled trigger, in milliseconds since the Unix epoch. */
	scheduledTime: number;
};

export type WorkflowEvent<T> = {
	payload: Readonly<T>;
	timestamp: Date;
	instanceId: string;
	workflowName: string;
	schedule?: WorkflowCronSchedule;
};

См. события и параметры документацию о том, как обрабатывать события в коде Workflow.

WorkflowStep

шаг

После ReadableStream<Uint8Array> объект был сохранён в рамках шага, его не следует использовать повторно: полагайтесь на новый поток, возвращаемый шагом. Байты сохраняются из исходного потока, но реализация может отличаться.

:::

export class MyWorkflow extends WorkflowEntrypoint {
	async run(_event, step) {
		const reportStream = await step.do("read report from R2", async () => {
			const object = await this.env.MY_BUCKET.get("reports/latest.csv");

			if (!object?.body) {
				throw new Error("Could not read reports/latest.csv from R2.");
			}

			return object.body;
		});

		const preview = await new Response(reportStream).text();
		return { preview };
	}
}
type Env = {
	MY_BUCKET: R2Bucket;
};

export class MyWorkflow extends WorkflowEntrypoint<Env> {
	async run(_event: WorkflowEvent<unknown>, step: WorkflowStep) {
		const reportStream = await step.do("read report from R2", async () => {
			const object = await this.env.MY_BUCKET.get("reports/latest.csv");

			if (!object?.body) {
				throw new Error("Could not read reports/latest.csv from R2.");
			}

			return object.body;
		});

		const preview = await new Response(reportStream).text();
		return { preview };
	}
}
export class MyWorkflow extends WorkflowEntrypoint {
	async run(event, step) {
		// Other steps in your Workflow
		let stripeEvent = await step.waitForEvent(
			"receive invoice paid webhook from Stripe",
			{ type: "stripe-webhook", timeout: "1 hour" },
		);
		// Rest of your Workflow
	}
}
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
	async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
		// Other steps in your Workflow
		let stripeEvent = await step.waitForEvent<IncomingStripeWebhook>(
			"receive invoice paid webhook from Stripe",
			{ type: "stripe-webhook", timeout: "1 hour" },
		);
		// Rest of your Workflow
	}
}

Ознакомьтесь с документацией по события и параметры чтобы узнать, как отправлять события запущенному экземпляру Workflow.

WorkflowStepConfig

export type WorkflowDynamicDelayContext = {
	ctx: WorkflowStepContext;
	error: Error;
};

export type WorkflowDelayFunction = (
	input: WorkflowDynamicDelayContext,
) => string | number | Promise<string | number>;

export type WorkflowStepConfig = {
	retries?: {
		limit: number;
		delay: string | number | WorkflowDelayFunction;
		backoff?: WorkflowBackoff;
	};
	timeout?: string | number;
};

См. документация о паузах и повторных попытках чтобы узнать больше о том, как выполняются повторные попытки для Workflows.

Параметры отката

type WorkflowRollbackContext<T = unknown> = {
	ctx: WorkflowStepContext;
	error: Error;
	output: T | undefined;
};

type WorkflowRollbackHandler<T = unknown> = (
	ctx: WorkflowRollbackContext<T>,
) => Promise<void>;

type WorkflowStepRollbackConfig = Pick<
	WorkflowStepConfig,
	"retries" | "timeout"
>;

type WorkflowStepRollbackOptions<T = unknown> = {
	rollback: WorkflowRollbackHandler<T>;
	rollbackConfig?: WorkflowStepRollbackConfig;
};
export class BillingWorkflow extends WorkflowEntrypoint {
	async run(_event, step) {
		await step.do(
			"create charge",
			async () => {
				const charge = await createCharge();
				return { chargeId: charge.id };
			},
			{
				rollback: async ({ ctx, output, error }) => {
					const { chargeId } = output;
					await refundCharge(chargeId, {
						reason: `${ctx.step.name}: ${error.message}`,
					});
				},
				rollbackConfig: {
					retries: {
						limit: 3,
						delay: "30 seconds",
						backoff: "linear",
					},
					timeout: "5 minutes",
				},
			},
		);
	}
}
export class BillingWorkflow extends WorkflowEntrypoint<Env> {
	async run(_event: WorkflowEvent<unknown>, step: WorkflowStep) {
		await step.do(
			"create charge",
			async () => {
				const charge = await createCharge();
				return { chargeId: charge.id };
			},
			{
				rollback: async ({ ctx, output, error }) => {
					const { chargeId } = output as { chargeId: string };
					await refundCharge(chargeId, {
						reason: `${ctx.step.name}: ${error.message}`,
					});
				},
				rollbackConfig: {
					retries: {
						limit: 3,
						delay: "30 seconds",
						backoff: "linear",
					},
					timeout: "5 minutes",
				},
			},
		);
	}
}

WorkflowStepContext

export type WorkflowStepContext = {
	step: {
		name: string;
		count: number;
	};
	attempt: number;
	config: WorkflowStepConfig;
};

См. документация по контексту шага для примеров использования.

Лимиты шагов Workflow

Каждый Workflow на тарифе Workers Paid по умолчанию поддерживает 10,000 шагов. Вы можете увеличить это значение до 25,000 шагов, настроив steps в пределах limits свойство в определении вашего Workflow в конфигурации Wrangler:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "workflows": [
    {
      "name": "my-workflow",
      "binding": "MY_WORKFLOW",
      "class_name": "MyWorkflow",
      "limits": {
        "steps": 25000
      }
    }
  ]
}
[[workflows]]
name = "my-workflow"
binding = "MY_WORKFLOW"
class_name = "MyWorkflow"

[workflows.limits]
steps = 25_000

step.sleep не учитывается при подсчёте максимального количества шагов.

Обратите внимание: в тарифе Workers Free Workflows ограничены 1024 шагами. См. Лимиты Workflow, где это описано подробнее.

NonRetryableError

Вызов Workflows из Workers

Workflows предоставляет API непосредственно вашим скриптам Workers через привязки концепция. Привязки позволяют безопасно вызывать Workflow без необходимости управлять API-ключами или клиентами.

Вы можете привязаться к Workflow, определив [[workflows]] привязка в конфигурации Wrangler.

Например, чтобы привязаться к Workflow с именем workflows-starter и сделать его доступным на MY_WORKFLOW переменную в скрипт Worker, настройте следующие поля в [[workflows]] определение привязки:

{
	"$schema": "./node_modules/wrangler/config-schema.json",
	"name": "workflows-starter",
	"main": "src/index.ts",
	// Set this to today's date
	"compatibility_date": "2026-08-28",
	"workflows": [
		{
			// name of your workflow
			"name": "workflows-starter",
			// binding name env.MY_WORKFLOW
			"binding": "MY_WORKFLOW",
			// this is class that extends the Workflow class in src/index.ts
			"class_name": "MyWorkflow",
		},
	],
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "workflows-starter"
main = "src/index.ts"
# Set this to today's date
compatibility_date = "2026-08-28"

[[workflows]]
name = "workflows-starter"
binding = "MY_WORKFLOW"
class_name = "MyWorkflow"

Привязка из Pages

Вы можете привязывать и запускать Workflows из Pages Functions путём развёртывания проекта Workers с определением вашего Workflow, а затем вызова этого Worker с помощью привязки к сервисам или стандартный fetch() вызов.

См. документацию по вызов Workflows из Pages с примерами.

Межскриптовые вызовы

Вы также можете привязаться к Workflow, определённому в другом скрипте Worker, а не в том, где находится определение вашего Workflow. Для этого укажите script_name ключ с именем скрипта в [[workflows]] определение привязки в конфигурации Wrangler.

Например, если ваш Workflow определён в скрипте Worker с именем billing-worker, но вы вызываете её из своего web-api-worker скрипт, ваш конфигурационный файл Wrangler будет выглядеть следующим образом:

{
	"$schema": "./node_modules/wrangler/config-schema.json",
	"name": "web-api-worker",
	"main": "src/index.ts",
	// Set this to today's date
	"compatibility_date": "2026-08-28",
	"workflows": [
		{
			// name of your workflow
			"name": "billing-workflow",
			// binding name env.MY_WORKFLOW
			"binding": "MY_WORKFLOW",
			// this is class that extends the Workflow class in src/index.ts
			"class_name": "MyWorkflow",
			// the script name where the Workflow is defined.
			// required if the Workflow is defined in another script.
			"script_name": "billing-worker",
		},
	],
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "web-api-worker"
main = "src/index.ts"
# Set this to today's date
compatibility_date = "2026-08-28"

[[workflows]]
name = "billing-workflow"
binding = "MY_WORKFLOW"
class_name = "MyWorkflow"
script_name = "billing-worker"

Если вы используете TypeScript, выполните wrangler types каждый раз, когда вы изменяете файл конфигурации Wrangler. Это генерирует типы для env объект на основе ваших привязок, а также типы среды выполнения.

Workflow

Workflow тип предоставляет методы для создания, проверки статуса и управления запущенными экземплярами Workflow из скрипта Worker. Он входит в состав типов, генерируемых wrangler types.

./worker-configuration.d.ts
interface Env {
	// The 'MY_WORKFLOW' variable should match the "binding" value set in the Wrangler config file
	MY_WORKFLOW: Workflow;
}

Workflow тип экспортирует следующие методы:

создать

Создайте (запустите) новый экземпляр заданного Workflow.

ID создается автоматически, но можно указать собственный ID (до 100 символов 1). Это может быть полезно при сопоставлении Workflows с пользователями, продавцами или другими идентификаторами в вашей системе. Вы также можете передать объект JSON в качестве params свойство, позволяющее передать данные, с которыми экземпляр Workflow будет работать как со своим WorkflowEvent.

// Create a new Workflow instance with your own ID and pass params to the Workflow instance
let instance = await env.MY_WORKFLOW.create({
	id: myIdDefinedFromOtherSystem,
	params: { hello: "world" },
});
return Response.json({
	id: instance.id,
	details: await instance.status(),
});

Возвращает WorkflowInstance.

Выдаёт ошибку, если указанный ID уже используется существующим экземпляром, который ещё не прошёл свой лимит хранения. Чтобы повторно запустить workflow с тем же ID, можно restart существующий экземпляр.

Вы также можете указать параметр type для Workflows тип при создании (запуске) экземпляра Workflow с помощью create метод объекта API Workers. Обратите внимание, что это не передать информацию о типах в сам Workflow, поскольку типы TypeScript существуют только на этапе сборки.

Чтобы указать необязательный параметр типа для Workflow, передайте аргумент типа вместе с вашим типом при определении привязок Workflow:

interface User {
	email: string;
	createdTimestamp: number;
}

interface Env {
	// Pass our User type as the type parameter to the Workflow definition
  MY_WORKFLOW: Workflow<User>;
}

export default {
	async fetch(request, env, ctx) {
		// More likely to come from your database or via the request body!
		const user: User = {
			email: [email protected],
			createdTimestamp: Date.now()
		}

		let instance = await env.MY_WORKFLOW.create({
			// params expects the type User
			params: user
		})

		return Response.json({
			id: instance.id,
			details: await instance.status(),
		});
	}
}

createBatch

Создайте (запустите) пакет новых экземпляров заданного Workflow, до 100 экземпляров за раз.

Это полезно, когда вы планируете сразу несколько экземпляров. Вызов createBatch обрабатывается так же, как вызов create (для одного экземпляра) и позволяет работать в пределах лимит создания экземпляров.

Каждый элемент массива batch список должен включать как id и params свойства:

// Create a new batch of 3 Workflow instances, each with its own ID and pass params to the Workflow instances
const listOfInstances = [
	{ id: "id-abc123", params: { hello: "world-0" } },
	{ id: "id-def456", params: { hello: "world-1" } },
	{ id: "id-ghi789", params: { hello: "world-2" } },
];
let instances = await env.MY_WORKFLOW.createBatch(listOfInstances);

Возвращает массив WorkflowInstance.

В отличие от create, эта операция идемпотентна и не завершится ошибкой, если ID уже используется. Если существующий экземпляр с тем же ID всё ещё находится в своём лимит хранения, он будет пропущен и не войдёт в возвращаемый массив.

get

Получить конкретный экземпляр Workflow по ID.

Возвращает WorkflowInstance. Выдает исключение, если экземпляр с указанным ID не существует.

// Fetch an existing Workflow instance by ID:
try {
	let instance = await env.MY_WORKFLOW.get(id);
	return Response.json({
		id: instance.id,
		details: await instance.status(),
	});
} catch (e: any) {
	// Handle errors
	// .get will throw an exception if the ID doesn't exist or is invalid.
	const msg = `failed to get instance ${id}: ${e.message}`;
	console.error(msg);
	return Response.json({ error: msg }, { status: 400 });
}

WorkflowInstanceCreateOptions

Необязательные свойства, которые можно передать при создании экземпляра.

interface WorkflowInstanceCreateOptions {
	/**
	 * An id for your Workflow instance. Must be unique within the Workflow.
	 */
	id?: string;
	/**
	 * The event payload the Workflow instance is triggered with
	 */
	params?: unknown;
	/**
	 * The retention policy for the Workflow instance.
	 * Defaults to the maximum retention period available for the owner's account.
	 */
	retention?: {
		/**
		 * How long to retain instance state after the Workflow completes successfully.
		 */
		successRetention?: WorkflowRetentionDuration;
		/**
		 * How long to retain instance state after the Workflow ends in an errored or terminated state.
		 */
		errorRetention?: WorkflowRetentionDuration;
	};
}

type WorkflowRetentionDuration = WorkflowSleepDuration;

Если retention не задан, состояние инстанса сохраняется в течение максимального периода хранения, доступного на вашем аккаунте (3 дня на плане Workers Free, 30 дней на плане Workers Paid). См. лимит хранения, где это описано подробнее.

В следующем примере создаётся экземпляр, который сохраняет состояние 1 день после успешного завершения и 7 дней после ошибки:

let instance = await env.MY_WORKFLOW.create({
	id: myIdDefinedFromOtherSystem,
	params: { hello: "world" },
	retention: {
		successRetention: "1 day",
		errorRetention: "7 days",
	},
});

WorkflowInstance

Представляет конкретный экземпляр Workflow и предоставляет методы для управления этим экземпляром.

declare abstract class WorkflowInstance {
	public id: string;
	/**
	 * Pause the instance.
	 */
	public pause(): Promise<void>;
	/**
	 * Resume the instance. If it is already running, an error will be thrown.
	 */
	public resume(): Promise<void>;
	/**
	 * Terminate the instance. If it is errored, terminated or complete, an error will be thrown.
	 */
	public terminate(options?: WorkflowInstanceTerminateOptions): Promise<void>;
	/**
	 * Restart the instance from the beginning, or from a specific step.
	 */
	public restart(options?: WorkflowInstanceRestartOptions): Promise<void>;
	/**
	 * Returns the current status of the instance.
	 */
	public status(): Promise<InstanceStatus>;
}

id

Вернуть ID Workflow.

статус

Вернуть статус выполняющегося экземпляра Workflow.

приостановить

Приостановите выполняющийся экземпляр Workflow.

возобновить

Возобновите приостановленный экземпляр Workflow.

перезапустить

Перезапустите экземпляр Workflow с самого начала или с определенного шага.

let instance = await env.MY_WORKFLOW.get("abc-123");

// Restart the instance from the beginning.
await instance.restart();

// Restart the instance from the step named "aggregate".
await instance.restart({ from: { name: "aggregate" } });

// Restart the instance from the third call to a step named "process".
await instance.restart({ from: { name: "process", count: 3 } });

При перезапуске с определённого шага результаты всех предыдущих шагов, сохранённые в кэше, используются повторно, а целевой шаг и все последующие шаги выполняются снова. Вызов завершается ошибкой, если не найден шаг, соответствующий from обнаруживается в истории выполнения инстанса.

WorkflowInstanceRestartOptions

interface WorkflowInstanceRestartOptions {
	/**
	 * The step to restart the instance from.
	 * If omitted, the instance restarts from the beginning.
	 */
	from?: {
		/**
		 * The name of the step.
		 */
		name: string;
		/**
		 * The 1-based index of the step, used when multiple steps share the same name and type. Defaults to 1 (the first occurrence).
		 */
		count?: number;
		/**
		 * The step type. Use this to disambiguate when the same name is shared across step types. Defaults to "do".
		 */
		type?: "do" | "sleep" | "waitForEvent";
	};
}

from объект определяет шаг, с которого нужно перезапустить выполнение. Только name обязателен; count и type нужны только тогда, когда в рамках одного запуска одно и то же имя шага встречается более одного раза.

завершить

Принудительное завершение экземпляра Workflow.

let instance = await env.MY_WORKFLOW.get("abc-123");

// Terminate without running rollback handlers.
await instance.terminate();

// Run registered rollback handlers before terminating.
await instance.terminate({ rollback: true });

Если rollback это true, Workflows запускает обработчики отката, зарегистрированные завершёнными или подходящими для этого шагами, прежде чем экземпляр перейдёт в terminated состояние. Шаги без обработчиков отката пропускаются.

WorkflowInstanceTerminateOptions

interface WorkflowInstanceTerminateOptions {
	/**
	 * If true, run registered rollback handlers before terminating the instance.
	 */
	rollback?: boolean;
}

sendEvent

Отправка события запущенному экземпляру Workflow.

Верните void при успешном выполнении; выбрасывает исключение, если Workflow не запущен или находится в состоянии ошибки.

export default {
	async fetch(req, env) {
		const instanceId = new URL(req.url).searchParams.get("instanceId");
		const webhookPayload = await req.json();

		let instance = await env.MY_WORKFLOW.get(instanceId);
		// Send our event, with `type` matching the event type defined in
		// our step.waitForEvent call
		await instance.sendEvent({
			type: "stripe-webhook",
			payload: webhookPayload,
		});

		return Response.json({
			status: await instance.status(),
		});
	},
};
export default {
	async fetch(req: Request, env: Env) {
		const instanceId = new URL(req.url).searchParams.get("instanceId");
		const webhookPayload = await req.json<Payload>();

		let instance = await env.MY_WORKFLOW.get(instanceId);
		// Send our event, with `type` matching the event type defined in
		// our step.waitForEvent call
		await instance.sendEvent({
			type: "stripe-webhook",
			payload: webhookPayload,
		});

		return Response.json({
			status: await instance.status(),
		});
	},
};

Можно вызвать sendEvent несколько раз, задавая значение type свойство, чтобы оно соответствовало конкретному waitForEvent вызовов в вашем Workflow.

Это позволяет ждать сразу несколько событий или использовать Promise.race чтобы ожидать несколько событий и позволить первому из них продолжить выполнение Workflow.

InstanceStatus

Описывает статус экземпляра Workflow.

type InstanceStatus = {
	status:
		| "queued" // means that instance is waiting to be started (see concurrency limits)
		| "running"
		| "paused"
		| "errored"
		| "terminated" // user terminated the instance while it was running
		| "complete"
		| "waiting" // instance is hibernating and waiting for sleep or event to finish
		| "waitingForPause" // instance is finishing the current work to pause
		| "unknown";
	error?: {
		name: string;
		message: string;
	};
	output?: unknown;
	rollback: {
		outcome: "complete" | "failed";
		error: {
			name: string;
			message: string;
		} | null;
	} | null;
};

Если Workflow переходит в состояние отката, Workers API продолжает сообщать status: "running" для совместимости на время выполнения отката. После того как инстанс перейдёт в конечное состояние, проверьте rollback чтобы определить, завершились ли компенсирующие шаги успешно или со сбоем.

Сноски

  1. Шаблон соответствия: ^[a-zA-Z0-9_][a-zA-Z0-9-_]*$ ↩ ↩2 ↩3