ResqueStore — node-resque Redis-backed jobs

Read this page in the documentation

ResqueStore — node-resque Redis-backed jobs Overview node-resque is a Redis-backed background-job system compatible with Ruby's Resque — not a database. A Queue enqueues jobs (a job class name plus args) into named queues, and a Worker/MultiWorker pulls jobs and runs the matching handler from a jobs map. There is no query language and no SQL-shaped access pattern. Because none of that fits the SQL-shaped Dialect interface, ResqueStore implements the minimal NoSqlStore marker interface (src/nosql/store.ts) — connection lifecycle plus a getClient() escape hatch — and exposes node-resque's real enqueue/worker operations (enqueue/process/getJob/remove/stats) directly rather than forcing them into a query(sql) shape. Identity: Property | Value | --------- | -------------- | name | 'resque' | library | 'node-resque' | Worker-scoped caching The store wraps a single producer Queue plus a Map of Workers keyed by queue name (created on process()). Handlers are accumulated into a shared jobs map ({ queueName: { perform: handler } }) that both the Queue and every Worker share. A repeat process() on the same queue name returns the existing Worker. All workers are ended and cleared on disconnect(). Lazy loading — not a hard dependency node-resque is not a hard dependency of this package. It is an optional peer, loaded lazily via require('node-resque') inside connect() rather than a top-level import. Importing this module therefore does not require the driver to be installed — it is only needed when a Resque store is actually connected. Injected client ResqueStoreOptions accepts a pre-built client — the node-resque module itself, or any stand-in exposing Queue and Worker constructors. When provided, connect() adopts it directly and does not require('node-resque'). This is how the test suite injects mocks (no driver, no network). Connection Build a store from connection options and call connect(): connect() resolves the driver, constructs new driver.Queue({ connection }, jobs), and awaits queue.connect() if the driver exposes it. The connection descriptor is reused for every Worker too. Failures are wrapped in a ConnectionError (a message containing ECONNREFUSED is normalized to 'Connection refused'). Option | Type | Purpose | ------------ | ----- | --------------------------------------------------------------------------------------------------------- | connection | any | node-resque connection descriptor (e.g. { pkg, host, port, database }) used for the Queue and every Worker. Defaults to { host: '127.0.0.1', port: 6379 }. | client | any | A pre-built node-resque module (or stand-in with Queue/Worker). When set, the driver is not required. | Injected-client form Methods Driver failures are wrapped in a DatabaseError (message Resque <action> failed: ..., preserving the original error). Using the store before connect() (or after disconnect()) throws a ConnectionError. Lifecycle Method | Signature | Behavior | ------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------- | connect | connect(): Promise<void> | Resolves the driver, constructs and connects the producer Queue (sharing the jobs map). Idempotent when already connected. Wraps failures in ConnectionError. | disconnect | disconnect(): Promise<void> | end()s every cached Worker then the Queue, clears the worker map, and drops the driver. | isConnected | isConnected(): boolean | true only when connected and a Queue is present. | getClient | getClient(): any | Returns the underlying node-resque Queue. Throws ConnectionError if not connected. | Queue operations Method | Signature | Behavior | --------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | enqueue | enqueue(queue: string, jobData: ResqueJobSpec \| string): Promise<null> | Normalizes jobData into { name, args } (a bare string is the job name with no args) and calls queue.enqueue(queue, name, args). node-resque assigns no client-visible id, so this resolves to null. | process | process(queue: string, handler: (...args: any[]) => any \| Promise<any>, opts?: any): Promise<any> | Registers handler in the shared jobs map under the queue name (as a perform function), constructs new Worker({ connection, queues: [queue], ...opts }, jobs), connects and starts it, and caches one Worker per queue name (repeat returns it). | getJob | getJob(queue: string, id: string \| number): Promise<any> | Lists queued jobs via queue.queued(queue, 0, -1) and returns the entry at index id (node-resque has no per-id lookup, so id is the 0-based index), or null. | remove | remove(queue: string, id: string): Promise<any> | Removes matching jobs via queue.del(queue, id), where id is the registered job name to delete. | stats | stats(queue: string): Promise<number> | Returns the number of jobs currently queued via queue.length(queue). | Supporting type: Example Verification status Unit / mock-verified only. The tests in tests/nosql/resque.test.ts are fully mock-driven: a fake driver module whose Queue and Worker constructors are Jest spies (with spied enqueue/queued/del/length/connect/start/end on instances) is injected via ResqueStoreOptions.client, so connect() adopts it and skips require('node-resque'). The real node-resque package is not installed, and there is no live Redis and no network in the test run. What this proves: name/library identity, Queue construction + connect(), and exposure via getClient() without loading the driver. Lifecycle: disconnect() calling end(), and ConnectionError when using the store before connecting. enqueue delegating to queue.enqueue(queue, name, args) (including the bare-string form), resolving null. process constructing a Worker with queues: [queue], registering the handler in the shared jobs map, starting it, and caching one per name. getJob returning the queued entry at an index, remove calling queue.del, stats returning queue.length. Error handling: enqueue failures wrapped in DatabaseError. What this does not prove: live execution against real Redis via node-resque. Constructor/method shapes are verified against the driver's documented contract, but end-to-end execution over the wire has not been exercised here. Related reading All data stores — the full catalogue, grouped by purpose Database types — where this sits among the 22 categories