← Dynamic Workers / dynamic-workers
Referenční dokumentace API
Tato stránka popisuje API bindingu Worker Loaderu za předpokladu, že máte nakonfigurovali takový binding jako env.LOADER.
load
env.LOADER.load(code WorkerCode) WorkerStub
Načte Worker z poskytnutého WorkerCode a vrátí WorkerStub která může sloužit k vyvolání Workeru.
Na rozdíl od get(), load() neukládá do cache podle ID. Každé volání vytvoří nový Worker.
Použijte load() když je kód vždy nový, například u jednorázových volání nástrojů generovaných AI.
get
env.LOADER.get(id string, getCodeCallback () => Promise<WorkerCode>): WorkerStub
Načte Worker se zadaným ID a vrátí WorkerStub která může sloužit k vyvolání Workeru.
Pro pohodlí loader implementuje kešování izolátů. Když se poprvé objeví nové ID, načte se nový izolát. Ten pak může nějakou dobu zůstat v paměti zahřátý. Pokud pozdější volání loaderu požádají o stejné ID, může se znovu vrátit existující izolát místo vytvoření nového. Není to však zaručeno: pozdější volání se stejným ID může místo toho spustit zcela nový izolát.
Kdykoli systém rozhodne, že potřebuje spustit nový isolate, a nemá kód dosud uložený v cache, vyvolá codeCallback k získání kódu Workeru. Jde o asynchronní callback, takže aplikace může kód v případě potřeby načíst ze vzdáleného úložiště. Callback vrací WorkerCode objekt (popsán níže).
Kvůli kešování byste měli zajistit, aby callback při volání se stejným ID vždy vrátil naprosto stejný obsah. Pokud se na obsahu cokoli změní, musíte použít nové ID. Pokud se ale obsah nezměnil, je nejlepší použít znovu stejné ID, abyste využili výhod kešování. Pokud WorkerCode se pokaždé liší, můžete předat náhodné ID.
Můžete například použít ID ve tvaru <worker-name>:<version-number>, kde se číslo verze zvyšuje při každé změně kódu. Případně můžete ID počítat z hashe kódu a konfigurace, takže jakákoli změna povede k novému ID.
get() vrací WorkerStub, který lze použít k odesílání požadavků na načtený Worker. Stub se vrací synchronně, není potřeba na něj čekat pomocí await. Pokud Worker ještě není načtený, požadavky na stub počkají, až se Worker načte, a teprve poté budou doručeny. Pokud načítání selže, požadavek vyvolá výjimku.
Není nikdy zaručeno, že dva požadavky poputují do stejného izolátu. I když použijete stejný WorkerStub k vytvoření více požadavků, mohou se vykonat v různých izolátech. Callback předaný do loader.get() může být volána libovolněkrát (i když je neobvyklé, aby byla volána víckrát než jednou).
WorkerCode
Toto je struktura, kterou vrací getCodeCallback k reprezentaci workeru.
compatibilityDate string
string compatibility date pro Worker. Má to stejný význam jako compatibility_date nastavení v konfiguračním souboru Wrangler.
compatibilityFlags string[] Optional
string[] OptionalVolitelný seznam compatibility flags rozšiřuje compatibility date. Má to stejný význam jako compatibility_flags nastavení v konfiguračním souboru Wrangler.
allowExperimental boolean Optional
boolean OptionalPokud je hodnota true, budou experimentální compatibility flags povoleny v compatibilityFlags. Aby to bylo možné nastavit, musí mít worker, který loader volá, sám nastaven compatibility flag "experimental" nastaven. Experimentální flagy nelze v produkci povolit.
mainModule string
stringNázev hlavního modulu Workeru. Musí se jednat o jeden z modulů uvedených v modules.
modules Record<string, string | Module>
Record<string, string | Module>Objekt slovníku, který mapuje názvy modulů na jejich textový obsah. Pokud je obsah modulu obyčejný řetězec, musí mít název modulu příponu souboru označující jeho typ, a to buď .js nebo .py.
Obsah modulu lze také zadat jako objekt, aby bylo možné určit jeho typ nezávisle na názvu. Povolené objekty jsou:
{js: string}: JavaScript modul, který pro importy a exporty používá syntaxi ES modulů.{cjs: string}: CommonJS modul, který používárequire()syntaxi pro importy.{py: string}: Python modul. Viz upozornění níže.{text: string}: Importovatelná řetězcová hodnota.{data: ArrayBuffer}: ImportovatelnýArrayBufferhodnota.{wasm: ArrayBuffer}: Zkompilovaný modul WebAssembly (Wasm).{json: object}: Importovatelný objekt. Hodnota musí být serializovatelná do JSON. Je však třeba mít na paměti, že hodnota se poskytuje i doručuje jako již rozparsovaný objekt, takže žádná strana ve skutečnosti JSON serializaci nevidí.
globalOutbound ServiceStub | null Optional
ServiceStub | null OptionalŘídí, zda má dynamický Worker přístup k síti. Globální fetch() a connect() funkce (pro vytváření požadavků HTTP, respektive připojení TCP) lze zablokovat nebo přesměrovat, a Worker tak izolovat.
Pokud globalOutbound není zadán, výchozí chování dědí síťový přístup nadřazeného prvku, což obvykle znamená, že dynamic Worker bude mít plný přístup k veřejnému internetu.
Pokud globalOutbound je null, pak bude dynamic Worker zcela odpojen od sítě. Obě fetch() a connect() vyvolá výjimky.
globalOutbound lze také nastavit na libovolný service binding, včetně service bindingů nadřazeného workeru v env a také loopback bindingy z ctx.exports.
Použití ctx.exports je obzvláště užitečné, protože umožňuje dále přizpůsobit binding pro konkrétní sandbox nastavením hodnoty ctx.props která by mu měla být předána zpět. props může obsahovat informace, podle kterých identifikujete konkrétní dynamic Worker, jenž požadavek odeslal.
Například:
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
objectObjekt prostředí (environment), který se má poskytnout dynamickému Workeru.
Díky tomu můžete Workeru poskytnout vlastní bindingy.
env se serializuje a přenese do dynamic Workeru, kde se použije přímo jako hodnota env tam. Může obsahovat:
- Typy klonovatelné pomocí Structured Clone ↗.
- Service Bindings, včetně loopback bindingy z
ctx.exports.
Druhý bod je klíčem k vytváření vlastních bindingů: binding můžete definovat s jakýmkoli libovolným API tak, že definujete WorkerEntrypoint třída implementující API RPC a následným předáním dynamic Workeru jako Service Binding.
Díky použití ctx.exports loopback bindingy můžete dále přizpůsobit pro konkrétní dynamic Worker nastavením ctx.props, stejně jako je popsáno u globalOutbound, výše.
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
ServiceStub[] OptionalMůžete zadat jeden nebo více Tail Workers která bude sledovat logy konzole, chyby a další podrobnosti o vykonávání dynamicky načteného workeru. Po dokončení požadavku na dynamicky načtený Worker se do Tail Workeru doručí tail event. Tail Worker můžete jako vždy implementovat jako alternativní entrypoint ve svém nadřazeném Workeru, na který odkážete pomocí 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),
});
}
}