# JobQueue class · @imqueue/job

Source: https://imqueue.org/api/job/latest/job.jobqueue/
Published: 2026-07-31
Author: @imqueue maintainers (https://github.com/imqueue)
Package: @imqueue/job 3.0.3 — generated reference, not hand-written

A job queue that both pushes and handles jobs in the same process — the default export, and the one to start with.

Scheduling is per job and optional: push with no options to run as soon as a worker is free, with [PushOptions.delay](https://imqueue.org/api/job/latest/job.pushoptions.delay/) to run later, and with [PushOptions.ttl](https://imqueue.org/api/job/latest/job.pushoptions.ttl/) to stop retrying after a while. Register the handler with [JobQueue.onPop()](https://imqueue.org/api/job/latest/job.jobqueue.onpop/) before [JobQueue.start()](https://imqueue.org/api/job/latest/job.jobqueue.start/) — this class insists on it, because a combined queue with no handler would enqueue work that nothing consumes.

Split the two ends into [JobQueuePublisher](https://imqueue.org/api/job/latest/job.jobqueuepublisher/) and [JobQueueWorker](https://imqueue.org/api/job/latest/job.jobqueueworker/) when they belong in different processes, which is what scaling the workers out requires.

**Signature:**

```typescript
export default class JobQueue<T> extends BaseJobQueue<JobQueue<T>, T> implements AnyJobQueueWorker<JobQueue<T>, T>, AnyJobQueuePublisher<JobQueue<T>, T> 
```
**Extends:** [BaseJobQueue](https://imqueue.org/api/job/latest/job.basejobqueue/)<[JobQueue](https://imqueue.org/api/job/latest/job.jobqueue/)<T>, T>

**Implements:** [AnyJobQueueWorker](https://imqueue.org/api/job/latest/job.anyjobqueueworker/)<[JobQueue](https://imqueue.org/api/job/latest/job.jobqueue/)<T>, T>, [AnyJobQueuePublisher](https://imqueue.org/api/job/latest/job.anyjobqueuepublisher/)<[JobQueue](https://imqueue.org/api/job/latest/job.jobqueue/)<T>, T>

## Remarks

On SIGTERM, SIGINT or SIGABRT the underlying `@imqueue/core` queue releases its watcher locks and exits the process. That is orderly, but it is not a drain: a handler still running is not awaited, so the job it was working on loses that attempt. Do the draining yourself if a half-finished job would leave a mess.

## Example


```typescript
import JobQueue from '@imqueue/job';

const queue = new JobQueue<Email>({ name: 'Email' });

queue.onPop(async (email: Email) => {
    await send(email);
});

await queue.start();

queue.push({ to: 'a@b.c', subject: 'Hi' });
```

## Constructors


| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(options)](https://imqueue.org/api/job/latest/job.jobqueue._constructor_/) |  | Creates a queue that both publishes and consumes the named job queue. |


## Methods


| Method | Modifiers | Description |
| --- | --- | --- |
| [onPop(handler)](https://imqueue.org/api/job/latest/job.jobqueue.onpop/) |  | Registers the handler called for each job popped from this queue. |
| [push(job, options)](https://imqueue.org/api/job/latest/job.jobqueue.push/) |  | Enqueues one job, optionally delayed or time-limited, refusing to enqueue without a handler. |
| [start()](https://imqueue.org/api/job/latest/job.jobqueue.start/) |  | Starts processing the job queue, refusing to start without a handler. |

