@cloudflare/containers
Version:
Helper class for container-enabled Durable Objects
198 lines (197 loc) • 8.64 kB
TypeScript
import type { ContainerOptions, ContainerStartOptions, ContainerStartConfigOptions, Schedule, StopParams, State, WaitOptions, CancellationOptions, StartAndWaitForPortsOptions } from '../types';
import { DurableObject } from 'cloudflare:workers';
export type Signal = 'SIGKILL' | 'SIGINT' | 'SIGTERM';
export type SignalInteger = number;
export declare class Container<Env = unknown> extends DurableObject<Env> {
defaultPort?: number;
requiredPorts?: number[];
sleepAfter: string | number;
envVars: ContainerStartOptions['env'];
entrypoint: ContainerStartOptions['entrypoint'];
enableInternet: ContainerStartOptions['enableInternet'];
constructor(ctx: DurableObject['ctx'], env: Env, options?: ContainerOptions);
/**
* Gets the current state of the container
* @returns Promise<State>
*/
getState(): Promise<State>;
/**
* Start the container if it's not running and set up monitoring and lifecycle hooks,
* without waiting for ports to be ready.
*
* It will automatically retry if the container fails to start, using the specified waitOptions
*
*
* @example
* await this.start({
* envVars: { DEBUG: 'true', NODE_ENV: 'development' },
* entrypoint: ['npm', 'run', 'dev'],
* enableInternet: false
* });
*
* @param startOptions - Override `envVars`, `entrypoint` and `enableInternet` on a per-instance basis
* @param waitOptions - Optional wait configuration with abort signal for cancellation. Default ~8s timeout.
* @returns A promise that resolves when the container start command has been issued
* @throws Error if no container context is available or if all start attempts fail
*/
start(startOptions?: ContainerStartConfigOptions, waitOptions?: WaitOptions): Promise<void>;
/**
* Start the container and wait for ports to be available.
*
* For each specified port, it polls until the port is available or `cancellationOptions.portReadyTimeoutMS` is reached.
*
* @param ports - The ports to wait for (if undefined, uses requiredPorts or defaultPort)
* @param cancellationOptions - Options to configure timeouts, polling intereva, and abort signal
* @param startOptions Override configuration on a per-instance basis for env vars, entrypoint command and internet access
* @returns A promise that resolves when the container has been started and the ports are listening
* @throws Error if port checks fail after the specified timeout or if the container fails to start.
*/
startAndWaitForPorts(args: StartAndWaitForPortsOptions): Promise<void>;
startAndWaitForPorts(ports?: number | number[], cancellationOptions?: CancellationOptions, startOptions?: ContainerStartConfigOptions): Promise<void>;
startAndWaitForPorts(portsOrArgs?: number | number[] | StartAndWaitForPortsOptions, cancellationOptions?: CancellationOptions, startOptions?: ContainerStartConfigOptions): Promise<void>;
/**
*
* Waits for a specified port to be ready
*
* Returns the number of tries used to get the port, or throws if it couldn't get the port within the specified retry limits.
*
* @param waitOptions -
* - `portToCheck`: The port number to check
* - `abort`: Optional AbortSignal to cancel waiting
* - `retries`: Number of retries before giving up (default: TRIES_TO_GET_PORTS)
* - `waitInterval`: Interval between retries in milliseconds (default: INSTANCE_POLL_INTERVAL_MS)
*/
waitForPort(waitOptions: WaitOptions): Promise<number>;
/**
* Send a signal to the container.
* @param signal - The signal to send to the container (default: 15 for SIGTERM)
*/
stop(signal?: Signal | SignalInteger): Promise<void>;
/**
* Destroys the container with a SIGKILL. Triggers onStop.
*/
destroy(): Promise<void>;
/**
* Lifecycle method called when container starts successfully
* Override this method in subclasses to handle container start events
*/
onStart(): void | Promise<void>;
/**
* Lifecycle method called when container shuts down
* Override this method in subclasses to handle Container stopped events
* @param params - Object containing exitCode and reason for the stop
*/
onStop(_: StopParams): void | Promise<void>;
/**
* Lifecycle method called when the container is running, and the activity timeout
* expiration (set by `sleepAfter`) has been reached.
*
* If you want to shutdown the container, you should call this.stop() here
*
* By default, this method calls `this.stop()`
*/
onActivityExpired(): Promise<void>;
/**
* Error handler for container errors
* Override this method in subclasses to handle container errors
* @param error - The error that occurred
* @returns Can return any value or throw the error
*/
onError(error: unknown): any;
/**
* Renew the container's activity timeout
*
* Call this method whenever there is activity on the container
*/
renewActivityTimeout(): void;
/**
* Schedule a task to be executed in the future.
*
* We strongly recommend using this instead of the `alarm` handler.
*
* @template T Type of the payload data
* @param when When to execute the task (Date object or number of seconds delay)
* @param callback Name of the method to call
* @param payload Data to pass to the callback
* @returns Schedule object representing the scheduled task
*/
schedule<T = string>(when: Date | number, callback: string, payload?: T): Promise<Schedule<T>>;
/**
* Send a request to the container (HTTP or WebSocket) using standard fetch API signature
*
* This method handles HTTP requests to the container.
*
* WebSocket requests done outside the DO won't work until https://github.com/cloudflare/workerd/issues/2319 is addressed.
* Until then, please use `switchPort` + `fetch()`.
*
* Method supports multiple signatures to match standard fetch API:
* - containerFetch(request: Request, port?: number)
* - containerFetch(url: string | URL, init?: RequestInit, port?: number)
*
* Starts the container if not already running, and waits for the target port to be ready.
*
* @returns A Response from the container
*/
containerFetch(requestOrUrl: Request | string | URL, portOrInit?: number | RequestInit, portParam?: number): Promise<Response>;
/**
*
* Fetch handler on the Container class.
* By default this forwards all requests to the container by calling `containerFetch`.
* Use `switchPort` to specify which port on the container to target, or this will use `defaultPort`.
* @param request The request to handle
*/
fetch(request: Request): Promise<Response>;
private container;
private onStopCalled;
private state;
private monitor;
private monitorSetup;
private sleepAfterMs;
/**
* Execute SQL queries against the Container's database
*/
private sql;
private requestAndPortFromContainerFetchArgs;
/**
*
* The method prioritizes port sources in this order:
* 1. Ports specified directly in the method call
* 2. `requiredPorts` class property (if set)
* 3. `defaultPort` (if neither of the above is specified)
* 4. Falls back to port 33 if none of the above are set
*/
private getPortsToCheck;
/**
* Tries to start a container if it's not already running
* Returns the number of tries used
*/
private startContainerIfNotRunning;
private setupMonitorCallbacks;
deleteSchedules(name: string): void;
/**
* Method called when an alarm fires
* Executes any scheduled tasks that are due
*/
alarm(alarmProps: {
isRetry: boolean;
retryCount: number;
}): Promise<void>;
timeout?: ReturnType<typeof setTimeout>;
resolve?: () => void;
private syncPendingStoppedEvents;
private callOnStop;
/**
* Schedule the next alarm based on upcoming tasks
*/
scheduleNextAlarm(ms?: number): Promise<void>;
listSchedules<T = string>(name: string): Promise<Schedule<T>[]>;
private toSchedule;
/**
* Get a scheduled task by ID
* @template T Type of the payload data
* @param id ID of the scheduled task
* @returns The Schedule object or undefined if not found
*/
getSchedule<T = string>(id: string): Promise<Schedule<T> | undefined>;
private isActivityExpired;
}