BeanstalkdStore — Beanstalkd work queue

Read this page in the documentation

BeanstalkdStore — Beanstalkd work queue Overview Beanstalkd is a simple, fast work queue, not a database. There is no query language, no rows, and no SQL-shaped access pattern. Producers put jobs (opaque byte payloads) into named tubes; workers reserve jobs from the tubes they watch, do the work, then delete (destroy) them. Because none of that fits the SQL-shaped Dialect interface, BeanstalkdStore implements the minimal NoSqlStore marker interface (src/nosql/store.ts) — connection lifecycle plus a getClient() escape hatch — and exposes Beanstalkd's real queue operations (enqueue/process/getJob/remove/stats) directly rather than forcing them into a query(sql) shape. Identity: Property | Value | --------- | -------------- | name | 'beanstalkd' | library | 'fivebeans' | The store is built on the fivebeans driver, whose client exposes a callback-style API (client.put(pri, delay, ttr, payload, cb), etc.). This store promisifies those calls internally, so its own surface is promise-based. Lazy loading — not a hard dependency fivebeans is not a hard dependency of this package. It is an optional peer, loaded lazily via require('fivebeans') 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 Beanstalkd store is actually connected. Injected client BeanstalkdStoreOptions accepts a pre-built client. When provided, connect() adopts it directly and does not require('fivebeans'). This is how the test suite injects a mock client (no driver, no network), and how callers can supply a custom-configured fivebeans client. Connection Build a store from connection options and call connect(): When no injected client is present, connect() lazy-requires fivebeans, constructs new fivebeans.client(host, port), and waits for the client's 'connect' event (rejecting on 'error'). Failures are wrapped in a ConnectionError (a message containing ECONNREFUSED is normalized to 'Connection refused'). Option | Type | Purpose | -------- | -------- | ------------------------------------------------------------- | host | string | Beanstalkd host. Defaults to '127.0.0.1'. | port | number | Beanstalkd port. Defaults to 11300. | client | any | A pre-built fivebeans client to adopt directly (mock or custom). When set, the driver is not required. | Injected-client form Methods Driver failures are wrapped in a DatabaseError (message Beanstalkd <action> failed: ..., preserving the original error). Using the client before connect() (or after disconnect()) throws a ConnectionError. Lifecycle Method | Signature | Behavior | -------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------- | connect | connect(): Promise<void> | Adopts an injected client, otherwise lazy-requires fivebeans and connects a new client. Idempotent when already connected. Wraps failures in ConnectionError. | disconnect | disconnect(): Promise<void> | Stops any running process() reserve loop, then calls the client's end() (or quit()) and clears state. | isConnected | isConnected(): boolean | true only when connected and a client is present. | getClient | getClient(): any | Returns the underlying fivebeans client. Throws ConnectionError if not connected. | Queue operations Method | Signature | Behavior | --------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | enqueue | enqueue(queue: string, jobData: unknown, opts?: BeanstalkdPutOptions): Promise<string> | Selects the tube via use(queue), then puts the payload (JSON-serialized unless already a string) with the given priority/delay/ttr. Returns the server-assigned job id. | process | process(queue: string, handler: (job: BeanstalkdJob) => void \| Promise<void>): Promise<void> | watches the tube, then fires a fire-and-forget loop that reserves jobs and invokes handler(job); after the handler resolves the job is destroyed. The loop self-terminates on disconnect(). | getJob | getJob(queue: string, id: string): Promise<BeanstalkdJob \| null> | peeks a job by id, returning { id, payload } or null. A NOTFOUND error is treated as null. | remove | remove(queue: string, id: string): Promise<void> | Deletes (destroys) a job by id. | stats | stats(queue: string): Promise<any> | Returns per-tube statistics (stats-tube), e.g. ready/reserved/buried counts. | Supporting types: Example Verification status Unit / mock-verified only. The tests in tests/nosql/beanstalkd.test.ts are fully mock-driven: a fake fivebeans client whose callback-style methods (use/put/watch/reserve/destroy/peek/statstube/end) are Jest spies is injected via BeanstalkdStoreOptions.client, so connect() adopts it and skips require('fivebeans'). The real fivebeans package is not installed, and there is no live Beanstalkd server and no network in the test run. What this proves: name/library identity and injected-client adoption without loading the driver. Lifecycle: idempotent double-connect(), disconnect() calling end(), and ConnectionError when using the client before connecting. enqueue calling use then put with mapped priority/delay/ttr (and defaults 0/0/60), returning the id. process watching the tube and reserving/destroying a delivered job; getJob peeking; remove destroying; stats reading stats-tube. Error handling: driver failures wrapped in DatabaseError. What this does not prove: live execution against a real Beanstalkd server. Command/callback 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