@zizq-labs/zizq 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,10 +7,12 @@ API.
7
7
  This is the official Zizq client library for Node.js, written in TypeScript.
8
8
 
9
9
  [![CI](https://github.com/zizq-labs/zizq-node/actions/workflows/ci.yml/badge.svg)](https://github.com/zizq-labs/zizq-node/actions/workflows/ci.yml)
10
+ [![npm version](https://img.shields.io/npm/v/@zizq-labs/zizq.svg)](https://www.npmjs.com/package/@zizq-labs/zizq)
10
11
 
11
12
  ## Features
12
13
 
13
14
  * Concurrent async-based worker
15
+ * Plain handler functions, or composable Job Functions with attached defaults
14
16
  * Enqueue and process jobs from one language to another
15
17
  * Arbitrary named queues
16
18
  * Granular job priorities
@@ -29,7 +31,7 @@ This is the official Zizq client library for Node.js, written in TypeScript.
29
31
 
30
32
  Install it with your package manager of choice:
31
33
 
32
- ``` shell
34
+ ```shell
33
35
  npm install @zizq-labs/zizq
34
36
  ```
35
37
 
@@ -39,29 +41,123 @@ Or:
39
41
  yarn add @zizq-labs/zizq
40
42
  ```
41
43
 
42
- ## Example
44
+ Node **22.19 or newer** is required. Client and server share version
45
+ numbers — keep the client's major/minor at or below the server's.
43
46
 
44
- > [!TIP]
45
- > There is also a composable function-based convenience wrapper available. Read
46
- > the documentation on
47
- > [Handler Functions](https://zizq.io/docs/clients/node/handlers.html) for more
48
- > info
47
+ ## Configuration
49
48
 
50
- Enqueueing a job.
49
+ A `Client` instance is the configuration — there is no global object. The
50
+ defaults talk to a server at `http://localhost:7890`, which is fine for local
51
+ development. For anything else, pass the URL (and TLS, if needed) when
52
+ constructing the client:
51
53
 
52
54
  ```ts
53
- import { Client, enqueue } from "@zizq-labs/zizq";
55
+ import fs from "node:fs";
56
+ import { Client } from "@zizq-labs/zizq";
54
57
 
55
- const client = new Client({ url: "http://localhost:7890" });
58
+ const client = new Client({
59
+ url: "https://zizq.your.network:7890",
60
+ tls: {
61
+ ca: fs.readFileSync("/path/to/server-ca-cert.pem"),
62
+ },
63
+ });
64
+ ```
65
+
66
+ For mutual TLS, add `cert` and `key` to the `tls` object (both PEM-encoded
67
+ strings or `Buffer`s).
68
+
69
+ > [!CAUTION]
70
+ > If your server is exposed directly to the internet, it should require
71
+ > mutual TLS — otherwise anybody can talk to it.
72
+
73
+ ## Usage
74
+
75
+ > [!TIP]
76
+ > This README is an overview. The
77
+ > [full documentation](https://zizq.io/docs/clients/node/) covers each
78
+ > feature in depth — handler patterns, job querying, unique jobs, and more.
56
79
 
57
- await enqueue(client, {
80
+ ### Enqueuing jobs
81
+
82
+ The simplest enqueue takes a `type`, `queue`, and `payload`. The Zizq server
83
+ returns the created job, with its `id`, `status`, `readyAt` and other
84
+ metadata:
85
+
86
+ ```ts
87
+ const job = await client.enqueue({
58
88
  type: "send_email",
59
89
  queue: "emails",
60
- payload: { to: "user@example.com" },
90
+ payload: { userId: 42, template: "welcome" },
91
+ });
92
+ job.id; // "03fu0wm75gxgmfyfplwvazhex"
93
+ ```
94
+
95
+ Per-call options override server defaults — set `priority`, `readyAt` (to
96
+ schedule a job in the future), `retryLimit`, `backoff`, or `retention`
97
+ inline. `client.enqueueBulk(inputs)` submits many jobs atomically in a
98
+ single HTTP request, across queues and types:
99
+
100
+ ```ts
101
+ await client.enqueueBulk([
102
+ { type: "send_email", queue: "emails", payload: { userId: 1 } },
103
+ { type: "send_email", queue: "emails", payload: { userId: 2 } },
104
+ ]);
105
+ ```
106
+
107
+ ### Defining handlers
108
+
109
+ A handler is an `async` function that accepts a `job` and either resolves
110
+ (the worker acks it as successful) or throws (the worker reports a failure
111
+ and the server retries per the backoff policy). The simplest version is a
112
+ `switch` on `job.type`:
113
+
114
+ ```ts
115
+ async function handler(job) {
116
+ switch (job.type) {
117
+ case "send_email":
118
+ return sendEmail(job.payload);
119
+ case "generate_report":
120
+ return generateReport(job.payload);
121
+ default:
122
+ throw new Error(`unexpected job type: ${job.type}`);
123
+ }
124
+ }
125
+ ```
126
+
127
+ For a more composable style, the client ships `buildHandler` — pass in your
128
+ job functions and you get back a handler that dispatches on the function
129
+ name. Each function can also carry `zizqOptions` with its own defaults
130
+ (queue, priority, backoff, retention, uniqueness), so enqueuing later only
131
+ needs the payload:
132
+
133
+ ```ts
134
+ import { buildHandler } from "@zizq-labs/zizq";
135
+
136
+ async function sendEmail(payload, job) {
137
+ // ...
138
+ }
139
+ sendEmail.zizqOptions = { queue: "emails", priority: 100 };
140
+
141
+ async function generateReport(payload) {
142
+ // ...
143
+ }
144
+ generateReport.zizqOptions = { queue: "reports" };
145
+
146
+ const handler = buildHandler([sendEmail, generateReport]);
147
+
148
+ // Job functions can be enqueued directly — the queue and other defaults
149
+ // come from the function's zizqOptions.
150
+ await client.enqueue({
151
+ type: sendEmail,
152
+ payload: { userId: 42, template: "welcome" },
61
153
  });
62
154
  ```
63
155
 
64
- A very basic worker with a custom handler.
156
+ ### Running a worker
157
+
158
+ A `Worker` streams jobs from the server, dispatches them through your
159
+ handler with bounded concurrency, batches acks, and reconnects on transient
160
+ failures. `worker.run()` blocks until the worker stops:
65
161
 
66
162
  ```ts
67
163
  import { Client, Worker } from "@zizq-labs/zizq";
@@ -71,16 +167,8 @@ const client = new Client({ url: "http://localhost:7890" });
71
167
  const worker = new Worker({
72
168
  client,
73
169
  concurrency: 25,
74
- queues: ["emails"],
75
- handler: async (job) => {
76
- switch (job.type) {
77
- case "send_email":
78
- console.log(`sending email using payload ${JSON.stringify(job.payload)}`);
79
- break;
80
- default:
81
- throw new Error(`unknown job type: ${job.type}`);
82
- }
83
- },
170
+ queues: ["emails", "payments"],
171
+ handler,
84
172
  });
85
173
 
86
174
  process.on("SIGINT", () => worker.stop());
@@ -89,6 +177,48 @@ process.on("SIGTERM", () => worker.stop());
89
177
  await worker.run();
90
178
  ```
91
179
 
180
+ `worker.stop()` waits for in-flight handlers to settle and flushes pending
181
+ acks before returning. To put a deadline on shutdown, schedule
182
+ `worker.kill()` after a timeout — any handlers still running continue to
183
+ completion (Node can't cancel promises), but their acks are not flushed, so
184
+ the server re-dispatches those jobs to another worker. No jobs are lost.
185
+
186
+ ### Recurring jobs (cron)
187
+
188
+ Define a cron schedule somewhere in your application startup.
189
+ Registrations are idempotent — every process can safely call the same
190
+ `register()`, and Zizq keeps the server-side schedule in sync by adding,
191
+ replacing, and removing entries as the definition changes. Cron requires
192
+ a Pro license on the server.
193
+
194
+ ```ts
195
+ import { sendDailyDigest } from "./handlers";
196
+
197
+ await client.cron("maintenance").register({
198
+ timezone: "Europe/London",
199
+ entries: [
200
+ {
201
+ name: "refresh_warehouse",
202
+ expression: "*/15 * * * *",
203
+ type: "refresh_warehouse",
204
+ queue: "data_warehouse",
205
+ payload: { incremental: true },
206
+ },
207
+ {
208
+ name: "daily_digest",
209
+ expression: "0 9 * * *",
210
+ type: sendDailyDigest, // Job Functions are accepted directly
211
+ payload: {},
212
+ },
213
+ ],
214
+ });
215
+ ```
216
+
217
+ Once defined, schedules can be inspected and managed via
218
+ `client.cron("maintenance")` — `get()` to read the current state,
219
+ `pause()`/`resume()` at the schedule or per-entry level, and `delete()`
220
+ to remove a schedule entirely.
221
+
92
222
  ## Resources
93
223
 
94
224
  * [Node.js Client Docs](https://zizq.io/docs/clients/node/)
@@ -103,3 +233,7 @@ If you need help using Zizq,
103
233
  [create an issue](https://github.com/zizq-labs/zizq-node/issues) on the
104
234
  [zizq-node](https://github.com/zizq-labs/zizq-node) repo. Feedback is very
105
235
  welcome.
236
+
237
+ ## License
238
+
239
+ MIT — see [LICENSE](LICENSE).
package/dist/client.d.ts CHANGED
@@ -34,8 +34,8 @@ import { type Dispatcher } from "undici";
34
34
  import { Job, JobPage, ErrorRecord, ErrorPage, CronGroup, CronEntry } from "./resources.ts";
35
35
  import { JobQuery, type JobQueryOptions } from "./query.ts";
36
36
  import { CronHandle } from "./cron.ts";
37
- export type { JobStatus, SortDirection, UniqueScope, BackoffConfig, RetentionConfig, EnqueueOptions, FailureOptions, UpdateJobOptions, Format, TakeOptions, ListJobsOptions, ListErrorsOptions, UpdateAllJobsOptions, JobFilter, DeleteAllJobsOptions, CronEntryInput, ReplaceCronGroupOptions, } from "./types.ts";
38
- import type { EnqueueOptions, FailureOptions, UpdateJobOptions, Format, TakeOptions, ListJobsOptions, ListErrorsOptions, UpdateAllJobsOptions, JobFilter, DeleteAllJobsOptions, CronEntryInput, ReplaceCronGroupOptions } from "./types.ts";
37
+ export type { JobStatus, SortDirection, UniqueScope, BackoffConfig, RetentionConfig, EnqueueOptions, EnqueueInput, FailureOptions, UpdateJobOptions, Format, TakeOptions, ListJobsOptions, ListErrorsOptions, UpdateAllJobsOptions, JobFilter, DeleteAllJobsOptions, CronEntryInput, ReplaceCronGroupOptions, } from "./types.ts";
38
+ import type { EnqueueOptions, EnqueueInput, FailureOptions, UpdateJobOptions, Format, TakeOptions, ListJobsOptions, ListErrorsOptions, UpdateAllJobsOptions, JobFilter, DeleteAllJobsOptions, CronEntryInput, ReplaceCronGroupOptions } from "./types.ts";
39
39
  export { Job, JobPage, ErrorRecord, ErrorPage, CronGroup, CronEntry, type JobData, type ErrorRecordData, type CronGroupData, type CronEntryData, } from "./resources.ts";
40
40
  /** Response shape for `GET /health`. */
41
41
  interface HealthResponse {
@@ -82,6 +82,35 @@ export interface ClientOptions {
82
82
  format?: Format;
83
83
  /** TLS configuration for HTTPS connections. */
84
84
  tls?: TlsOptions;
85
+ /**
86
+ * Connect timeout in milliseconds — deadline for the TCP/TLS
87
+ * handshake. Applies to every pool.
88
+ *
89
+ * Default: 10000 (10s).
90
+ */
91
+ connectTimeout?: number;
92
+ /**
93
+ * Per-read timeout in milliseconds for API traffic (enqueue,
94
+ * queries, mutations — anything that isn't the long-lived
95
+ * `take()` stream). Bounds the time between consecutive bytes
96
+ * received from the server.
97
+ *
98
+ * Default: 30000 (30s).
99
+ */
100
+ readTimeout?: number;
101
+ /**
102
+ * Per-read timeout in milliseconds for the long-lived
103
+ * `take()` stream consumed by {@link Worker}. The server's
104
+ * heartbeats (default ~3s) reset the clock on each frame, so this
105
+ * only fires when the connection has actually gone silent.
106
+ * Triggers a Worker reconnect via the standard error path.
107
+ *
108
+ * Should be comfortably above the server's heartbeat interval to
109
+ * avoid false-positive disconnects.
110
+ *
111
+ * Default: 30000 (30s).
112
+ */
113
+ streamIdleTimeout?: number;
85
114
  /** @internal For testing — override the HTTP dispatcher. */
86
115
  dispatcher?: Dispatcher;
87
116
  }
@@ -164,10 +193,14 @@ export declare class Client {
164
193
  /**
165
194
  * Enqueue a single job.
166
195
  *
196
+ * The `type` field accepts either a string job type name or a function
197
+ * reference with attached `zizqOptions`. When a function is provided,
198
+ * its `zizqOptions` supplies defaults for `queue`, `priority`, etc.
199
+ *
167
200
  * @returns The created job, including its server-assigned `id` and `status`.
168
201
  * @throws {ZizqError} If the server rejects the request (e.g. invalid queue name).
169
202
  *
170
- * @example
203
+ * @example String type
171
204
  * ```ts
172
205
  * const job = await client.enqueue({
173
206
  * type: "send_email",
@@ -175,22 +208,51 @@ export declare class Client {
175
208
  * payload: { to: "user@example.com" },
176
209
  * });
177
210
  * ```
211
+ *
212
+ * @example Function reference
213
+ * ```ts
214
+ * const job = await client.enqueue({
215
+ * type: sendEmail,
216
+ * payload: { to: "user@example.com" },
217
+ * });
218
+ * ```
178
219
  */
179
- enqueue(options: EnqueueOptions): Promise<Job>;
220
+ enqueue(input: EnqueueInput): Promise<Job>;
180
221
  /**
181
222
  * Enqueue multiple jobs in a single request.
182
223
  *
224
+ * Accepts the same input format as {@link enqueue}, including function
225
+ * references for the `type` field.
226
+ *
183
227
  * @returns An array of created jobs in the same order as the input.
184
228
  *
185
229
  * @example
186
230
  * ```ts
187
231
  * const jobs = await client.enqueueBulk([
188
- * { type: "send_email", queue: "emails", payload: { to: "a@b.com" } },
189
- * { type: "send_email", queue: "emails", payload: { to: "c@d.com" } },
232
+ * { type: sendEmail, payload: { to: "a@b.com" } },
233
+ * { type: "manual_job", queue: "ops", payload: {} },
190
234
  * ]);
191
235
  * ```
192
236
  */
193
- enqueueBulk(jobs: EnqueueOptions[]): Promise<Job[]>;
237
+ enqueueBulk(inputs: EnqueueInput[]): Promise<Job[]>;
238
+ /**
239
+ * Enqueue a single job using raw, fully-resolved options.
240
+ *
241
+ * Prefer {@link enqueue} for most use cases. This method is useful when
242
+ * you have already resolved function references or need direct control
243
+ * over the options object.
244
+ *
245
+ * @returns The created job, including its server-assigned `id` and `status`.
246
+ */
247
+ enqueueRaw(options: EnqueueOptions): Promise<Job>;
248
+ /**
249
+ * Enqueue multiple jobs using raw, fully-resolved options.
250
+ *
251
+ * Prefer {@link enqueueBulk} for most use cases.
252
+ *
253
+ * @returns An array of created jobs in the same order as the input.
254
+ */
255
+ enqueueBulkRaw(jobs: EnqueueOptions[]): Promise<Job[]>;
194
256
  /**
195
257
  * Acknowledge a job as successfully completed.
196
258
  *
package/dist/client.js CHANGED
@@ -37,6 +37,7 @@ import { encode as msgpackEncode, decode as msgpackDecode } from "@msgpack/msgpa
37
37
  import { Job, JobPage, ErrorRecord, ErrorPage, CronGroup, CronEntry, } from "./resources.js";
38
38
  import { JobQuery } from "./query.js";
39
39
  import { CronHandle } from "./cron.js";
40
+ import { resolveInput } from "./enqueue.js";
40
41
  // Re-export resource types so consumers can import from client.ts.
41
42
  export { Job, JobPage, ErrorRecord, ErrorPage, CronGroup, CronEntry, } from "./resources.js";
42
43
  /** Base error class for all Zizq errors. */
@@ -150,39 +151,68 @@ export class Client {
150
151
  this.contentType = CONTENT_TYPES[this.format];
151
152
  this.accept = CONTENT_TYPES[this.format];
152
153
  this.streamAccept = STREAM_ACCEPT[this.format];
154
+ const connectTimeout = options.connectTimeout ?? 10_000;
155
+ const readTimeout = options.readTimeout ?? 30_000;
156
+ const streamIdleTimeout = options.streamIdleTimeout ?? 30_000;
153
157
  if (options.dispatcher) {
154
158
  // Testing: use the same dispatcher for both.
155
159
  this.http = options.dispatcher;
156
160
  this.streamHttp = options.dispatcher;
157
161
  }
158
162
  else {
159
- const connectOpts = options.tls ? {
160
- ca: options.tls.ca,
161
- cert: options.tls.cert,
162
- key: options.tls.key,
163
- } : undefined;
163
+ const connectOpts = {
164
+ ...(options.tls ? {
165
+ ca: options.tls.ca,
166
+ cert: options.tls.cert,
167
+ key: options.tls.key,
168
+ } : {}),
169
+ timeout: connectTimeout,
170
+ };
164
171
  // HTTP/2 for request/response traffic (multiplexed acks, enqueues).
172
+ // `bodyTimeout` is per-chunk inactivity — reset on each byte —
173
+ // so it acts as the read timeout; `headersTimeout` caps
174
+ // "server accepted the request but didn't respond" cases.
165
175
  this.http = new Pool(this.url, {
166
176
  allowH2: true,
167
177
  connect: connectOpts,
178
+ headersTimeout: readTimeout,
179
+ bodyTimeout: readTimeout,
168
180
  });
169
181
  // HTTP/1.1 for the long-lived take stream. HTTP/2 adds framing
170
182
  // overhead and flow control with no multiplexing benefit on a
171
183
  // single long-lived response, resulting in measurably lower
172
184
  // throughput compared to HTTP/1.1 chunked transfer.
185
+ //
186
+ // `bodyTimeout` here uses `streamIdleTimeout` rather than the
187
+ // normal `readTimeout`: server heartbeats reset it on each frame,
188
+ // so this only fires when the connection has actually gone
189
+ // silent. The Worker's reconnect path handles the resulting
190
+ // BodyTimeoutError.
191
+ //
192
+ // `headersTimeout` stays on `readTimeout`: the response headers
193
+ // are a one-shot request/response pair like any other API call,
194
+ // only the body streams. Falling through to undici's 5-minute
195
+ // default would leave a server stuck pre-headers blocking the
196
+ // worker far longer than the user-configured timeout would suggest.
173
197
  this.streamHttp = new Pool(this.url, {
174
198
  allowH2: false,
175
199
  connect: connectOpts,
200
+ headersTimeout: readTimeout,
201
+ bodyTimeout: streamIdleTimeout,
176
202
  });
177
203
  }
178
204
  }
179
205
  /**
180
206
  * Enqueue a single job.
181
207
  *
208
+ * The `type` field accepts either a string job type name or a function
209
+ * reference with attached `zizqOptions`. When a function is provided,
210
+ * its `zizqOptions` supplies defaults for `queue`, `priority`, etc.
211
+ *
182
212
  * @returns The created job, including its server-assigned `id` and `status`.
183
213
  * @throws {ZizqError} If the server rejects the request (e.g. invalid queue name).
184
214
  *
185
- * @example
215
+ * @example String type
186
216
  * ```ts
187
217
  * const job = await client.enqueue({
188
218
  * type: "send_email",
@@ -190,25 +220,58 @@ export class Client {
190
220
  * payload: { to: "user@example.com" },
191
221
  * });
192
222
  * ```
223
+ *
224
+ * @example Function reference
225
+ * ```ts
226
+ * const job = await client.enqueue({
227
+ * type: sendEmail,
228
+ * payload: { to: "user@example.com" },
229
+ * });
230
+ * ```
193
231
  */
194
- async enqueue(options) {
195
- const api = enqueueToApi(options);
196
- return this.wrapJob(await this.handleResponse(await this.post("/jobs", api)));
232
+ async enqueue(input) {
233
+ return this.enqueueRaw(resolveInput(input));
197
234
  }
198
235
  /**
199
236
  * Enqueue multiple jobs in a single request.
200
237
  *
238
+ * Accepts the same input format as {@link enqueue}, including function
239
+ * references for the `type` field.
240
+ *
201
241
  * @returns An array of created jobs in the same order as the input.
202
242
  *
203
243
  * @example
204
244
  * ```ts
205
245
  * const jobs = await client.enqueueBulk([
206
- * { type: "send_email", queue: "emails", payload: { to: "a@b.com" } },
207
- * { type: "send_email", queue: "emails", payload: { to: "c@d.com" } },
246
+ * { type: sendEmail, payload: { to: "a@b.com" } },
247
+ * { type: "manual_job", queue: "ops", payload: {} },
208
248
  * ]);
209
249
  * ```
210
250
  */
211
- async enqueueBulk(jobs) {
251
+ async enqueueBulk(inputs) {
252
+ return this.enqueueBulkRaw(inputs.map(resolveInput));
253
+ }
254
+ /**
255
+ * Enqueue a single job using raw, fully-resolved options.
256
+ *
257
+ * Prefer {@link enqueue} for most use cases. This method is useful when
258
+ * you have already resolved function references or need direct control
259
+ * over the options object.
260
+ *
261
+ * @returns The created job, including its server-assigned `id` and `status`.
262
+ */
263
+ async enqueueRaw(options) {
264
+ const api = enqueueToApi(options);
265
+ return this.wrapJob(await this.handleResponse(await this.post("/jobs", api)));
266
+ }
267
+ /**
268
+ * Enqueue multiple jobs using raw, fully-resolved options.
269
+ *
270
+ * Prefer {@link enqueueBulk} for most use cases.
271
+ *
272
+ * @returns An array of created jobs in the same order as the input.
273
+ */
274
+ async enqueueBulkRaw(jobs) {
212
275
  const api = { jobs: jobs.map(enqueueToApi) };
213
276
  const data = await this.handleResponse(await this.post("/jobs/bulk", api));
214
277
  return data.jobs.map((j) => this.wrapJob(j));
package/dist/cron.d.ts CHANGED
@@ -8,8 +8,7 @@
8
8
  */
9
9
  import type { Client } from "./client.ts";
10
10
  import type { CronGroup, CronEntry } from "./resources.ts";
11
- import type { EnqueueOptions } from "./types.ts";
12
- import { type EnqueueInput } from "./enqueue.ts";
11
+ import type { EnqueueOptions, EnqueueInput } from "./types.ts";
13
12
  /**
14
13
  * A cron entry definition that accepts function references for the job type.
15
14
  *
package/dist/enqueue.d.ts CHANGED
@@ -1,120 +1,25 @@
1
- import { Client, type BackoffConfig, type EnqueueOptions, Job, type RetentionConfig, type UniqueScope } from "./client.ts";
2
- import type { JobFunction } from "./handler.ts";
3
- /**
4
- * Input for enqueueing a job.
5
- *
6
- * The `type` field accepts either a string job type name or a function
7
- * reference with optional attached `zizqOptions`. When a function is provided,
8
- * its `zizqOptions` supplies defaults for `queue`, `priority`, etc. These
9
- * defaults can be overridden by inputs specified at enqueue-time.
10
- *
11
- * When `type` is a string, `queue` is required in the inputs.
12
- *
13
- * @example Function reference
14
- * ```ts
15
- * await enqueue(client, { type: sendEmail, payload: { to: "a@b.com" } });
16
- * ```
17
- *
18
- * @example String type with explicit config
19
- * ```ts
20
- * await enqueue(client, {
21
- * type: "send_email",
22
- * queue: "emails",
23
- * payload: { to: "a@b.com" },
24
- * priority: 100,
25
- * });
26
- * ```
27
- */
28
- export interface EnqueueInput {
29
- /** Job type — a function reference or a string type name. */
30
- type: JobFunction | string;
31
- /** Arbitrary payload delivered to the worker. */
32
- payload: unknown;
33
- /**
34
- * Target queue name.
35
- *
36
- * Required when `type` is a string and no `zizqOptions.queue` default
37
- * is available.
38
- */
39
- queue?: string;
40
- /**
41
- * Priority (lower = higher priority).
42
- *
43
- * Valid range is 0 to 65536. Default: 32768.
44
- */
45
- priority?: number;
46
- /**
47
- * Timestamp (ms since epoch) when the job becomes eligible.
48
- *
49
- * When set to a future timestamp the job is created in the "scheduled"
50
- * status. Otherwise the job is created in the "ready" status.
51
- */
52
- readyAt?: number;
53
- /**
54
- * Per-job retry limit.
55
- *
56
- * When not set the server default value applies.
57
- */
58
- retryLimit?: number;
59
- /** Per-job backoff configuration. */
60
- backoff?: BackoffConfig;
61
- /** Per-job retention configuration. */
62
- retention?: RetentionConfig;
63
- /**
64
- * Unique key for enqueue-time deduplication.
65
- *
66
- * Requires a pro license on the server.
67
- *
68
- * The key is global across all queues and job types. Prefix with the job
69
- * type to make it unique per job type.
70
- */
71
- uniqueKey?: string;
72
- /** Uniqueness scope. Only valid when `uniqueKey` is set. */
73
- uniqueWhile?: UniqueScope;
74
- }
1
+ import type { EnqueueOptions, EnqueueInput } from "./types.ts";
2
+ import type { Client } from "./client.ts";
3
+ import type { Job } from "./resources.ts";
4
+ export type { EnqueueInput } from "./types.ts";
75
5
  /**
76
6
  * Enqueue a single job.
77
7
  *
8
+ * @deprecated Use `client.enqueue()` instead.
9
+ *
78
10
  * @param client - The Zizq client to use for the HTTP request.
79
11
  * @param input - Job type, payload, and optional configuration.
80
12
  * @returns The created job, including its server-assigned `id` and `status`.
81
- *
82
- * @example Function reference
83
- * ```ts
84
- * async function sendEmail(payload) { ... }
85
- * sendEmail.zizqOptions = { queue: "emails", priority: 100 };
86
- *
87
- * const job = await enqueue(client, {
88
- * type: sendEmail,
89
- * payload: { to: "user@example.com" },
90
- * });
91
- * ```
92
- *
93
- * @example String type
94
- * ```ts
95
- * const job = await enqueue(client, {
96
- * type: "send_email",
97
- * queue: "emails",
98
- * payload: { to: "user@example.com" },
99
- * });
100
- * ```
101
13
  */
102
14
  export declare function enqueue(client: Client, input: EnqueueInput): Promise<Job>;
103
15
  /**
104
16
  * Enqueue multiple jobs in a single request.
105
17
  *
18
+ * @deprecated Use `client.enqueueBulk()` instead.
19
+ *
106
20
  * @param client - The Zizq client to use for the HTTP request.
107
21
  * @param inputs - Array of job inputs.
108
22
  * @returns An array of created jobs in the same order as the input.
109
- *
110
- * @example
111
- * ```ts
112
- * const jobs = await enqueueBulk(client, [
113
- * { type: sendEmail, payload: { to: "a@b.com" } },
114
- * { type: sendEmail, payload: { to: "c@d.com" }, priority: 1 },
115
- * { type: "manual_job", queue: "ops", payload: {} },
116
- * ]);
117
- * ```
118
23
  */
119
24
  export declare function enqueueBulk(client: Client, inputs: EnqueueInput[]): Promise<Job[]>;
120
25
  /**
package/dist/enqueue.js CHANGED
@@ -3,51 +3,26 @@
3
3
  /**
4
4
  * Enqueue a single job.
5
5
  *
6
+ * @deprecated Use `client.enqueue()` instead.
7
+ *
6
8
  * @param client - The Zizq client to use for the HTTP request.
7
9
  * @param input - Job type, payload, and optional configuration.
8
10
  * @returns The created job, including its server-assigned `id` and `status`.
9
- *
10
- * @example Function reference
11
- * ```ts
12
- * async function sendEmail(payload) { ... }
13
- * sendEmail.zizqOptions = { queue: "emails", priority: 100 };
14
- *
15
- * const job = await enqueue(client, {
16
- * type: sendEmail,
17
- * payload: { to: "user@example.com" },
18
- * });
19
- * ```
20
- *
21
- * @example String type
22
- * ```ts
23
- * const job = await enqueue(client, {
24
- * type: "send_email",
25
- * queue: "emails",
26
- * payload: { to: "user@example.com" },
27
- * });
28
- * ```
29
11
  */
30
12
  export async function enqueue(client, input) {
31
- return client.enqueue(resolveInput(input));
13
+ return client.enqueue(input);
32
14
  }
33
15
  /**
34
16
  * Enqueue multiple jobs in a single request.
35
17
  *
18
+ * @deprecated Use `client.enqueueBulk()` instead.
19
+ *
36
20
  * @param client - The Zizq client to use for the HTTP request.
37
21
  * @param inputs - Array of job inputs.
38
22
  * @returns An array of created jobs in the same order as the input.
39
- *
40
- * @example
41
- * ```ts
42
- * const jobs = await enqueueBulk(client, [
43
- * { type: sendEmail, payload: { to: "a@b.com" } },
44
- * { type: sendEmail, payload: { to: "c@d.com" }, priority: 1 },
45
- * { type: "manual_job", queue: "ops", payload: {} },
46
- * ]);
47
- * ```
48
23
  */
49
24
  export async function enqueueBulk(client, inputs) {
50
- return client.enqueueBulk(inputs.map(resolveInput));
25
+ return client.enqueueBulk(inputs);
51
26
  }
52
27
  // --- Internal ---
53
28
  // Compute the unique key from a job function's ZizqOptions + payload.
package/dist/handler.d.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * @module
10
10
  */
11
- import type { BackoffConfig, EnqueueOptions, RetentionConfig, UniqueScope } from "./client.ts";
11
+ import type { BackoffConfig, EnqueueOptions, RetentionConfig, UniqueScope } from "./types.ts";
12
12
  import type { Job } from "./resources.ts";
13
13
  /**
14
14
  * Configuration that can be attached to a job function via `fn.zizqOptions`.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { Client, Job, JobPage, ErrorRecord, ErrorPage, CronGroup, CronEntry, ZizqError, ConnectionError, ResponseError, ClientError, NotFoundError, ServerError, } from "./client.ts";
2
2
  export type { ClientOptions, TlsOptions, } from "./client.ts";
3
- export type { JobStatus, SortDirection, UniqueScope, Format, BackoffConfig, RetentionConfig, EnqueueOptions, FailureOptions, UpdateJobOptions, TakeOptions, ListJobsOptions, ListErrorsOptions, UpdateAllJobsOptions, JobFilter, DeleteAllJobsOptions, CronEntryInput, ReplaceCronGroupOptions, } from "./types.ts";
3
+ export type { JobStatus, SortDirection, UniqueScope, Format, BackoffConfig, RetentionConfig, EnqueueOptions, EnqueueInput, FailureOptions, UpdateJobOptions, TakeOptions, ListJobsOptions, ListErrorsOptions, UpdateAllJobsOptions, JobFilter, DeleteAllJobsOptions, CronEntryInput, ReplaceCronGroupOptions, } from "./types.ts";
4
4
  export type { JobData, ErrorRecordData, CronEntryData, CronGroupData, } from "./resources.ts";
5
5
  export { Worker } from "./worker.ts";
6
6
  export type { WorkerOptions, Logger, RequestRetryOptions } from "./worker.ts";
@@ -11,5 +11,4 @@ export type { ErrorQueryOptions, JobQueryOptions } from "./query.ts";
11
11
  export { enqueue, enqueueBulk } from "./enqueue.ts";
12
12
  export { CronHandle, CronEntryHandle } from "./cron.ts";
13
13
  export type { CronEntryDefinition, RegisterCronOptions } from "./cron.ts";
14
- export type { EnqueueInput } from "./enqueue.ts";
15
14
  export { uniqueKey } from "./unique-key.ts";
package/dist/types.d.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  *
7
7
  * @module
8
8
  */
9
+ import type { JobFunction } from "./handler.ts";
9
10
  /** Lifecycle status of a job. */
10
11
  export type JobStatus = "ready" | "in_flight" | "scheduled" | "completed" | "dead";
11
12
  /** Sort direction for paginated listings. */
@@ -242,3 +243,75 @@ export interface ReplaceCronGroupOptions {
242
243
  /** Named collection of entries present in this group. */
243
244
  entries: CronEntryInput[];
244
245
  }
246
+ /**
247
+ * Input for enqueueing a job.
248
+ *
249
+ * The `type` field accepts either a string job type name or a function
250
+ * reference with optional attached `zizqOptions`. When a function is provided,
251
+ * its `zizqOptions` supplies defaults for `queue`, `priority`, etc. These
252
+ * defaults can be overridden by inputs specified at enqueue-time.
253
+ *
254
+ * When `type` is a string, `queue` is required in the inputs.
255
+ *
256
+ * @example Function reference
257
+ * ```ts
258
+ * await client.enqueue({ type: sendEmail, payload: { to: "a@b.com" } });
259
+ * ```
260
+ *
261
+ * @example String type with explicit config
262
+ * ```ts
263
+ * await client.enqueue({
264
+ * type: "send_email",
265
+ * queue: "emails",
266
+ * payload: { to: "a@b.com" },
267
+ * priority: 100,
268
+ * });
269
+ * ```
270
+ */
271
+ export interface EnqueueInput {
272
+ /** Job type — a function reference or a string type name. */
273
+ type: JobFunction | string;
274
+ /** Arbitrary payload delivered to the worker. */
275
+ payload: unknown;
276
+ /**
277
+ * Target queue name.
278
+ *
279
+ * Required when `type` is a string and no `zizqOptions.queue` default
280
+ * is available.
281
+ */
282
+ queue?: string;
283
+ /**
284
+ * Priority (lower = higher priority).
285
+ *
286
+ * Valid range is 0 to 65536. Default: 32768.
287
+ */
288
+ priority?: number;
289
+ /**
290
+ * Timestamp (ms since epoch) when the job becomes eligible.
291
+ *
292
+ * When set to a future timestamp the job is created in the "scheduled"
293
+ * status. Otherwise the job is created in the "ready" status.
294
+ */
295
+ readyAt?: number;
296
+ /**
297
+ * Per-job retry limit.
298
+ *
299
+ * When not set the server default value applies.
300
+ */
301
+ retryLimit?: number;
302
+ /** Per-job backoff configuration. */
303
+ backoff?: BackoffConfig;
304
+ /** Per-job retention configuration. */
305
+ retention?: RetentionConfig;
306
+ /**
307
+ * Unique key for enqueue-time deduplication.
308
+ *
309
+ * Requires a pro license on the server.
310
+ *
311
+ * The key is global across all queues and job types. Prefix with the job
312
+ * type to make it unique per job type.
313
+ */
314
+ uniqueKey?: string;
315
+ /** Uniqueness scope. Only valid when `uniqueKey` is set. */
316
+ uniqueWhile?: UniqueScope;
317
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zizq-labs/zizq",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Node.js client for the Zizq job queue server",
5
5
  "homepage": "https://zizq.io",
6
6
  "repository": {