UNPKG

@cloudflare/containers

Version:

Helper class for container-enabled Durable Objects

198 lines (197 loc) 8.64 kB
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; }