Skip to Content
Packages@cfxdevkit/executor

@cfxdevkit/executor

Generic background job runner with queues and scheduler.

Install

pnpm add @cfxdevkit/executor

Scope: Generic execution primitives for keeper / off-chain automation systems.

Responsibilities

  • Job queue interface (pluggable backends via createTaskQueue)
  • Retry with exponential backoff policies (via RetryPolicy and ExecuteOptions)
  • Gas-aware transaction submission (via gasPrice, maxFeePerGas, maxPriorityFeePerGas in ExecutionContext)
  • Idempotency support (via idempotencyKey in ExecuteOptions)
  • Distributed locking (via withLock)
  • Periodic polling (via createPoller)

Domain-specific automation strategies (DCA, limit orders, etc.) live in @cfxdevkit/automation and consume this package.

Installation

npm install @cfxdevkit/executor

Sub-paths

Sub-pathExports
.16 symbols

.

Types

export interface ExecutionContext { chainId: number; blockNumber: number; timestamp: number; gasPrice?: bigint; maxFeePerGas?: bigint; maxPriorityFeePerGas?: bigint; } export interface RetryPolicy { maxRetries: number; baseDelayMs: number; } export interface ExecuteOptions extends RetryPolicy { idempotencyKey?: string; context?: Partial<ExecutionContext>; timeoutMs?: number; labels?: Record<string, string>; } export interface BatchOptions extends ExecuteOptions { concurrency?: number; } export interface TaskQueueOptions extends BatchOptions { name?: string; persistent?: boolean; priorityFn?: (a: ExecutionTask<any>, b: ExecutionTask<any>) => number; } export interface PollerContext { lastExecutionTime: number; consecutiveFailures: number; } export type ExecutionTask<T> = (context: ExecutionContext) => Promise<T> | T; export type ExecutionResult<T> = { success: boolean; value?: T; error?: Error; attempts: number; }; export type PollerTask = (context: PollerContext) => Promise<void> | void; export interface Poller { start(): void; stop(): void; isRunning: boolean; }

Functions

export declare function execute<T>( task: ExecutionTask<T>, options?: ExecuteOptions ): Promise<ExecutionResult<T>>; export declare function executeBatch<T>( tasks: ReadonlyArray<ExecutionTask<T>>, options?: BatchOptions ): Promise<Array<ExecutionResult<T>>>; export declare function createTaskQueue( options?: TaskQueueOptions ): { enqueue<T>(task: ExecutionTask<T>, options?: ExecuteOptions): Promise<ExecutionResult<T>>; start(): void; stop(): void; isRunning: boolean; }; export declare function createPoller( task: PollerTask, intervalMs: number ): Poller; export declare function withLock<T>( key: string, task: () => Promise<T> | T ): Promise<T>; export declare const __packageName: "@cfxdevkit/executor";

Usage

Single execution with retry and idempotency

import { execute } from '@cfxdevkit/executor'; const result = await execute( async (ctx) => { // Perform on-chain operation using ctx.gasPrice, etc. return 'success'; }, { maxRetries: 3, baseDelayMs: 500, idempotencyKey: 'tx-0x123', context: { chainId: 1, blockNumber: 18000000 } } );

Batch execution

import { executeBatch } from '@cfxdevkit/executor'; const results = await executeBatch( [ async (ctx) => task1(ctx), async (ctx) => task2(ctx), ], { maxRetries: 2, context: { chainId: 1 } } );

Task queue with concurrency control

import { createTaskQueue } from '@cfxdevkit/executor'; const queue = createTaskQueue({ concurrency: 5, maxRetries: 3, baseDelayMs: 250, name: 'automation-queue' }); queue.start(); await queue.enqueue(async (ctx) => { // Enqueued task }); // Later... queue.stop();

Poller for periodic checks

import { createPoller } from '@cfxdevkit/executor'; const poller = createPoller( async (ctx) => { // Check condition every 10s; ctx.lastExecutionTime and ctx.consecutiveFailures available }, 10_000 ); poller.start(); // poller.stop();

Distributed locking

import { withLock } from '@cfxdevkit/executor'; const result = await withLock('dca:account-0x...', async () => { // Critical section — only one instance runs at a time });

API Reference

See API.md for the full public surface.

Tier

Tier 0 — framework — Must not runtime-import from any higher tier.

API Reference

.

Usage

import { execute, executeBatch, createTaskQueue } from '@cfxdevkit/executor'; const task = async (ctx) => { return "success"; }; const result = await execute(task); const batchResults = await executeBatch([task, task]);
// Package name identifier for runtime introspection. export declare const __packageName: "@cfxdevkit/executor"; // Metadata and runtime information for the current task execution. export interface ExecutionContext { // Unique ID for this execution instance. id: string; // Timestamp when the execution started. startTime: number; // Optional labels attached to the task. labels?: Record<string, string>; // Reference to the queue if executed within a queue context. queueName?: string; } // Defines how many times a failed task should be retried and the delay between retries. export interface RetryPolicy { // Maximum number of retry attempts after initial failure. maxRetries: number; // Base delay in milliseconds between retries (applied with exponential backoff). baseDelayMs: number; } // Options such as timeout, labels, and retry behavior for a single task. export interface ExecuteOptions extends RetryPolicy { // Maximum duration in milliseconds before the task is considered timed out. timeoutMs?: number; // Arbitrary key-value metadata to attach to the task for tracing/debugging. labels?: Record<string, string>; } // Options inherited from ExecuteOptions, plus batch-specific settings like concurrency. export interface BatchOptions extends ExecuteOptions { // Maximum number of tasks allowed to run concurrently in the batch. concurrency?: number; } // Queue-specific settings including concurrency, priority, and persistence. export interface TaskQueueOptions extends BatchOptions { // Name of the queue for identification and logging. name?: string; // Whether to persist queue state (e.g., to disk or remote store). persistent?: boolean; // Optional priority function to reorder pending tasks. priorityFn?: (a: ExecutionTask<any>, b: ExecutionTask<any>) => number; } // Runtime context for periodic tasks, including last execution time and metadata. export interface PollerContext { // Timestamp of the last successful execution (0 if none yet). lastExecutionTime: number; // Number of consecutive failures since last success. failureCount: number; // Optional metadata passed at poller creation. metadata?: Record<string, unknown>; } // Interface representing a running poller instance with start/stop capabilities. export interface Poller { // Start the poller and begin executing the task at the specified interval. start(): void; // Stop the poller and cancel any pending executions. stop(): void; // Whether the poller is currently running. isRunning(): boolean; } // A function that performs a unit of work and receives execution context. export type ExecutionTask<T> = (context: ExecutionContext) => Promise<T> | T; // Contains the result value, status (success/failure), and optional error details. export type ExecutionResult<T> = { // The value returned by the task on success. value?: T; // Whether the execution succeeded. success: boolean; // Error object if the execution failed. error?: Error; }; // A function that performs a periodic background task and receives poller context. export type PollerTask = (context: PollerContext) => Promise<void> | void; // Executes a single task with the provided options. export declare function execute<T>(task: ExecutionTask<T>, options?: ExecuteOptions): Promise<ExecutionResult<T>>; // Executes a collection of tasks in a batch. export declare function executeBatch<T>(tasks: ReadonlyArray<ExecutionTask<T>>, options?: BatchOptions): Promise<Array<ExecutionResult<T>>>; // Initializes a new task queue. export declare function createTaskQueue(options?: TaskQueueOptions): { // Enqueue a task to be processed by the queue. enqueue<T>(task: ExecutionTask<T>, options?: ExecuteOptions): void; // Start processing tasks from the queue. start(): void; // Stop processing tasks and wait for in-flight tasks to finish. stop(): Promise<void>; // Number of tasks currently pending in the queue. pendingCount(): number; // Number of tasks currently being processed. activeCount(): number; }; // Initializes a new poller for periodic tasks. export declare function createPoller(task: PollerTask, intervalMs: number): Poller; // Executes a task within a distributed lock. export declare function withLock<T>(key: string, task: () => Promise<T> | T): Promise<T>;
Last updated on