durable-execution-orpc-utils
Version:
oRPC utilities for durable-execution to create a separate server process for durable execution
163 lines • 8.05 kB
TypeScript
import { type FriendlyClientOptions } from '@orpc/client';
import { type AnySchema, type ErrorMap, type InferSchemaInput, type InferSchemaOutput, type Meta } from '@orpc/contract';
import { type Builder, type Context, type DecoratedProcedure, type ProcedureClient, type Schema } from '@orpc/server';
import { type AnyTasks, type CommonTaskOptions, type DurableExecutor, type FinishedTaskExecution, type InferTaskInput, type InferTaskOutput, type Task, type TaskEnqueueOptions, type TaskExecution, type WakeupSleepingTaskExecutionOptions } from 'durable-execution';
/**
* Type for the enqueueTask procedure that submits tasks for execution.
*/
export type EnqueueTaskProcedure<TTasks extends AnyTasks, TInitialContext extends Context, TCurrentContext extends Context, TErrorMap extends ErrorMap, TMeta extends Meta> = {
[K in keyof TTasks]: DecoratedProcedure<TInitialContext, TCurrentContext, Schema<{
taskId: K & string;
input: InferTaskInput<TTasks[K]>;
options?: TaskEnqueueOptions<TTasks[K]>;
}, {
taskId: K & string;
input: InferTaskInput<TTasks[K]>;
options?: TaskEnqueueOptions<TTasks[K]>;
}>, Schema<string, string>, TErrorMap, TMeta>;
}[keyof TTasks];
/**
* Type for the getTaskExecution procedure that retrieves task execution status.
*/
export type GetTaskExecutionProcedure<TTasks extends AnyTasks, TInitialContext extends Context, TCurrentContext extends Context, TErrorMap extends ErrorMap, TMeta extends Meta> = {
[K in keyof TTasks]: DecoratedProcedure<TInitialContext, TCurrentContext, Schema<{
taskId: K & string;
executionId: string;
}, {
taskId: K & string;
executionId: string;
}>, Schema<TaskExecution<InferTaskOutput<TTasks[K]>>, TaskExecution<InferTaskOutput<TTasks[K]>>>, TErrorMap, TMeta>;
}[keyof TTasks];
/**
* Type for the input schema of the wakeupSleepingTaskExecution procedure.
*/
export type WakeupSleepingTaskExecutionProcedureInputSchema<TTasks extends AnyTasks> = {
[K in keyof TTasks]: {
taskId: K & string;
sleepingTaskUniqueId: string;
options: WakeupSleepingTaskExecutionOptions<InferTaskOutput<TTasks[K]>>;
};
}[keyof TTasks];
/**
* Type for the wakeupSleepingTaskExecution procedure that wakes up a sleeping task execution.
*/
export type WakeupSleepingTaskExecutionProcedure<TTasks extends AnyTasks, TInitialContext extends Context, TCurrentContext extends Context, TErrorMap extends ErrorMap, TMeta extends Meta> = {
[K in keyof TTasks]: DecoratedProcedure<TInitialContext, TCurrentContext, Schema<{
taskId: K & string;
sleepingTaskUniqueId: string;
options: WakeupSleepingTaskExecutionOptions<InferTaskOutput<TTasks[K]>>;
}, {
taskId: K & string;
sleepingTaskUniqueId: string;
options: WakeupSleepingTaskExecutionOptions<InferTaskOutput<TTasks[K]>>;
}>, Schema<FinishedTaskExecution<InferTaskOutput<TTasks[K]>>, FinishedTaskExecution<InferTaskOutput<TTasks[K]>>>, TErrorMap, TMeta>;
}[keyof TTasks];
/**
* Router type containing both enqueueTask and getTaskExecution procedures.
*/
export type TasksRouter<TTasks extends AnyTasks, TInitialContext extends Context, TCurrentContext extends Context, TErrorMap extends ErrorMap, TMeta extends Meta> = {
enqueueTask: EnqueueTaskProcedure<TTasks, TInitialContext, TCurrentContext, TErrorMap, TMeta>;
getTaskExecution: GetTaskExecutionProcedure<TTasks, TInitialContext, TCurrentContext, TErrorMap, TMeta>;
wakeupSleepingTaskExecution: WakeupSleepingTaskExecutionProcedure<TTasks, TInitialContext, TCurrentContext, TErrorMap, TMeta>;
};
/**
* Creates an oRPC router with procedures for managing durable task executions.
*
* Exposes three procedures:
* - `enqueueTask` - Submit a task for execution
* - `getTaskExecution` - Get task execution status
* - `wakeupSleepingTaskExecution` - Wake up a sleeping task execution
*
* @example
* ```ts
* import { os } from '@orpc/server'
* import { DurableExecutor, InMemoryTaskExecutionsStorage } from 'durable-execution'
* import { createTasksRouter } from 'durable-execution-orpc-utils'
*
* // Create executor with storage implementation
* const executor = await DurableExecutor.make(new InMemoryTaskExecutionsStorage())
*
* // Define tasks
* const sendEmail = executor.task({
* id: 'sendEmail',
* timeoutMs: 30000,
* run: async (_, input: { to: string; subject: string }) => {
* // Send email logic here
* return { messageId: '123' }
* },
* })
*
* const waitForWebhook = executor.sleepingTask<{ webhookId: string }>({
* id: 'waitForWebhook',
* timeoutMs: 60 * 60 * 1000, // 1 hour
* })
*
* const tasks = { sendEmail, waitForWebhook }
*
* // Create router
* const tasksRouter = createTasksRouter(os, executor, tasks)
*
* // Export for use in oRPC server
* export { tasksRouter }
* ```
*
* @param osBuilder - The oRPC builder instance used to construct the procedures
* @param executor - The DurableExecutor instance that manages task execution and persistence
* @param tasks - A record of Task objects that can be enqueued and executed
* @returns A router object containing the `enqueueTask`, `getTaskExecution` and
* `wakeupSleepingTaskExecution` procedures
*/
export declare function createTasksRouter<TTasks extends AnyTasks, TInitialContext extends Context, TCurrentContext extends Context, TErrorMap extends ErrorMap, TMeta extends Meta, TBuilder extends Builder<TInitialContext, TCurrentContext, Schema<unknown, unknown>, Schema<unknown, unknown>, TErrorMap, TMeta>>(osBuilder: TBuilder, executor: DurableExecutor, tasks: TTasks): TasksRouter<TTasks, TInitialContext, TCurrentContext, TErrorMap, TMeta>;
/**
* Converts an oRPC procedure client into a durable task.
*
* Enables business logic to remain in your application while the executor manages retries and
* persistence. The task calls back to your app via RPC.
*
* Automatically handles:
* - Error mapping (HTTP to DurableExecutionError)
* - Retry logic (408, 429, 500, 502, 503, 504)
* - Error classification (retryable/non-retryable)
*
* @example
* ```ts
* import { createORPCClient } from '@orpc/client'
* import { RPCLink } from '@orpc/client/fetch'
* import { convertProcedureClientToTask } from 'durable-execution-orpc-utils'
*
* // Create client for your web app's procedures
* const webAppLink = new RPCLink({
* url: 'https://your-app.com/api/rpc',
* headers: () => ({ authorization: 'Bearer token' }),
* })
* const webAppClient = createORPCClient(webAppLink)
*
* // Convert a client procedure to a durable task
* const processPayment = convertProcedureClientToTask(
* executor,
* {
* id: 'processPayment',
* timeoutMs: 60000, // 1 minute
* retryOptions: {
* maxAttempts: 3,
* baseDelayMs: 1000,
* },
* },
* webAppClient.processPayment,
* )
*
* // Now processPayment can be enqueued and executed durably
* const handle = await executor.enqueueTask(processPayment, {
* orderId: '123',
* amount: 99.99,
* })
* ```
*
* @param executor - The DurableExecutor instance that will manage this task
* @param taskOptions - Configuration for the task including id, timeoutMs, and retry settings
* @param procedure - The oRPC client procedure to wrap as a task
* @param rest - Optional client configuration (headers, auth, etc.) for the RPC calls
* @returns A task that executes the procedure when run
*/
export declare function convertProcedureClientToTask<TProcedure extends ProcedureClient<any, AnySchema, AnySchema, ErrorMap>>(executor: DurableExecutor, taskOptions: CommonTaskOptions, procedure: TProcedure, ...rest: TProcedure extends ProcedureClient<infer TClientContext, AnySchema, AnySchema, ErrorMap> ? [options?: FriendlyClientOptions<TClientContext>] : never): TProcedure extends ProcedureClient<any, infer TInputSchema, infer TOutputSchema, ErrorMap> ? Task<InferSchemaInput<TInputSchema>, InferSchemaOutput<TOutputSchema>> : never;
//# sourceMappingURL=index.d.ts.map