@openstatus/health-bullmq 0.1.4-dev.0

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 ADDED
@@ -0,0 +1,73 @@
1
+ # @openstatus/health-bullmq
2
+
3
+ [BullMQ](https://bullmq.io/) probe for
4
+ [`@openstatus/health`](https://jsr.io/@openstatus/health). Counts the
5
+ waiting jobs of a `Queue` — one `LLEN` against Redis — and fails the check
6
+ when Redis does not answer or, with `maxWaiting`, when the backlog grows
7
+ past a threshold.
8
+
9
+ ```sh
10
+ deno add jsr:@openstatus/health jsr:@openstatus/health-bullmq
11
+ npm install @openstatus/health @openstatus/health-bullmq
12
+ ```
13
+
14
+ ```ts
15
+ import { Queue } from "bullmq";
16
+ import { createHealthHandler } from "@openstatus/health";
17
+ import { bullmqProbe } from "@openstatus/health-bullmq";
18
+
19
+ const emails = new Queue("emails", { connection: { url: env.REDIS_URL } });
20
+
21
+ Deno.serve(
22
+ createHealthHandler({
23
+ probes: [bullmqProbe({ queue: emails, maxWaiting: 10_000 })],
24
+ }),
25
+ );
26
+ ```
27
+
28
+ Reuse the `Queue` your application already holds: BullMQ keeps a Redis
29
+ connection per `Queue`, so constructing one for the health endpoint would
30
+ add a connection of its own. Without `maxWaiting` the probe only proves the
31
+ queue's Redis is reachable; with it the check also turns `failed` when
32
+ producers outrun workers, which is usually the earlier warning.
33
+
34
+ ```ts
35
+ bullmqProbe({
36
+ queue: emails,
37
+ maxWaiting: 10_000,
38
+ // optional overrides from the Probe contract
39
+ name: "emails",
40
+ critical: true,
41
+ timeoutMs: 1000,
42
+ skip: () => env.REDIS_URL == null,
43
+ });
44
+ ```
45
+
46
+ Non-critical by default: a queue usually carries background work, so an
47
+ outage or backlog degrades the report instead of taking the service out of
48
+ rotation. Set `critical: true` when requests cannot complete without
49
+ enqueuing.
50
+
51
+ The queue is typed structurally as `{ getWaitingCount(): PromiseLike<number> }`,
52
+ so `bullmq` is an optional peer dependency for its types only and the probe
53
+ adds no runtime import of it. The factory throws `ProbeConfigError` at
54
+ construction when the queue has no `getWaitingCount()` or `maxWaiting` is
55
+ not a finite number of zero or more.
56
+
57
+ ## About openstatus
58
+
59
+ [openstatus](https://www.openstatus.dev/) is the open-source uptime monitoring
60
+ and status page platform. This package is part of
61
+ [`@openstatus/health`](https://github.com/openstatusHQ/health), the `/health`
62
+ endpoints behind openstatus's own services, extracted so any JavaScript server
63
+ can expose one. Point an
64
+ [openstatus monitor](https://www.openstatus.dev/docs/reference/http-monitor)
65
+ at the endpoint and assert on `status` in the body to be alerted on
66
+ `degraded` before it becomes `unhealthy`.
67
+
68
+ Source: [github.com/openstatusHQ/health](https://github.com/openstatusHQ/health).
69
+ Issues and PRs welcome.
70
+
71
+ ## License
72
+
73
+ [MIT](https://github.com/openstatusHQ/health/blob/main/LICENSE)
@@ -0,0 +1,30 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+
23
+ //#endregion
24
+
25
+ Object.defineProperty(exports, '__toESM', {
26
+ enumerable: true,
27
+ get: function () {
28
+ return __toESM;
29
+ }
30
+ });
package/dist/mod.cjs ADDED
@@ -0,0 +1,47 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ const __openstatus_health = require_rolldown_runtime.__toESM(require("@openstatus/health"));
3
+
4
+ //#region src/mod.ts
5
+ /** Probe name when `name` is unset. */
6
+ const bullmqDefaultName = "queue";
7
+ /** Thrown by the probe when the waiting count exceeds `maxWaiting`. */
8
+ var BullmqBacklogError = class extends Error {
9
+ /** The number of waiting jobs. */
10
+ waiting;
11
+ /** Build the error for `waiting` jobs against the `max` threshold. */
12
+ constructor(waiting, max) {
13
+ super(`${waiting} jobs waiting exceeds ${max}`);
14
+ this.name = "BullmqBacklogError";
15
+ this.waiting = waiting;
16
+ }
17
+ };
18
+ /** A probe that counts waiting jobs and fails above `maxWaiting`; non-critical by default. Throws `ProbeConfigError` without `getWaitingCount()` or when `maxWaiting` is not a finite number of zero or more. */
19
+ function bullmqProbe(options) {
20
+ const queue = options.queue;
21
+ if (typeof queue?.getWaitingCount !== "function") throw new __openstatus_health.ProbeConfigError("bullmqProbe", "queue", `must expose getWaitingCount(), got ${describe(queue)}`);
22
+ const maxWaiting = options.maxWaiting;
23
+ if (maxWaiting != null && (typeof maxWaiting !== "number" || !Number.isFinite(maxWaiting) || maxWaiting < 0)) throw new __openstatus_health.ProbeConfigError("bullmqProbe", "maxWaiting", `must be a non-negative number, got ${String(maxWaiting)}`);
24
+ return {
25
+ name: options.name ?? bullmqDefaultName,
26
+ critical: options.critical ?? false,
27
+ timeoutMs: options.timeoutMs,
28
+ skip: options.skip,
29
+ run: async () => {
30
+ const waiting = await queue.getWaitingCount();
31
+ if (typeof waiting !== "number" || !Number.isFinite(waiting)) throw new Error("unexpected waiting count");
32
+ if (maxWaiting != null && waiting > maxWaiting) throw new BullmqBacklogError(waiting, maxWaiting);
33
+ return { waiting };
34
+ }
35
+ };
36
+ }
37
+ function describe(queue) {
38
+ if (queue == null) return String(queue);
39
+ if (typeof queue !== "object") return typeof queue;
40
+ const keys = Object.keys(queue);
41
+ return keys.length === 0 ? "an object with no keys" : `an object with keys ${keys.slice(0, 8).join(", ")}`;
42
+ }
43
+
44
+ //#endregion
45
+ exports.BullmqBacklogError = BullmqBacklogError;
46
+ exports.bullmqDefaultName = bullmqDefaultName;
47
+ exports.bullmqProbe = bullmqProbe;
package/dist/mod.d.cts ADDED
@@ -0,0 +1,31 @@
1
+ import { Probe, ProbeOverrides } from "@openstatus/health";
2
+
3
+ //#region src/mod.d.ts
4
+
5
+ /** Probe name when `name` is unset. */
6
+ declare const bullmqDefaultName = "queue";
7
+ /** The subset of a BullMQ `Queue` the probe uses. */
8
+ interface BullmqLikeQueue {
9
+ /** Count the jobs in the `waiting` state. */
10
+ getWaitingCount(): PromiseLike<number>;
11
+ }
12
+ /** Options for `bullmqProbe()`. */
13
+ interface BullmqProbeOptions extends ProbeOverrides {
14
+ /** A BullMQ `Queue`. */
15
+ readonly queue: BullmqLikeQueue;
16
+ /** Fail when more jobs than this are waiting. Unlimited by default. */
17
+ readonly maxWaiting?: number;
18
+ }
19
+ /** Thrown by the probe when the waiting count exceeds `maxWaiting`. */
20
+ declare class BullmqBacklogError extends Error {
21
+ /** The number of waiting jobs. */
22
+ readonly waiting: number;
23
+ /** Build the error for `waiting` jobs against the `max` threshold. */
24
+ constructor(waiting: number, max: number);
25
+ }
26
+ /** A probe that counts waiting jobs and fails above `maxWaiting`; non-critical by default. Throws `ProbeConfigError` without `getWaitingCount()` or when `maxWaiting` is not a finite number of zero or more. */
27
+ declare function bullmqProbe(options: BullmqProbeOptions): Probe;
28
+ //# sourceMappingURL=mod.d.ts.map
29
+ //#endregion
30
+ export { BullmqBacklogError, BullmqLikeQueue, BullmqProbeOptions, bullmqDefaultName, bullmqProbe };
31
+ //# sourceMappingURL=mod.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.cts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";;;;AAoD+D;cA9BlD,iBAAA;;UAGI,eAAA;;qBAEI;;;UAIJ,kBAAA,SAA2B;;kBAE1B;;;;;cAML,kBAAA,SAA2B,KAAK;;;;;;;iBAa7B,WAAA,UAAqB,qBAAqB"}
package/dist/mod.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { Probe, ProbeOverrides } from "@openstatus/health";
2
+
3
+ //#region src/mod.d.ts
4
+
5
+ /** Probe name when `name` is unset. */
6
+ declare const bullmqDefaultName = "queue";
7
+ /** The subset of a BullMQ `Queue` the probe uses. */
8
+ interface BullmqLikeQueue {
9
+ /** Count the jobs in the `waiting` state. */
10
+ getWaitingCount(): PromiseLike<number>;
11
+ }
12
+ /** Options for `bullmqProbe()`. */
13
+ interface BullmqProbeOptions extends ProbeOverrides {
14
+ /** A BullMQ `Queue`. */
15
+ readonly queue: BullmqLikeQueue;
16
+ /** Fail when more jobs than this are waiting. Unlimited by default. */
17
+ readonly maxWaiting?: number;
18
+ }
19
+ /** Thrown by the probe when the waiting count exceeds `maxWaiting`. */
20
+ declare class BullmqBacklogError extends Error {
21
+ /** The number of waiting jobs. */
22
+ readonly waiting: number;
23
+ /** Build the error for `waiting` jobs against the `max` threshold. */
24
+ constructor(waiting: number, max: number);
25
+ }
26
+ /** A probe that counts waiting jobs and fails above `maxWaiting`; non-critical by default. Throws `ProbeConfigError` without `getWaitingCount()` or when `maxWaiting` is not a finite number of zero or more. */
27
+ declare function bullmqProbe(options: BullmqProbeOptions): Probe;
28
+ //# sourceMappingURL=mod.d.ts.map
29
+ //#endregion
30
+ export { BullmqBacklogError, BullmqLikeQueue, BullmqProbeOptions, bullmqDefaultName, bullmqProbe };
31
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";;;;AAoD+D;cA9BlD,iBAAA;;UAGI,eAAA;;qBAEI;;;UAIJ,kBAAA,SAA2B;;kBAE1B;;;;;cAML,kBAAA,SAA2B,KAAK;;;;;;;iBAa7B,WAAA,UAAqB,qBAAqB"}
package/dist/mod.js ADDED
@@ -0,0 +1,45 @@
1
+ import { ProbeConfigError } from "@openstatus/health";
2
+
3
+ //#region src/mod.ts
4
+ /** Probe name when `name` is unset. */
5
+ const bullmqDefaultName = "queue";
6
+ /** Thrown by the probe when the waiting count exceeds `maxWaiting`. */
7
+ var BullmqBacklogError = class extends Error {
8
+ /** The number of waiting jobs. */
9
+ waiting;
10
+ /** Build the error for `waiting` jobs against the `max` threshold. */
11
+ constructor(waiting, max) {
12
+ super(`${waiting} jobs waiting exceeds ${max}`);
13
+ this.name = "BullmqBacklogError";
14
+ this.waiting = waiting;
15
+ }
16
+ };
17
+ /** A probe that counts waiting jobs and fails above `maxWaiting`; non-critical by default. Throws `ProbeConfigError` without `getWaitingCount()` or when `maxWaiting` is not a finite number of zero or more. */
18
+ function bullmqProbe(options) {
19
+ const queue = options.queue;
20
+ if (typeof queue?.getWaitingCount !== "function") throw new ProbeConfigError("bullmqProbe", "queue", `must expose getWaitingCount(), got ${describe(queue)}`);
21
+ const maxWaiting = options.maxWaiting;
22
+ if (maxWaiting != null && (typeof maxWaiting !== "number" || !Number.isFinite(maxWaiting) || maxWaiting < 0)) throw new ProbeConfigError("bullmqProbe", "maxWaiting", `must be a non-negative number, got ${String(maxWaiting)}`);
23
+ return {
24
+ name: options.name ?? bullmqDefaultName,
25
+ critical: options.critical ?? false,
26
+ timeoutMs: options.timeoutMs,
27
+ skip: options.skip,
28
+ run: async () => {
29
+ const waiting = await queue.getWaitingCount();
30
+ if (typeof waiting !== "number" || !Number.isFinite(waiting)) throw new Error("unexpected waiting count");
31
+ if (maxWaiting != null && waiting > maxWaiting) throw new BullmqBacklogError(waiting, maxWaiting);
32
+ return { waiting };
33
+ }
34
+ };
35
+ }
36
+ function describe(queue) {
37
+ if (queue == null) return String(queue);
38
+ if (typeof queue !== "object") return typeof queue;
39
+ const keys = Object.keys(queue);
40
+ return keys.length === 0 ? "an object with no keys" : `an object with keys ${keys.slice(0, 8).join(", ")}`;
41
+ }
42
+
43
+ //#endregion
44
+ export { BullmqBacklogError, bullmqDefaultName, bullmqProbe };
45
+ //# sourceMappingURL=mod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.js","names":["waiting: number","max: number","options: BullmqProbeOptions","queue: BullmqLikeQueue"],"sources":["../src/mod.ts"],"sourcesContent":["/**\n * BullMQ probe for `@openstatus/health`: counts the waiting jobs of a\n * `Queue`, which round-trips to Redis, and optionally fails above a backlog\n * threshold.\n *\n * ```ts\n * import { Queue } from \"bullmq\";\n * import { bullmqProbe } from \"@openstatus/health-bullmq\";\n *\n * const probe = bullmqProbe({ queue: new Queue(\"emails\"), maxWaiting: 10_000 });\n * ```\n *\n * @module\n */\n\nimport {\n type Probe,\n ProbeConfigError,\n type ProbeOverrides,\n} from \"@openstatus/health\";\n\n/** Probe name when `name` is unset. */\nexport const bullmqDefaultName = \"queue\";\n\n/** The subset of a BullMQ `Queue` the probe uses. */\nexport interface BullmqLikeQueue {\n /** Count the jobs in the `waiting` state. */\n getWaitingCount(): PromiseLike<number>;\n}\n\n/** Options for `bullmqProbe()`. */\nexport interface BullmqProbeOptions extends ProbeOverrides {\n /** A BullMQ `Queue`. */\n readonly queue: BullmqLikeQueue;\n /** Fail when more jobs than this are waiting. Unlimited by default. */\n readonly maxWaiting?: number;\n}\n\n/** Thrown by the probe when the waiting count exceeds `maxWaiting`. */\nexport class BullmqBacklogError extends Error {\n /** The number of waiting jobs. */\n readonly waiting: number;\n\n /** Build the error for `waiting` jobs against the `max` threshold. */\n constructor(waiting: number, max: number) {\n super(`${waiting} jobs waiting exceeds ${max}`);\n this.name = \"BullmqBacklogError\";\n this.waiting = waiting;\n }\n}\n\n/** A probe that counts waiting jobs and fails above `maxWaiting`; non-critical by default. Throws `ProbeConfigError` without `getWaitingCount()` or when `maxWaiting` is not a finite number of zero or more. */\nexport function bullmqProbe(options: BullmqProbeOptions): Probe {\n const queue = options.queue;\n if (typeof queue?.getWaitingCount !== \"function\") {\n throw new ProbeConfigError(\n \"bullmqProbe\",\n \"queue\",\n `must expose getWaitingCount(), got ${describe(queue)}`,\n );\n }\n const maxWaiting = options.maxWaiting;\n if (\n maxWaiting != null &&\n (typeof maxWaiting !== \"number\" || !Number.isFinite(maxWaiting) ||\n maxWaiting < 0)\n ) {\n throw new ProbeConfigError(\n \"bullmqProbe\",\n \"maxWaiting\",\n `must be a non-negative number, got ${String(maxWaiting)}`,\n );\n }\n return {\n name: options.name ?? bullmqDefaultName,\n critical: options.critical ?? false,\n timeoutMs: options.timeoutMs,\n skip: options.skip,\n run: async () => {\n const waiting = await queue.getWaitingCount();\n if (typeof waiting !== \"number\" || !Number.isFinite(waiting)) {\n throw new Error(\"unexpected waiting count\");\n }\n if (maxWaiting != null && waiting > maxWaiting) {\n throw new BullmqBacklogError(waiting, maxWaiting);\n }\n return { waiting };\n },\n };\n}\n\nfunction describe(queue: BullmqLikeQueue): string {\n if (queue == null) return String(queue);\n if (typeof queue !== \"object\") return typeof queue;\n const keys = Object.keys(queue);\n return keys.length === 0\n ? \"an object with no keys\"\n : `an object with keys ${keys.slice(0, 8).join(\", \")}`;\n}\n"],"mappings":";;;;AAsBA,MAAa,oBAAoB;;AAiBjC,IAAa,qBAAb,cAAwC,MAAM;;CAE5C,AAAS;;CAGT,YAAYA,SAAiBC,KAAa;AACxC,SAAO,EAAE,QAAQ,wBAAwB,IAAI,EAAE;AAC/C,OAAK,OAAO;AACZ,OAAK,UAAU;CAChB;AACF;;AAGD,SAAgB,YAAYC,SAAoC;CAC9D,MAAM,QAAQ,QAAQ;AACtB,YAAW,OAAO,oBAAoB,WACpC,OAAM,IAAI,iBACR,eACA,UACC,qCAAqC,SAAS,MAAM,CAAC;CAG1D,MAAM,aAAa,QAAQ;AAC3B,KACE,cAAc,gBACN,eAAe,aAAa,OAAO,SAAS,WAAW,IAC7D,aAAa,GAEf,OAAM,IAAI,iBACR,eACA,eACC,qCAAqC,OAAO,WAAW,CAAC;AAG7D,QAAO;EACL,MAAM,QAAQ,QAAQ;EACtB,UAAU,QAAQ,YAAY;EAC9B,WAAW,QAAQ;EACnB,MAAM,QAAQ;EACd,KAAK,YAAY;GACf,MAAM,UAAU,MAAM,MAAM,iBAAiB;AAC7C,cAAW,YAAY,aAAa,OAAO,SAAS,QAAQ,CAC1D,OAAM,IAAI,MAAM;AAElB,OAAI,cAAc,QAAQ,UAAU,WAClC,OAAM,IAAI,mBAAmB,SAAS;AAExC,UAAO,EAAE,QAAS;EACnB;CACF;AACF;AAED,SAAS,SAASC,OAAgC;AAChD,KAAI,SAAS,KAAM,QAAO,OAAO,MAAM;AACvC,YAAW,UAAU,SAAU,eAAc;CAC7C,MAAM,OAAO,OAAO,KAAK,MAAM;AAC/B,QAAO,KAAK,WAAW,IACnB,4BACC,sBAAsB,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC;AACxD"}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@openstatus/health-bullmq",
3
+ "version": "0.1.4-dev.0",
4
+ "description": "BullMQ queue probe for @openstatus/health",
5
+ "keywords": [
6
+ "openstatus",
7
+ "health",
8
+ "healthcheck",
9
+ "bullmq",
10
+ "bull",
11
+ "queue",
12
+ "redis",
13
+ "background-jobs"
14
+ ],
15
+ "license": "MIT",
16
+ "author": {
17
+ "name": "openstatus",
18
+ "url": "https://www.openstatus.dev/"
19
+ },
20
+ "homepage": "https://github.com/openstatusHQ/health",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/openstatusHQ/health.git",
24
+ "directory": "packages/bullmq/"
25
+ },
26
+ "bugs": {
27
+ "url": "https://github.com/openstatusHQ/health/issues"
28
+ },
29
+ "type": "module",
30
+ "module": "./dist/mod.js",
31
+ "main": "./dist/mod.cjs",
32
+ "types": "./dist/mod.d.ts",
33
+ "exports": {
34
+ ".": {
35
+ "types": {
36
+ "import": "./dist/mod.d.ts",
37
+ "require": "./dist/mod.d.cts"
38
+ },
39
+ "import": "./dist/mod.js",
40
+ "require": "./dist/mod.cjs"
41
+ },
42
+ "./package.json": "./package.json"
43
+ },
44
+ "sideEffects": false,
45
+ "files": [
46
+ "dist/"
47
+ ],
48
+ "engines": {
49
+ "node": ">=22"
50
+ },
51
+ "peerDependencies": {
52
+ "@openstatus/health": "^0.1.4-dev.0",
53
+ "bullmq": ">=4.0.0"
54
+ },
55
+ "peerDependenciesMeta": {
56
+ "bullmq": {
57
+ "optional": true
58
+ }
59
+ },
60
+ "devDependencies": {
61
+ "tsdown": "^0.12.7",
62
+ "typescript": "^5.8.3"
63
+ },
64
+ "scripts": {
65
+ "build": "tsdown",
66
+ "prepack": "tsdown",
67
+ "test": "node --experimental-transform-types --test"
68
+ }
69
+ }