durable-execution-storage-drizzle
Version:
Drizzle ORM storage implementation for durable-execution
833 lines • 30.4 kB
TypeScript
import { type TablesRelationalConfig } from 'drizzle-orm';
import { type MySqlDatabase, type MySqlQueryResultHKT, type MySqlQueryResultKind, type PreparedQueryHKTBase } from 'drizzle-orm/mysql-core';
import { type DurableExecutionErrorStorageValue, type TaskExecutionCloseStatus, type TaskExecutionOnChildrenFinishedProcessingStatus, type TaskExecutionsStorage, type TaskExecutionStatus, type TaskExecutionSummary, type TaskRetryOptions } from 'durable-execution';
/**
* Creates a MySQL table schema for storing durable task executions.
*
* This function generates a Drizzle ORM table definition with all necessary columns and indexes
* for the durable-execution storage layer. The table includes:
* - Task hierarchy tracking (root, parent, child relationships)
* - Execution state management (status, retries, timeouts)
* - Input/output data storage
* - Timestamp tracking for scheduling and expiration
*
* @example
* ```ts
* // In your schema file (e.g., schema.ts)
* import { createMySqlTaskExecutionsTable } from 'durable-execution-storage-drizzle'
*
* // Use default table name
* export const taskExecutions = createMySqlTaskExecutionsTable()
*
* // Or specify a custom table name
* export const myTasksTable = createMySqlTaskExecutionsTable('my_custom_task_executions')
* ```
*
* @param tableName - The name of the table to create. Defaults to 'task_executions'.
* @returns A Drizzle MySQL table definition ready for migrations.
*/
export declare function createMySqlTaskExecutionsTable(tableName?: string): import("drizzle-orm/mysql-core").MySqlTableWithColumns<{
name: string;
schema: undefined;
columns: {
id: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "id";
tableName: string;
dataType: "number";
columnType: "MySqlSerial";
data: number;
driverParam: number;
notNull: true;
hasDefault: true;
isPrimaryKey: true;
isAutoincrement: true;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
rootTaskId: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "root_task_id";
tableName: string;
dataType: "string";
columnType: "MySqlVarChar";
data: string;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
rootExecutionId: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "root_execution_id";
tableName: string;
dataType: "string";
columnType: "MySqlVarChar";
data: string;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
parentTaskId: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "parent_task_id";
tableName: string;
dataType: "string";
columnType: "MySqlVarChar";
data: string;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
parentExecutionId: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "parent_execution_id";
tableName: string;
dataType: "string";
columnType: "MySqlVarChar";
data: string;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
indexInParentChildren: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "index_in_parent_children";
tableName: string;
dataType: "number";
columnType: "MySqlInt";
data: number;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
isOnlyChildOfParent: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "is_only_child_of_parent";
tableName: string;
dataType: "boolean";
columnType: "MySqlBoolean";
data: boolean;
driverParam: number | boolean;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
isFinalizeOfParent: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "is_finalize_of_parent";
tableName: string;
dataType: "boolean";
columnType: "MySqlBoolean";
data: boolean;
driverParam: number | boolean;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
taskId: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "task_id";
tableName: string;
dataType: "string";
columnType: "MySqlVarChar";
data: string;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
executionId: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "execution_id";
tableName: string;
dataType: "string";
columnType: "MySqlVarChar";
data: string;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
isSleepingTask: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "is_sleeping_task";
tableName: string;
dataType: "boolean";
columnType: "MySqlBoolean";
data: boolean;
driverParam: number | boolean;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
sleepingTaskUniqueId: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "sleeping_task_unique_id";
tableName: string;
dataType: "string";
columnType: "MySqlVarChar";
data: string;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
retryOptions: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "retry_options";
tableName: string;
dataType: "json";
columnType: "MySqlJson";
data: TaskRetryOptions;
driverParam: string;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {
$type: TaskRetryOptions;
}>;
sleepMsBeforeRun: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "sleep_ms_before_run";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
timeoutMs: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "timeout_ms";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
areChildrenSequential: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "are_children_sequential";
tableName: string;
dataType: "boolean";
columnType: "MySqlBoolean";
data: boolean;
driverParam: number | boolean;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
input: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "input";
tableName: string;
dataType: "string";
columnType: "MySqlText";
data: string;
driverParam: string;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
executorId: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "executor_id";
tableName: string;
dataType: "string";
columnType: "MySqlVarChar";
data: string;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
status: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "status";
tableName: string;
dataType: "string";
columnType: "MySqlVarChar";
data: TaskExecutionStatus;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {
$type: TaskExecutionStatus;
}>;
isFinished: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "is_finished";
tableName: string;
dataType: "boolean";
columnType: "MySqlBoolean";
data: boolean;
driverParam: number | boolean;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
runOutput: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "run_output";
tableName: string;
dataType: "string";
columnType: "MySqlText";
data: string;
driverParam: string;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
output: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "output";
tableName: string;
dataType: "string";
columnType: "MySqlText";
data: string;
driverParam: string;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
error: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "error";
tableName: string;
dataType: "json";
columnType: "MySqlJson";
data: DurableExecutionErrorStorageValue;
driverParam: string;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {
$type: DurableExecutionErrorStorageValue;
}>;
retryAttempts: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "retry_attempts";
tableName: string;
dataType: "number";
columnType: "MySqlInt";
data: number;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
startAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "start_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
startedAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "started_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
expiresAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "expires_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
waitingForChildrenStartedAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "waiting_for_children_started_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
waitingForFinalizeStartedAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "waiting_for_finalize_started_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
finishedAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "finished_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
children: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "children";
tableName: string;
dataType: "json";
columnType: "MySqlJson";
data: TaskExecutionSummary[];
driverParam: string;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {
$type: TaskExecutionSummary[];
}>;
activeChildrenCount: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "active_children_count";
tableName: string;
dataType: "number";
columnType: "MySqlInt";
data: number;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
onChildrenFinishedProcessingStatus: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "on_children_finished_processing_status";
tableName: string;
dataType: "string";
columnType: "MySqlVarChar";
data: TaskExecutionOnChildrenFinishedProcessingStatus;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {
$type: TaskExecutionOnChildrenFinishedProcessingStatus;
}>;
onChildrenFinishedProcessingExpiresAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "on_children_finished_processing_expires_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
onChildrenFinishedProcessingFinishedAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "on_children_finished_processing_finished_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
finalize: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "finalize";
tableName: string;
dataType: "json";
columnType: "MySqlJson";
data: TaskExecutionSummary;
driverParam: string;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {
$type: TaskExecutionSummary;
}>;
closeStatus: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "close_status";
tableName: string;
dataType: "string";
columnType: "MySqlVarChar";
data: TaskExecutionCloseStatus;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: [string, ...string[]];
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {
$type: TaskExecutionCloseStatus;
}>;
closeExpiresAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "close_expires_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
closedAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "closed_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: false;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
needsPromiseCancellation: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "needs_promise_cancellation";
tableName: string;
dataType: "boolean";
columnType: "MySqlBoolean";
data: boolean;
driverParam: number | boolean;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
createdAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "created_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
updatedAt: import("drizzle-orm/mysql-core").MySqlColumn<{
name: "updated_at";
tableName: string;
dataType: "number";
columnType: "MySqlBigInt53";
data: number;
driverParam: string | number;
notNull: true;
hasDefault: false;
isPrimaryKey: false;
isAutoincrement: false;
hasRuntimeDefault: false;
enumValues: undefined;
baseColumn: never;
identity: undefined;
generated: undefined;
}, {}, {}>;
};
dialect: "mysql";
}>;
/**
* Type representing the MySQL table schema for task executions. Use this type when you need to
* reference the table structure in your code.
*/
export type TaskExecutionsMySqlTable = ReturnType<typeof createMySqlTaskExecutionsTable>;
/**
* Creates a MySQL storage adapter for durable-execution.
*
* This function creates a storage implementation that uses MySQL as the backend for persisting
* task execution state. The storage adapter handles:
* - Transactional operations for consistency
* - Row-level locking with 'FOR UPDATE SKIP LOCKED' for concurrent access
* - Efficient querying with proper indexes
* - Parent-child task relationship management
*
* @example
* ```ts
* import { drizzle } from 'drizzle-orm/mysql2'
* import mysql from 'mysql2/promise'
* import { DurableExecutor } from 'durable-execution'
* import { createMySqlTaskExecutionsTable, createMySqlTaskExecutionsStorage } from 'durable-execution-storage-drizzle'
*
* // Setup database connection
* const connection = await mysql.createConnection({
* uri: process.env.DATABASE_URL
* })
* const db = drizzle(connection)
*
* // Create table schema and storage
* const taskExecutionsTable = createMySqlTaskExecutionsTable()
* const storage = createMySqlTaskExecutionsStorage(
* db,
* taskExecutionsTable,
* (result) => result[0].affectedRows // mysql2 driver
* )
*
* // Use with DurableExecutor
* const executor = await DurableExecutor.make(storage)
* ```
*
* @example
* ```ts
* // For PlanetScale driver
* import { drizzle } from 'drizzle-orm/planetscale-serverless'
* import { Client } from '@planetscale/database'
*
* const client = new Client({
* url: process.env.DATABASE_URL
* })
* const db = drizzle(client)
*
* const storage = createMySqlTaskExecutionsStorage(
* db,
* taskExecutionsTable,
* (result) => result.rowsAffected // PlanetScale driver
* )
* ```
*
* @param db - A Drizzle MySQL database instance.
* @param taskExecutionsTable - The table created by `createMySqlTaskExecutionsTable()`.
* @param getAffectedRowsCount - A function to extract affected rows count from MySQL query
* results. This varies based on your MySQL driver (mysql2, planetscale, etc.).
* @param options - The options for the storage.
* @param options.enableTestMode - Whether to enable test mode. Defaults to false.
* @returns A TaskExecutionsStorage implementation for use with DurableExecutor.
*/
export declare function createMySqlTaskExecutionsStorage<TQueryResult extends MySqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig>(db: MySqlDatabase<TQueryResult, TPreparedQueryHKT, TFullSchema, TSchema>, taskExecutionsTable: TaskExecutionsMySqlTable, getAffectedRowsCount: (result: MySqlQueryResultKind<TQueryResult, never>) => number, options?: {
enableTestMode?: boolean;
}): TaskExecutionsStorage;
//# sourceMappingURL=mysql.d.ts.map