Runtime environment for sequence execution and communication with Transform Hub host.
—
The RunnerAppContext provides the runtime context for sequences, implementing the AppContext interface with lifecycle management, event handling, and host integration APIs.
import { RunnerAppContext } from "@scramjet/runner/src/runner-app-context";Application context for sequences providing comprehensive runtime APIs including configuration access, lifecycle handlers, monitoring, and communication with the Transform Hub.
/**
* Application context for sequences, implementing AppContext interface
*/
class RunnerAppContext<AppConfigType extends AppConfig, State extends any>
implements AppContext<AppConfigType, State> {
constructor(
config: AppConfigType,
monitorStream: WritableStream<any>,
emitter: EventEmitter,
runner: RunnerProxy,
hostClient: HostClient,
spaceClient: ManagerClient,
id: string
);
/** Application configuration */
config: AppConfigType;
/** Error constructor for application errors */
AppError!: AppErrorConstructor;
/** Monitoring stream for sending status updates */
monitorStream: WritableStream<any>;
/** Event emitter for sequence events */
emitter: EventEmitter;
/** Initial state (optional) */
initialState?: State;
/** Exit timeout in milliseconds (default: 10000) */
exitTimeout: number;
/** Context logger instance */
logger: IObjectLogger;
/** Host API client for Transform Hub operations */
hub: HostClient;
/** Manager API client for space operations */
space: ManagerClient;
/** Instance identifier */
instanceId: string;
/** Function definition metadata */
readonly definition: FunctionDefinition;
}Usage Example:
// In a sequence function
export default function(this: RunnerAppContext<any, any>, input: DataStream) {
// Access configuration
const config = this.config;
// Set up lifecycle handlers
this.addStopHandler(async (timeout, canKeepAlive) => {
console.log(`Stopping with timeout: ${timeout}`);
// Cleanup logic here
});
// Send keep-alive if needed
this.keepAlive(5000);
// Emit events
this.emit("progress", { completed: 0.5 });
return input.map(item => ({ ...item, processed: true }));
}Handler registration and execution for sequence lifecycle events.
/**
* Add handler for kill requests (immediate termination)
* @param handler - Function to execute on kill
* @returns this for method chaining
*/
addKillHandler(handler: KillHandler): this;
/**
* Execute all registered kill handlers
*/
killHandler(): void;
/**
* Add handler for stop requests (graceful termination)
* @param handler - Function to execute on stop with timeout and keepalive options
* @returns this for method chaining
*/
addStopHandler(handler: StopHandler): this;
/**
* Execute all registered stop handlers
* @param timeout - Timeout in milliseconds for graceful stop
* @param canCallKeepalive - Whether keepalive can be called during stop
*/
stopHandler(timeout: number, canCallKeepalive: boolean): Promise<void>;Health monitoring and status reporting functionality.
/**
* Add handler for health monitoring checks
* @param handler - Function that returns health status
* @returns this for method chaining
*/
addMonitoringHandler(handler: MonitoringHandler): this;
/**
* Execute all monitoring handlers and aggregate health status
* @param initialMessage - Initial health message (default: { healthy: true })
* @returns Promise resolving to aggregated health status
*/
monitor(initialMessage?: MonitoringMessageFromRunnerData): Promise<MonitoringMessageFromRunnerData>;Methods for controlling sequence execution and communicating with the host.
/**
* Send keep-alive message to extend sequence lifetime
* @param milliseconds - Keep-alive duration in milliseconds (default: 0)
* @returns this for method chaining
*/
keepAlive(milliseconds?: number): this;
/**
* End sequence execution normally
* @returns this for method chaining
*/
end(): this;
/**
* Destroy sequence with error
* @param error - Optional error to report
* @returns this for method chaining
*/
destroy(error?: AppError): this;Event emission and subscription for sequence communication.
/**
* Subscribe to events from the host or other sequences
* @param eventName - Name of the event to listen for
* @param handler - Function to handle the event
* @returns this for method chaining
*/
on(eventName: string, handler: (message?: any) => void): this;
/**
* Emit event to the host
* @param eventName - Name of the event
* @param message - Optional message data
* @returns this for method chaining
*/
emit(eventName: string, message?: any): this;Metadata management for sequence functions.
/**
* Describe the sequence function with metadata
* @param definition - Function definition with mode, name, and other properties
* @returns this for method chaining
*/
describe(definition: FunctionDefinition): this;State persistence functionality (placeholder implementation).
/**
* Save sequence state (not currently implemented)
* @param state - State to save
* @returns this for method chaining
*/
save(state: State): this;Usage Example:
export default function(this: RunnerAppContext<any, any>, input: DataStream) {
// Describe the function
this.describe({
mode: "stream",
name: "data-processor",
description: "Processes incoming data stream"
});
// Add monitoring
this.addMonitoringHandler(async (message) => {
const memUsage = process.memoryUsage();
return {
healthy: memUsage.heapUsed < 100 * 1024 * 1024, // 100MB limit
memoryUsage: memUsage
};
});
// Handle graceful stop
let processing = true;
this.addStopHandler(async (timeout, canKeepAlive) => {
processing = false;
if (canKeepAlive) {
this.keepAlive(timeout);
}
});
return input
.filter(() => processing)
.map(item => {
this.emit("item-processed", { id: item.id });
return { ...item, timestamp: Date.now() };
});
}interface AppContext<AppConfigType extends AppConfig, State extends any> {
config: AppConfigType;
logger: IObjectLogger;
hub: HostClient;
space: ManagerClient;
instanceId: string;
definition: FunctionDefinition;
addKillHandler(handler: KillHandler): this;
addStopHandler(handler: StopHandler): this;
addMonitoringHandler(handler: MonitoringHandler): this;
keepAlive(milliseconds?: number): this;
end(): this;
destroy(error?: AppError): this;
on(eventName: string, handler: (message?: any) => void): this;
emit(eventName: string, message?: any): this;
describe(definition: FunctionDefinition): this;
save(state: State): this;
}
interface AppError {
message: string;
code?: string;
stack?: string;
}
type AppErrorConstructor = new (message: string) => AppError;
interface HostClient {
// API client for Transform Hub operations
[key: string]: any;
}
interface ManagerClient {
// API client for space/manager operations
[key: string]: any;
}Install with Tessl CLI
npx tessl i tessl/npm-scramjet--runner