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

Справочник по API

На этой странице описывается API привязки Worker Loader. Предполагается, что у вас уже есть настроили такую привязку как env.LOADER.

load

env.LOADER.load(code WorkerCode) WorkerStub

Загружает Worker из предоставленного WorkerCode и возвращает WorkerStub который можно использовать для вызова Worker.

В отличие от get(), load() не кеширует по ID. Каждый вызов создает новый Worker.

Используйте load() когда код всегда новый, например для разовых вызовов инструментов, сгенерированных AI.

get

env.LOADER.get(id string, getCodeCallback () => Promise<WorkerCode>): WorkerStub

Загружает Worker с указанным ID и возвращает WorkerStub который можно использовать для вызова Worker.

Для удобства загрузчик реализует кэширование isolate. Когда ID встречается впервые, загружается новый isolate. При этом isolate может некоторое время оставаться прогретым в памяти. Если последующие вызовы загрузчика запрашивают тот же ID, может быть возвращен уже существующий isolate вместо создания нового. Однако гарантии нет: последующий вызов с тем же ID может вместо этого запустить новый isolate с нуля.

Каждый раз, когда системе нужно запустить новый изолят и в кэше ещё нет копии кода, она вызывает codeCallback для получения кода Worker. Это асинхронный колбэк, поэтому приложение может при необходимости загружать код из удалённого хранилища. Колбэк возвращает WorkerCode объект (описан ниже).

Из-за кэширования нужно следить за тем, чтобы колбэк всегда возвращал одно и то же содержимое при вызове с одним и тем же ID. Если содержимое как-либо меняется, необходимо использовать новый ID. Но если содержимое не изменилось, лучше использовать тот же ID, чтобы задействовать кэширование. Если WorkerCode отличается каждый раз, можно передавать случайный ID.

Например, вы можете использовать идентификаторы вида <worker-name>:<version-number>, где номер версии увеличивается при каждом изменении кода. Либо можно вычислять ID на основе хеша кода и конфигурации, чтобы любое изменение приводило к новому ID.

get() возвращает WorkerStub, который можно использовать для отправки запросов загруженному Worker. Обратите внимание, что стаб возвращается синхронно: вызывать await для него не нужно. Если Worker ещё не загружен, запросы к стабу будут ожидать его загрузки перед доставкой. Если загрузка завершится ошибкой, запрос выбросит исключение.

Нет гарантии, что два запроса попадут в один и тот же изолят. Даже если вы используете один и тот же WorkerStub для нескольких запросов, они могут выполняться в разных isolate. Колбэк, переданный в loader.get() может вызываться любое количество раз (хотя обычно он вызывается не более одного раза).

WorkerCode

Это структура, которую возвращает getCodeCallback для представления Worker.

compatibilityDate string

дата совместимости для Worker. Это имеет то же значение, что и compatibility_date настройку в конфигурационном файле Wrangler.

compatibilityFlags string[] Optional

Необязательный список флаги совместимости дополняя дату совместимости. Это имеет то же значение, что и compatibility_flags настройку в конфигурационном файле Wrangler.

allowExperimental boolean Optional

Если задано значение true, экспериментальные флаги совместимости будут разрешены в compatibilityFlags. Чтобы задать это значение, worker, вызывающий Worker Loader, должен сам иметь флаг совместимости "experimental" задан. Экспериментальные флаги нельзя включать в production.

mainModule string

Имя главного модуля Worker. Это должен быть один из модулей, перечисленных в modules.

modules Record<string, string | Module>

Объект-словарь, сопоставляющий имена модулей с их строковым содержимым. Если содержимое модуля представляет собой обычную строку, имя модуля должно иметь расширение файла, указывающее его тип: либо .js или .py.

Содержимое модуля также можно задать в виде объекта, чтобы указать его тип независимо от имени. Допустимые объекты:

globalOutbound ServiceStub | null Optional

Определяет, есть ли у dynamic Worker доступ к сети. Глобальный fetch() и connect() функции (для выполнения HTTP-запросов и TCP-соединений соответственно) можно блокировать или перенаправлять, чтобы изолировать Worker.

Если globalOutbound не указан, по умолчанию наследуется сетевой доступ родителя, что обычно означает полный доступ динамического Worker к публичному интернету.

Если globalOutbound это null, то dynamic Worker будет полностью отрезан от сети. Оба fetch() и connect() выбрасывает исключения.

globalOutbound также можно задать как любую привязку сервиса, включая привязки сервисов у родительского worker в env а также loopback-привязки от ctx.exports.

Использование ctx.exports особенно полезен тем, что позволяет дополнительно настроить привязку для конкретной песочницы, задав значение ctx.props который следует передать ему обратно. props может содержать информацию, позволяющую определить конкретный динамический Worker, который сделал запрос.

Например:

import { WorkerEntrypoint } from "cloudflare:workers";

export class Greeter extends WorkerEntrypoint {
	fetch(request) {
		return new Response(`Hello, ${this.ctx.props.name}!`);
	}
}

export default {
	async fetch(request, env, ctx) {
		let worker = env.LOADER.get("alice", () => {
			return {
				// Redirect the worker's global outbound to send all requests
				// to the `Greeter` class, filling in `ctx.props.name` with
				// the name "Alice", so that it always responds "Hello, Alice!".
				globalOutbound: ctx.exports.Greeter({ props: { name: "Alice" } }),

				// ... code ...
			};
		});

		return worker.getEntrypoint().fetch(request);
	},
};

env object

Объект окружения, передаваемый динамическому Worker.

С его помощью вы можете предоставить Worker пользовательские привязки.

env сериализуется и передаётся в динамический Worker, где используется напрямую как значение env там. Он может содержать:

Второй момент является ключевым для создания пользовательских привязок: вы можете определить привязку с произвольным API, определив WorkerEntrypoint класс реализующий RPC API, а затем передать его динамическому Worker в виде привязки сервиса.

Кроме того, при использовании ctx.exports loopback-привязок можно дополнительно настроить привязки для конкретного динамического Worker, задав ctx.props, точно так же, как описано для globalOutbound, выше.

import { WorkerEntrypoint } from "cloudflare:workers";

// Implement a binding which can be called by the dynamic Worker.
export class Greeter extends WorkerEntrypoint {
	greet() {
		return `Hello, ${this.ctx.props.name}!`;
	}
}

export default {
	async fetch(request, env, ctx) {
		let worker = env.LOADER.get("alice", () => {
			return {
				env: {
					// Provide a binding which has a method greet() which can be called
					// to receive a greeting. The binding knows the Worker's name.
					GREETER: ctx.exports.Greeter({ props: { name: "Alice" } }),
				},

				// ... code ...
			};
		});

		return worker.getEntrypoint().fetch(request);
	},
};

tails ServiceStub[] Optional

Вы можете указать один или несколько Tail Workers который будет наблюдать за логами консоли, ошибками и другими деталями выполнения динамически загруженного worker. Tail-событие будет доставлено Tail Worker по завершении запроса к динамически загруженному Worker. Как обычно, вы можете реализовать Tail Worker как альтернативную точку входа в родительском Worker, ссылаясь на него с помощью ctx.exports:

import { WorkerEntrypoint } from "cloudflare:workers";

export default {
	async fetch(request, env, ctx) {
		let worker = env.LOADER.get("alice", () => {
			return {
				// Send logs, errors, etc. to `LogTailer`. We pass `name` in the
				// `ctx.props` so that `LogTailer` knows what generated the logs.
				// (You can pass anything you want in `props`.)
				tails: [ctx.exports.LogTailer({ props: { name: "alice" } })],

				// ... code ...
			};
		});

		return worker.getEntrypoint().fetch(request);
	},
};

export class LogTailer extends WorkerEntrypoint {
	async tail(events) {
		let name = this.ctx.props.name;

		// Send the logs off to our log endpoint, specifying the worker name in
		// the URL.
		//
		// Note that `events` will always be an array of size 1 in this scenario,
		// describing the event delivered to the dynamically-loaded Worker.
		await fetch(`https://example.com/submit-logs/${name}`, {
			method: "POST",
			body: JSON.stringify(events),
		});
	}
}