INTEGRITY Dokumentace

Provádění procesů

V náhledu verze 1.0 přistupujte k sandboxu jako k počítači, který ovládáte pomocí explicitních programů.

Každý exec() spustí nový spravovaný proces z argv. Volání se vyřeší, jakmile spuštění proběhne úspěšně (obdržíte handle procesu s id a pid vlastnosti), nikoli při ukončení procesu. Každé spuštění je nezávislé: předejte cwd a env když je proces potřebuje, nebo vložte víceúrovňovou syntaxi shellu do jednoho explicitního argv shellu. Pro interaktivní PTY použijte terminál API.

Dlouhotrvající práce se často rozprostírá přes mnoho krátkých požadavků Workeru. ID procesu stačí, pouze dokud stejný kontejner má tento proces stále k dispozici. Pro případ zastavení kvůli nečinnosti, selhání nebo nahrazení si uložte celé spuštění (příkaz, volby a případný checkpoint aplikace), abyste mohli začít znovu. Podívejte se na Pokračování v práci napříč požadavky.

ID sandboxu, kontejner a proces

Většina aplikací používá jeden sandbox na uživatele nebo úkol:

const sandbox = getSandbox(env.Sandbox, "user-123");
const sandbox = getSandbox(env.Sandbox, "user-123");

Do hry vstupují tři různé věci:

Pojem Význam
ID sandboxu Stabilní řetězec, který vaše aplikace použije k opětovnému nalezení sandboxu, například "user-123").
Kontejner Containers instance, která pro daný sandbox aktuálně zpracovává úlohy. Sandboxy běží na kontejnerech. ID sandboxu je stálé. Instance kontejneru za ním ale není vždy stejná.
Proces Program, který spustíte pomocí exec() uvnitř aktuálního kontejneru. Handle a process.id znamenají „tento program v tomto kontejneru“, ne „toto ID sandboxu navždy“.

Stejné ID sandboxu neznamená stejný kontejner. Procesy existují jen v kontejneru, který je spustil. Jakmile dané ID obsluhuje nový kontejner, spusťte nové procesy: staré procesy neobnovujete. Úplný model sandboxu: Životní cyklus sandboxu.

Model příkazů

Model příkazů se v náhledu 1.0 oproti aktuálnímu stabilnímu balíčku mění:

Aktuální stabilní balíček 1.0 preview
exec(string) se vyřeší, jakmile příkaz skončí exec(argv) se vyřeší, jakmile se proces spustí
Výchozí relace může zachovat cd / export Každé spuštění je nezávislé
startProcess / execStream pro jiné tvary Jeden handle procesu pokrývá krátkodobé i dlouhotrvající úlohy

Pro jediný binární soubor použijte argv:

const process = await sandbox.exec(["node", "--version"]);
const output = await process.output({ encoding: "utf8" });
const process = await sandbox.exec(["node", "--version"]);
const output = await process.output({ encoding: "utf8" });

Pokud potřebujete syntaxi shellu, použijte explicitní shell:

const process = await sandbox.exec([
	"/bin/bash",
	"-lc",
	"cd /workspace/app && npm test",
]);
const process = await sandbox.exec([
	"/bin/bash",
	"-lc",
	"cd /workspace/app && npm test",
]);

Nebo předejte cwd a env při spuštění, místo abyste se spoléhali na předchozí příkaz:

const process = await sandbox.exec(["npm", "test"], {
	cwd: "/workspace/app",
	env: { NODE_ENV: "test" },
});
const process = await sandbox.exec(["npm", "test"], {
	cwd: "/workspace/app",
	env: { NODE_ENV: "test" },
});

Hodnoty platné pro celý sandbox používají setEnvVars. Viz Proměnné prostředí.

Popisovače procesů

await sandbox.exec(argv) vrací handle procesu:

Možnost Členové
Identita id, pid
Pozorování status(), logs(), output(), waitForExit(), waitForLog(), waitForPort(), exitCode
Ovládání kill(signal?) s číselným signálem (výchozí 15)

Časové limity pozorování a AbortSignal hodnoty zruší pouze ty, které čekají nebo streamují. Proces tím nezastaví. Zavolejte kill() když ho hodláte zastavit.

exec(argv, { timeout }) nastaví vzdálená životnost deadline. Když supervisor kvůli tomuto deadline proces zastaví, dokončení může hlásit timedOut: true.

Pro krátké příkazy, output() stačí. Pro velké nebo dlouho běžící výstupy dejte přednost logs({ since, replay, follow }) a ponechte poslední kurzor aby mohl pozdější požadavek stream obnovit, dokud proces stále běží ve stejném kontejneru. Podrobnosti API: Processes API.

Jak dlouho proces žije

Proces existuje pouze tak dlouho, dokud běží v aktuálním kontejneru pro daný sandbox. Jakmile se kontejner zastaví, stará ID procesů přestávají platit v pozdějším kontejneru, který obsluhuje stejné ID sandboxu.

Když se kontejner zastaví

Kontejner sandboxu není určen k tomu, aby běžel neustále. Po určité době nečinnosti ho Cloudflare může zastavit. Kontejner se také může zastavit po selhání nebo když ho platforma při běžném provozu nahradí, například po některých nasazeních.

Když se to stane:

Zastavení a nahrazení kontejneru nejsou ve verzi 1.0 novinkou. Náhled zajišťuje, že handly procesů selžou v režimu fail closed poté, co kontejner, který je vlastnil, zanikne: SDK nepřesměruje staré ID procesu na nový kontejner se stejným ID sandboxu.

Co uvidíte v API

Co vyzkoušíte Co se stane
Proces stále běží v aktuálním kontejneru getProcess(id) ho vrátí; logy můžete číst a čekat jako obvykle
Pro sandbox zatím neběží žádný kontejner getProcess a listProcesses vrátit null / []. Ano, ne spouštět kontejner jen kvůli zodpovězení tohoto dotazu
Stále držíte handle z doby před zastavením kontejneru Volání na tomto handleru selžou s StaleProcessHandleError
Potřebujete stejný úloha po zastavení Spusťte nový exec() ze spuštění a checkpointu, které vaše aplikace uložila

Postupy obnovení: Chyby a zotavení.

Udržujte kontejner spuštěný

Dokud je proces nebo terminál aktivní, může kontejner zůstat spuštěný, aby práce pokračovala napříč požadavky. Pokud nic aktivní není, může se kontejner po určité době nečinnosti opět zastavit. U dlouhotrvajících produkčních procesů byste měli buď udržovat smysluplnou práci aktivní, nebo se spolehnout na kontrolní body a opětovné spuštění.

Pokračování v práci napříč požadavky

Požadavky Workeru jsou krátké. Procesy sandboxu často nejsou. Úlohu navrhněte tak, aby pozdější požadavek mohl buď obnovit stejný proces nebo spustit úlohu znovu.

Co ukládat

Vždy užitečné Když streamujete logy
ID sandboxu Poslední protokol kurzor z doručených událostí
Úplný exec argv
cwd a env pokud je spuštění potřebuje
Kontrolní bod aplikace (cesta k repozitáři, krok, stav agenta)

ID procesu slouží jako klíč pro obnovení aktuální pouze kontejner. Nestačí úlohu restartovat až poté, co se kontejner případně zastavil.

Případ 1: Kontejner má proces stále k dispozici

Tuto cestu použijte, pokud práce ještě běží a kontejner nebyl nahrazen: další požadavek dorazí o několik sekund později, zatímco běží sestavení nebo server.

const process = await sandbox.getProcess(storedProcessId);
if (process) {
	const stream = await process.logs({
		since: storedCursor,
		replay: true,
		follow: true,
	});
	// consume events; keep the latest cursor from each event
	return;
}
const process = await sandbox.getProcess(storedProcessId);
if (process) {
	const stream = await process.logs({
		since: storedCursor,
		replay: true,
		follow: true,
	});
	// consume events; keep the latest cursor from each event
	return;
}

Můžete také zavolat status(), waitForPort(), waitForExit(), nebo kill() na tomto handle. Kurzory logu platí pouze dokud tento proces v tomto kontejneru stále existuje.

Případ 2: Proces zmizel, začněte od uložené úlohy

Tuto cestu použijte, když getProcess vrací null, volání vyvolá StaleProcessHandleError, nebo uplynulo dost času na to, že kontejner mohl být zastaven nebo nahrazen.

const process = await sandbox.exec(storedCommand, {
	cwd: storedCwd,
	env: storedEnv,
});
// persist process.id (and clear any old cursor)
await process.waitForPort(3000, { timeout: 60_000 });
const process = await sandbox.exec(storedCommand, {
	cwd: storedCwd,
	env: storedEnv,
});
// persist process.id (and clear any old cursor)
await process.waitForPort(3000, { timeout: 60_000 });

Pokud úloha závisí i na souborech, které existovaly pouze v předchozím kontejneru, zálohování a obnovení tyto adresáře nebo připojte trvalé úložiště, než se na tento strom souborů znovu spolehnete. Zálohování a obnovení nahrazují stav souborového systému. Nevrací ale stará ID procesů ani obsah logovacích bufferů.

Pokud kontejner ještě není připravený, může se zobrazit ContainerUnavailableError : počkejte (backoff) a zopakujte stejnou jednotku práce. Viz Chyby a zotavení.

Zvolte cestu

async function continueJob(sandbox, job) {
	if (job.processId) {
		const existing = await sandbox.getProcess(job.processId);
		if (existing) {
			return existing; // Case 1 — same container, same process
		}
		// null: no container, or this ID is not in the current container
	}

	// Case 2 — relaunch from stored command and checkpoint
	const process = await sandbox.exec(job.command, {
		cwd: job.cwd,
		env: job.env,
	});
	job.processId = process.id;
	job.cursor = undefined;
	return process;
}
async function continueJob(sandbox: Sandbox, job: StoredJob) {
	if (job.processId) {
		const existing = await sandbox.getProcess(job.processId);
		if (existing) {
			return existing; // Case 1 — same container, same process
		}
		// null: no container, or this ID is not in the current container
	}

	// Case 2 — relaunch from stored command and checkpoint
	const process = await sandbox.exec(job.command, {
		cwd: job.cwd,
		env: job.env,
	});
	job.processId = process.id;
	job.cursor = undefined;
	return process;
}

Pokud stále držíte objekt handle z doby před zastavením kontejneru, volání na tomto handlu vyvolají StaleProcessHandleError. Upřednostněte getProcess(id) při každém novém požadavku, místo abyste mezi požadavky opakovaně používali starý handle.

Procesy a terminály

Proces (exec) Terminál
Role Sledovaný proces argv Interaktivní PTY
Vstup argv při spuštění Vstup PTY (write / prohlížeč connect)
Zastavit kill(signal?) interrupt() / terminate()
Vyhledání getProcess / listProcesses getTerminal / listTerminals

Oba se řídí stejným pravidla životnosti kontejneru. Dokumentace k terminálu: Terminály. API: Terminals API.

Protokoly a rozsáhlý výstup

output() ukládá stdout a stderr do bufferu a může nastavit truncated: true. Upřednostněte logs() když výstup může být velký nebo proces běží déle než jeden požadavek Workeru.

const stream = await process.logs({ follow: true, replay: true });
// each data/terminal event includes a cursor — store the latest
const stream = await process.logs({ follow: true, replay: true });
// each data/terminal event includes a cursor — store the latest

Při pozdějším požadavku na stejný stále běžící kontejner, zavolejte getProcess(id) a obnovte pomocí logs({ since: cursor, replay: true, follow: true }). Jakmile se pro sandbox spustí nový kontejner, spusťte nový proces; starý kurzor už neplatí.

Tvary událostí, možnosti čekání a kontroly připravenosti: Processes API.