pg-boss
Version:
Queueing jobs in Postgres from Node.js like a boss
470 lines • 14.2 kB
TypeScript
export type JobStates = {
created: 'created';
retry: 'retry';
active: 'active';
completed: 'completed';
cancelled: 'cancelled';
failed: 'failed';
};
export type Events = {
error: 'error';
warning: 'warning';
wip: 'wip';
stopped: 'stopped';
bam: 'bam';
};
export interface IDatabase {
executeSql(text: string, values?: unknown[]): Promise<{
rows: any[];
}>;
}
export interface DatabaseOptions {
application_name?: string;
database?: string;
user?: string;
password?: string | (() => string | Promise<string>);
host?: string;
port?: number;
schema?: string;
ssl?: any;
connectionString?: string;
max?: number;
db?: IDatabase;
connectionTimeoutMillis?: number;
}
export interface SchedulingOptions {
schedule?: boolean;
clockMonitorIntervalSeconds?: number;
cronWorkerIntervalSeconds?: number;
cronMonitorIntervalSeconds?: number;
}
export interface MaintenanceOptions {
supervise?: boolean;
migrate?: boolean;
createSchema?: boolean;
warningSlowQuerySeconds?: number;
warningQueueSize?: number;
superviseIntervalSeconds?: number;
maintenanceIntervalSeconds?: number;
queueCacheIntervalSeconds?: number;
monitorIntervalSeconds?: number;
persistWarnings?: boolean;
warningRetentionDays?: number;
bamIntervalSeconds?: number;
}
export interface Migration {
release: string;
version: number;
previous: number;
install: string[];
async?: string[];
uninstall?: string[];
}
export interface ConstructorOptions extends DatabaseOptions, SchedulingOptions, MaintenanceOptions {
__test__enableSpies?: boolean;
}
export interface ResolvedConstructorOptions extends ConstructorOptions {
schema: string;
monitorIntervalSeconds: number;
cronMonitorIntervalSeconds: number;
maintenanceIntervalSeconds: number;
bamIntervalSeconds: number;
}
/**
* Options for a queue. All retry, expiration, and retention options set on a
* queue will be inherited by each job in the queue unless they are overridden.
*/
export interface QueueOptions {
/**
* How many seconds a job may be in active state before being retried or
* failed. Must be >=1. The default is 15 minutes.
* @default 900
*/
expireInSeconds?: number;
/**
* How many seconds a job may be in created or retry state before it's
* deleted. Must be >=1. The default is 14 days.
* @default 1209600
*/
retentionSeconds?: number;
/**
* How long a job should be retained in the database after it's completed. Set
* to `0` to never delete completed jobs. The default is 7 days.
* @default 604800
*/
deleteAfterSeconds?: number;
/**
* Number of times a job is allowed to be retried before it is marked as
* failed.
* @default 2
*/
retryLimit?: number;
/**
* Delay between retries of failed jobs, in seconds.
* @default 0
*/
retryDelay?: number;
/**
* Enables exponential backoff retries based on `retryDelay` instead of a
* fixed delay. Sets initial `retryDelay` to 1 if not set.
*
* A simplified function to get the delay between runs is: `retryDelay * 2 ^ retryCount`
* with some jitter.
*
* The function used to determine the backoff delay is:
* ```js
* Math.min(retryDelayMax, retryDelay * (2 ** Math.Min(16, retryCount) / 2 + 2 Math.Min(16, retryCount) / 2 * Math.random()))
* ```
* @default false
*/
retryBackoff?: boolean;
/**
* Maximum delay between retries of failed jobs, in seconds. Only used when
* `retryBackoff` is `true`. The default is no limit.
*/
retryDelayMax?: number;
/**
* Expected heartbeat interval in seconds. When set, workers must send periodic
* heartbeats. If no heartbeat is received within this interval, the monitor will
* fail/retry the job. Must be >= 10. NULL = heartbeat disabled (default).
*/
heartbeatSeconds?: number;
}
export interface GroupOptions {
id: string;
tier?: string;
}
export interface GroupConcurrencyConfig {
default: number;
tiers?: Record<string, number>;
}
export interface JobOptions {
id?: string;
priority?: number;
startAfter?: number | string | Date;
singletonKey?: string;
singletonSeconds?: number;
singletonNextSlot?: boolean;
keepUntil?: number | string | Date;
group?: GroupOptions;
deadLetter?: string;
}
export interface ConnectionOptions {
db?: IDatabase;
}
export interface CompleteOptions extends ConnectionOptions {
includeQueued?: boolean;
}
export interface FindJobsOptions extends ConnectionOptions {
id?: string;
key?: string;
data?: object;
queued?: boolean;
}
export type InsertOptions = ConnectionOptions & {
returnId?: boolean;
};
export type SendOptions = JobOptions & QueueOptions & ConnectionOptions;
/**
* The queue policy dictates how jobs are allowed to be queued and processed.
*
* - `standard` supports all standard features such as deferral, priority, and
* throttling.
*
* - `short` only allows 1 job to be queued, unlimited active. Can be extended
* with `singletonKey`.
*
* - `singleton` only allows 1 job to be active, unlimited queued. Can be
* extended with `singletonKey`.
*
* - `stately` offers a combination of `short` and `singleton`; only allows 1
* job per state, queued and/or active. Can be extended with `singletonKey`.
*
* - `exclusive` only allows 1 job to be queued or active. Can be extended with
* singletonKey`.
*
* - `key_strict_fifo` ensures strict FIFO ordering per `singletonKey`. Requires
* `singletonKey` on every job. Blocks processing of jobs with the same key
* while any job with that key is active, in retry, or failed.
*/
export type QueuePolicy = 'standard' | 'short' | 'singleton' | 'stately' | 'exclusive' | 'key_strict_fifo' | (string & {});
export interface Queue extends QueueOptions {
/**
* The name of the queue.
*/
name: string;
/**
* The policy for the queue.
* @default 'standard'
*/
policy?: QueuePolicy;
/**
* If set to true, a dedicated table will be created in the partition scheme.
* This is more useful for a large queue in order to keep it from being a
* "noisy neighbor".
* @default false
*/
partition?: boolean;
/**
* The name of the queue's dead letter queue. When a job fails after all
* retries, the job's payload will be copied into said queue, copying the same
* retention and retry configuration as the original job.
*/
deadLetter?: string;
/**
* The number of jobs allowed to exist in the created or retry state before
* emitting a warning event.
*/
warningQueueSize?: number;
/**
* Expected heartbeat interval in seconds for jobs in this queue.
* When set, workers must send periodic heartbeats. NULL = heartbeat disabled (default).
*/
heartbeatSeconds?: number;
}
export interface QueueResult extends Queue {
deferredCount: number;
queuedCount: number;
activeCount: number;
totalCount: number;
table: string;
createdOn: Date;
updatedOn: Date;
singletonsActive: string[] | null;
}
export type ScheduleOptions = SendOptions & {
tz?: string;
key?: string;
};
export interface JobPollingOptions {
/**
* Interval to check for new jobs, in seconds. Must be >= `0.5` (500 ms).
* @default 2
*/
pollingIntervalSeconds?: number;
}
export interface JobFetchOptions {
/**
* If `true`, all job metadata will be included in the returned job object.
* @default false
*/
includeMetadata?: boolean;
/**
* Allow jobs with a higher priority to be fetched before jobs with lower or
* no priority.
* @default true
*/
priority?: boolean;
/**
* Fetch jobs in the order they were created. Set to `false` to disable this
* sorting and improve performance when the order of jobs does not matter.
* @default true
*/
orderByCreatedOn?: boolean;
/**
* The number of jobs to fetch.
* @default 1
*/
batchSize?: number;
/**
* Fetch jobs even if they have a `startAfter` timestamp in the future.
* @default false
*/
ignoreStartAfter?: boolean;
/**
* Only fetch jobs with a priority greater than or equal to this value.
* Useful for reserving worker capacity exclusively for higher-priority jobs.
* Must be an integer. If both `minPriority` and `maxPriority` are set,
* `minPriority` must be less than or equal to `maxPriority`.
*/
minPriority?: number;
/**
* Only fetch jobs with a priority less than or equal to this value.
* Useful for workers dedicated to lower-priority background work.
* Must be an integer. If both `minPriority` and `maxPriority` are set,
* `minPriority` must be less than or equal to `maxPriority`.
*/
maxPriority?: number;
}
export interface WorkConcurrencyOptions {
/**
* Number of workers to spawn for this queue (per-node).
* Each worker polls and processes jobs independently.
*/
localConcurrency?: number;
/**
* Limit concurrent jobs per group within this node (in-memory tracking).
* No database overhead. Does not coordinate across nodes.
*/
localGroupConcurrency?: number | GroupConcurrencyConfig;
/**
* Limit concurrent jobs per group globally across all nodes (database tracking).
* Coordinates across distributed deployments via database queries.
*/
groupConcurrency?: number | GroupConcurrencyConfig;
}
export type WorkOptions = JobFetchOptions & JobPollingOptions & WorkConcurrencyOptions & {
/**
* Custom heartbeat refresh interval in seconds. Defaults to `heartbeatSeconds / 2`.
* Must be strictly less than `heartbeatSeconds`.
*/
heartbeatRefreshSeconds?: number;
};
export interface FetchGroupConcurrencyOptions {
groupConcurrency?: number | GroupConcurrencyConfig;
ignoreGroups?: string[] | null;
}
export type FetchOptions = JobFetchOptions & ConnectionOptions & FetchGroupConcurrencyOptions;
export interface ResolvedWorkOptions extends WorkOptions {
pollingInterval: number;
}
export interface WorkHandler<ReqData, ResData = any> {
(job: Job<ReqData>[]): Promise<ResData>;
}
export interface WorkWithMetadataHandler<ReqData, ResData = any> {
(job: JobWithMetadata<ReqData>[]): Promise<ResData>;
}
export interface Request {
name: string;
data?: object;
options?: SendOptions;
}
export interface Schedule {
name: string;
key: string;
cron: string;
timezone: string;
data?: object;
options?: SendOptions;
}
export interface Job<T = object> {
id: string;
name: string;
data: T;
expireInSeconds: number;
heartbeatSeconds: number | null;
signal: AbortSignal;
groupId?: string | null;
groupTier?: string | null;
}
export interface JobWithMetadata<T = object> extends Job<T> {
priority: number;
state: 'created' | 'retry' | 'active' | 'completed' | 'cancelled' | 'failed';
retryLimit: number;
retryCount: number;
retryDelay: number;
retryBackoff: boolean;
retryDelayMax?: number;
startAfter: Date;
startedOn: Date;
singletonKey: string | null;
singletonOn: Date | null;
expireInSeconds: number;
deleteAfterSeconds: number;
createdOn: Date;
completedOn: Date | null;
keepUntil: Date;
policy: QueuePolicy;
heartbeatOn: Date | null;
heartbeatSeconds: number | null;
deadLetter: string;
output: object;
}
export interface JobInsert<T = object> {
id?: string;
data?: T;
priority?: number;
retryLimit?: number;
retryDelay?: number;
retryBackoff?: boolean;
retryDelayMax?: number;
startAfter?: number | string | Date;
singletonKey?: string;
singletonSeconds?: number;
expireInSeconds?: number;
deleteAfterSeconds?: number;
retentionSeconds?: number;
heartbeatSeconds?: number;
group?: GroupOptions;
deadLetter?: string;
}
export type WorkerState = 'created' | 'active' | 'stopping' | 'stopped';
export interface WipData {
id: string;
workId: string;
name: string;
options: WorkOptions;
state: WorkerState;
count: number;
createdOn: number;
lastFetchedOn: number | null;
lastJobStartedOn: number | null;
lastJobEndedOn: number | null;
lastJobDuration: number | null;
lastError: object | null;
lastErrorOn: number | null;
}
export interface StopOptions {
close?: boolean;
graceful?: boolean;
timeout?: number;
}
export interface OffWorkOptions {
id?: string;
wait?: boolean;
}
export interface EventsMixin extends NodeJS.EventEmitter {
events: Record<string, string>;
}
export interface FunctionsMixin {
functions: Function[];
}
export type UpdateQueueOptions = Omit<Queue, 'name' | 'partition' | 'policy'>;
export interface Warning {
message: string;
data: object;
}
export type WarningType = 'slow_query' | 'queue_backlog' | 'clock_skew';
export interface PersistedWarning {
id: number;
type: WarningType;
message: string;
data: object;
createdOn: Date;
}
export interface CommandResponse {
}
export interface BamEntry {
id: string;
name: string;
version: number;
status: 'pending' | 'in_progress' | 'completed' | 'failed';
queue?: string;
table: string;
command: string;
error?: string;
createdOn: Date;
startedOn?: Date;
completedOn?: Date;
}
export interface BamStatusSummary {
status: 'pending' | 'in_progress' | 'completed' | 'failed';
count: number;
lastCreatedOn: Date;
}
export interface BamEvent {
id: string;
name: string;
status: string;
queue?: string;
table: string;
error?: string;
}
export type PgBossEventMap = {
error: [error: Error];
warning: [warning: Warning];
wip: [data: WipData[]];
stopped: [];
bam: [data: BamEvent];
};
//# sourceMappingURL=types.d.ts.map