@shivaedev/jobs 0.26.0 → 0.28.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/CHANGELOG.md +17 -0
- package/README.md +18 -2
- package/dist/server/adapters/retireJobs.d.ts +5 -0
- package/dist/server/adapters/retireJobs.d.ts.map +1 -0
- package/dist/server/adapters/retireJobs.js +28 -0
- package/dist/server/adapters/retireJobs.js.map +1 -0
- package/dist/server/client.d.ts +2 -0
- package/dist/server/client.d.ts.map +1 -1
- package/dist/server/internal/makeService.js +1 -1
- package/dist/server/internal/makeService.js.map +1 -1
- package/dist/server/internal/registerReleasedJobs.d.ts +1 -1
- package/dist/server/internal/registerReleasedJobs.d.ts.map +1 -1
- package/dist/server/internal/registerReleasedJobs.js +4 -3
- package/dist/server/internal/registerReleasedJobs.js.map +1 -1
- package/dist/server/service.d.ts +4 -1
- package/dist/server/service.d.ts.map +1 -1
- package/dist/server/service.js +8 -5
- package/dist/server/service.js.map +1 -1
- package/package.json +6 -6
- package/src/server/adapters/retireJobs.ts +30 -0
- package/src/server/client.ts +2 -0
- package/src/server/internal/makeService.ts +1 -1
- package/src/server/internal/registerReleasedJobs.ts +7 -2
- package/src/server/service.ts +20 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.28.0 - 2026-10-31
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Expose native PostgreSQL `connectionTTL`, `idleTimeout` and `minConnections` through the SQL layer and application host, and `idleTimeoutMillis` and `maxLifetimeSeconds` through the jobs layer.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Application and jobs pools recycle connections after ten minutes and close idle connections after one minute by default, returning backend memory after heavy queries. Application change listeners renew their reserved connection and resynchronize subscribers across renewal.
|
|
12
|
+
|
|
13
|
+
## 0.27.0 - 2026-10-31
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Jobs Layers accept `retired` queue names, deleting their queues and schedules before registering current workers once the database release is active. Dead-letter queues remain unless explicitly retired. Custom clients can expose native `deleteQueue` and `unschedule` capabilities.
|
|
18
|
+
- Jobs health accepts explicit queue names. Jobs admin pages use their declared names for health and accept a browser-safe `{ name }` entry for schedules registered only by a worker, with null payloads for their runs.
|
|
19
|
+
|
|
3
20
|
## 0.26.0 - 2026-10-31
|
|
4
21
|
|
|
5
22
|
### Added
|
package/README.md
CHANGED
|
@@ -165,6 +165,18 @@ Only a Layer whose `jobs` list contains a schedule registration such as `cleanup
|
|
|
165
165
|
|
|
166
166
|
The Layer requires the workers' Effect services. Leaving `Mail` unprovided leaves that requirement in the resulting Effect's type. A primitive Schema such as `Schema.String` is rejected as a queue definition because the durable contract must be an object.
|
|
167
167
|
|
|
168
|
+
### Retire queues and schedules
|
|
169
|
+
|
|
170
|
+
Declare obsolete queue names in the worker Layer:
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
const live = Jobs.layer({ jobs: [sendEmailWorker, cleanupWorker], retired: ["old-mail", "old-cleanup"] });
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Startup stops local workers for each retired name and deletes its queue through pg-boss, including its schedules and queued jobs, before registering current workers. Missing queues can be retired again on subsequent starts. With `WorkerRelease`, retirement waits until this deployment holds the database release, including Layers with no current jobs. Names still registered by the Layer, and their dead-letter queue names, are rejected before any deletion.
|
|
177
|
+
|
|
178
|
+
Dead-letter queues remain unless explicitly included in `retired`; list a source queue before its dead-letter queue when retiring both. Put retirement in the worker deployment that owns those queues and remove the old registrations from other running deployments. Custom clients need the native `deleteQueue` capability for retirement; `PgBossClient` also exposes optional native `unschedule` for removing a single schedule while keeping its queue.
|
|
179
|
+
|
|
168
180
|
### Backlog throughput and concurrency
|
|
169
181
|
|
|
170
182
|
Queue and schedule workers default to `batchSize: 10` and `burstWhenBatchFull: true`. pg-boss fetches again immediately after a full batch completes, until a fetch returns fewer than ten jobs. The adapter runs handlers sequentially within each batch, and pg-boss defaults `localConcurrency` to one. Set native `localConcurrency` to run multiple batches at once:
|
|
@@ -285,6 +297,8 @@ export const jobsLayer = (databaseUrl: Redacted.Redacted<string>) =>
|
|
|
285
297
|
|
|
286
298
|
The redacted connection string is unwrapped only at the pg-boss adapter. Put connection, pool size, client factory, schema, migration and stop settings in `pgBossLayer`. Provide the same Layer to the merged registration, worker and producer services so native Layer memoization starts one client. `jobs` is the complete list of registrations for this Layer. The Layer captures `MailLive` for both the queue handler and the scheduled Effect. A client startup or queue registration failure fails Layer acquisition with `PgBossError` or `PgBossQueueOptionsError` and closes its registrations. A name declaration mismatch fails with `PgBossQueueNamesError`. The owning app Layer releases the client. Registration creates a queue again, up to six times with a short backoff, when PostgreSQL rolls the creation back as a deadlock victim (SQLSTATE `40P01`), which a partitioned queue can meet when other queues in the schema have traffic. A shared client stays running while another scope still owns a reference.
|
|
287
299
|
|
|
300
|
+
`pgBossLayer` defaults its pool to `maxLifetimeSeconds: 600` and `idleTimeoutMillis: 60_000`. Override either with the native pool option; zero disables that timeout. Expired connections close when released, and subsequent jobs operations acquire a replacement. An application-supplied `db` owns its own connection lifecycle.
|
|
301
|
+
|
|
288
302
|
Keep the Layer in the application's worker runtime scope. A short scope is useful for an acquisition or health check; a worker process needs its scope to remain open while it handles jobs.
|
|
289
303
|
|
|
290
304
|
Set `clientCacheKey` on `pgBossLayer` to share one reference-counted client across Layer builds with equal pg-boss constructor settings. Reusing a key with different settings fails acquisition with `PgBossClientOptionsError` before constructing another client. Its `key`, `options` and message identify the key and differing option names without exposing connection values. Nested options are compared by value.
|
|
@@ -352,6 +366,8 @@ export const readJobCounts = Effect.gen(function* () {
|
|
|
352
366
|
|
|
353
367
|
`health` exposes pg-boss cached queue counts as data. It stays cheap and follows the pg-boss monitor interval; it does not establish that a queue has just drained. Its total fields include the registered queue's active, failed, queued and ready counts, plus the dead-letter queue's queued count. Decide in the application which values affect an HTTP health response or an alert.
|
|
354
368
|
|
|
369
|
+
`health([{ name: "cleanup-mail" }])` reads only the supplied queues, in order, even when another runtime registered them. Omitting the argument keeps the Layer's registered names. Admin pages use this to include worker-only schedules without registering those schedules in the request runtime.
|
|
370
|
+
|
|
355
371
|
### Read live counts and retry a job
|
|
356
372
|
|
|
357
373
|
```ts
|
|
@@ -556,10 +572,10 @@ Worker registration always requests `includeMetadata: true`, including when `wor
|
|
|
556
572
|
### Install, setup and limits
|
|
557
573
|
|
|
558
574
|
```sh
|
|
559
|
-
pnpm add @shivaedev/jobs effect
|
|
575
|
+
pnpm add @shivaedev/jobs effect
|
|
560
576
|
```
|
|
561
577
|
|
|
562
|
-
The package requires Node.js 24 or later and PostgreSQL. `effect` and `pg-boss` are peers
|
|
578
|
+
The package requires Node.js 24 or later and PostgreSQL. `effect` and `pg-boss` are peers. pnpm installs `pg-boss` as the jobs package’s peer; apps do not list `pg-boss` themselves.
|
|
563
579
|
|
|
564
580
|
`connectionString` configures pg-boss's own `pg` Pool, separately from the application's Effect SQL pool, and pg-boss's driver decides how its `sslmode` behaves. Set the TLS mode in that URL; the [framework database connection security guide](https://github.com/ShivaeDev/platform/blob/main/docs/framework/quickstart.md#database-connection-security) compares the drivers and the application's connection paths.
|
|
565
581
|
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { PgBossClient } from "#client.ts";
|
|
3
|
+
import type { JobRegistration } from "#definition.ts";
|
|
4
|
+
export declare const retireJobs: (client: PgBossClient, jobs: readonly JobRegistration[], retired: readonly string[]) => Effect.Effect<void, import("#error.ts").PgBossError, never>;
|
|
5
|
+
//# sourceMappingURL=retireJobs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retireJobs.d.ts","sourceRoot":"","sources":["../../../src/server/adapters/retireJobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKtD,eAAO,MAAM,UAAU,qJAsBrB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { toPgBossError } from "#error.ts";
|
|
3
|
+
import { deadLetterQueueName } from "#health.ts";
|
|
4
|
+
import { registrationNames } from "#internal/register.ts";
|
|
5
|
+
export const retireJobs = Effect.fnUntraced(function* (client, jobs, retired) {
|
|
6
|
+
yield* Effect.try({
|
|
7
|
+
catch: (error) => toPgBossError("register", error),
|
|
8
|
+
try: () => {
|
|
9
|
+
const active = registrationNames(jobs).flatMap((name) => [name, deadLetterQueueName(name)]);
|
|
10
|
+
if (retired.some((name) => active.includes(name))) {
|
|
11
|
+
throw new TypeError("Retired queues must not be registered or used as dead-letter queues");
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
for (const name of retired) {
|
|
16
|
+
yield* Effect.tryPromise({
|
|
17
|
+
catch: (error) => toPgBossError("register", error, name),
|
|
18
|
+
try: async () => {
|
|
19
|
+
if (client.deleteQueue === undefined) {
|
|
20
|
+
throw new TypeError("This pg-boss client does not support deleteQueue");
|
|
21
|
+
}
|
|
22
|
+
await client.offWork(name);
|
|
23
|
+
await client.deleteQueue(name);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=retireJobs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retireJobs.js","sourceRoot":"","sources":["../../../src/server/adapters/retireJobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAoB,EAAE,IAAgC,EAAE,OAA0B;IACxI,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;QACjB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,KAAK,CAAC;QAClD,GAAG,EAAE,GAAG,EAAE;YACT,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC5F,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,SAAS,CAAC,qEAAqE,CAAC,CAAC;YAC5F,CAAC;QACF,CAAC;KACD,CAAC,CAAC;IACH,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC5B,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;YACxB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC;YACxD,GAAG,EAAE,KAAK,IAAI,EAAE;gBACf,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;oBACtC,MAAM,IAAI,SAAS,CAAC,kDAAkD,CAAC,CAAC;gBACzE,CAAC;gBACD,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC3B,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;SACD,CAAC,CAAC;IACJ,CAAC;AACF,CAAC,CAAC,CAAC"}
|
package/dist/server/client.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { ConstructorOptions, FindJobsOptions, Job, JobWithMetadata, PgBoss,
|
|
|
2
2
|
export interface PgBossClient {
|
|
3
3
|
readonly complete?: PgBoss["complete"];
|
|
4
4
|
readonly createQueue: (name: string, options?: Omit<Queue, "name">) => Promise<void>;
|
|
5
|
+
readonly deleteQueue?: PgBoss["deleteQueue"];
|
|
5
6
|
readonly fail?: PgBoss["fail"];
|
|
6
7
|
readonly findJobs?: (name: string, options?: FindJobsOptions) => Promise<readonly JobWithMetadata<unknown>[]>;
|
|
7
8
|
readonly getDb?: PgBoss["getDb"];
|
|
@@ -16,6 +17,7 @@ export interface PgBossClient {
|
|
|
16
17
|
readonly send: (name: string, data?: object | null, options?: SendOptions) => Promise<string | null>;
|
|
17
18
|
readonly start: () => Promise<unknown>;
|
|
18
19
|
readonly stop: (options?: StopOptions) => Promise<void>;
|
|
20
|
+
readonly unschedule?: PgBoss["unschedule"];
|
|
19
21
|
readonly update?: PgBoss["update"];
|
|
20
22
|
readonly updateQueue?: PgBoss["updateQueue"];
|
|
21
23
|
readonly work: (name: string, options: WorkOptions, handler: (jobs: readonly Job<unknown>[]) => Promise<unknown>) => Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/server/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,kBAAkB,EAClB,eAAe,EACf,GAAG,EACH,eAAe,EACf,MAAM,EACN,KAAK,EACL,WAAW,EACX,eAAe,EACf,WAAW,EACX,WAAW,EACX,WAAW,EACX,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACvC,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,SAAS,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9G,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACjE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IAC3C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IAC/C,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,KAAK,OAAO,CAAC;IAC5E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,KAAK,OAAO,CAAC;IAC3E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClH,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACrG,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IAC7C,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACrI;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,kBAAkB,KAAK,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/server/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ export function makeService(client, names, schema = "pgboss") {
|
|
|
10
10
|
enqueue: enqueueFor(client),
|
|
11
11
|
failedJobs: failedJobsFor(client, schema),
|
|
12
12
|
getJob: getJobFor(client),
|
|
13
|
-
health: () => healthFor(client, names),
|
|
13
|
+
health: (queues) => healthFor(client, queues === undefined ? names : queues.map((queue) => queue.name)),
|
|
14
14
|
retry: retryFor(client),
|
|
15
15
|
};
|
|
16
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"makeService.js","sourceRoot":"","sources":["../../../src/server/internal/makeService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG3E,MAAM,UAAU,WAAW,CAAC,MAAoB,EAAE,KAAwB,EAAE,MAAM,GAAG,QAAQ;IAC5F,OAAO;QACN,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC;QACxD,gBAAgB,EAAE,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC;QACrD,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC;QAC3B,UAAU,EAAE,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC;QACzC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC;QACzB,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"makeService.js","sourceRoot":"","sources":["../../../src/server/internal/makeService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG3E,MAAM,UAAU,WAAW,CAAC,MAAoB,EAAE,KAAwB,EAAE,MAAM,GAAG,QAAQ;IAC5F,OAAO;QACN,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC;QACxD,gBAAgB,EAAE,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC;QACrD,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC;QAC3B,UAAU,EAAE,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC;QACzC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC;QACzB,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvG,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC;KACvB,CAAC;AACH,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Context, Effect, Scope } from "effect";
|
|
2
2
|
import type { PgBossClient } from "#client.ts";
|
|
3
3
|
import type { JobRegistration } from "#definition.ts";
|
|
4
|
-
export declare const registerReleasedJobs: <R>(client: PgBossClient, jobs: readonly JobRegistration[], context: Context.Context<R>, replaceWorkers: boolean, schema: string | undefined, graceful: boolean) => Effect.Effect<void, import("#error.ts").PgBossError | import("#error.ts").PgBossQueueOptionsError, Scope.Scope>;
|
|
4
|
+
export declare const registerReleasedJobs: <R>(client: PgBossClient, jobs: readonly JobRegistration[], context: Context.Context<R>, replaceWorkers: boolean, schema: string | undefined, graceful: boolean, retired?: readonly string[] | undefined) => Effect.Effect<void, import("#error.ts").PgBossError | import("#error.ts").PgBossQueueOptionsError, Scope.Scope>;
|
|
5
5
|
//# sourceMappingURL=registerReleasedJobs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registerReleasedJobs.d.ts","sourceRoot":"","sources":["../../../src/server/internal/registerReleasedJobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"registerReleasedJobs.d.ts","sourceRoot":"","sources":["../../../src/server/internal/registerReleasedJobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAC;AAG7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD,eAAO,MAAM,oBAAoB,GAAgC,CAAC,0TAyChE,CAAC"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { Effect, Option, Scope } from "effect";
|
|
2
2
|
import { WorkerRelease } from "@shivaedev/sql/WorkerRelease.ts";
|
|
3
|
+
import { retireJobs } from "#adapters/retireJobs.ts";
|
|
3
4
|
import { toPgBossError } from "#error.ts";
|
|
4
5
|
import { registerJobs, registrationName } from "./register.js";
|
|
5
|
-
export const registerReleasedJobs = Effect.fnUntraced(function* (client, jobs, context, replaceWorkers, schema, graceful) {
|
|
6
|
+
export const registerReleasedJobs = Effect.fnUntraced(function* (client, jobs, context, replaceWorkers, schema, graceful, retired = []) {
|
|
6
7
|
const signal = yield* Effect.serviceOption(WorkerRelease);
|
|
7
8
|
const workers = jobs.filter((job) => job._tag !== "QueueDefinition");
|
|
8
9
|
const scope = yield* Effect.scope;
|
|
9
|
-
const register = registerJobs(client, jobs, context, replaceWorkers, schema, true, graceful)
|
|
10
|
-
if (Option.isNone(signal) || workers.length === 0) {
|
|
10
|
+
const register = retireJobs(client, jobs, retired).pipe(Effect.andThen(registerJobs(client, jobs, context, replaceWorkers, schema, true, graceful)), Effect.provideService(Scope.Scope, scope));
|
|
11
|
+
if (Option.isNone(signal) || (workers.length === 0 && retired.length === 0)) {
|
|
11
12
|
return yield* register;
|
|
12
13
|
}
|
|
13
14
|
yield* registerJobs(client, jobs, context, replaceWorkers, schema, false, graceful);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registerReleasedJobs.js","sourceRoot":"","sources":["../../../src/server/internal/registerReleasedJobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"registerReleasedJobs.js","sourceRoot":"","sources":["../../../src/server/internal/registerReleasedJobs.ts"],"names":[],"mappings":"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"}
|
package/dist/server/service.d.ts
CHANGED
|
@@ -22,11 +22,13 @@ export interface PgBossService {
|
|
|
22
22
|
readonly name: TName;
|
|
23
23
|
readonly schema: TPayload;
|
|
24
24
|
}, id: string) => Effect.Effect<Option.Option<JobWithMetadata<unknown>>, PgBossError | PgBossPayloadError, TPayload["DecodingServices"]>;
|
|
25
|
-
readonly health: () => Effect.Effect<JobsHealth, PgBossError>;
|
|
25
|
+
readonly health: (queues?: readonly Pick<QueueDefinition, "name">[]) => Effect.Effect<JobsHealth, PgBossError>;
|
|
26
26
|
readonly retry: (queue: Pick<QueueDefinition, "name">, id: string) => Effect.Effect<void, PgBossError>;
|
|
27
27
|
}
|
|
28
28
|
export type PgBossOptions = Omit<ConstructorOptions, "connectionString"> & {
|
|
29
29
|
readonly connectionString?: Redacted.Redacted<string>;
|
|
30
|
+
readonly idleTimeoutMillis?: number;
|
|
31
|
+
readonly maxLifetimeSeconds?: number;
|
|
30
32
|
readonly clientFactory?: PgBossClientFactory;
|
|
31
33
|
readonly clientCacheKey?: string | symbol | undefined;
|
|
32
34
|
readonly stop?: StopOptions;
|
|
@@ -35,6 +37,7 @@ export declare function pgBossLayer(options: PgBossOptions): Layer.Layer<PgBoss,
|
|
|
35
37
|
export interface PgBossLayerOptions<TRegistrations extends readonly JobRegistration[], TErrorRequirements> {
|
|
36
38
|
readonly jobs: TRegistrations;
|
|
37
39
|
readonly onError?: (error: Error) => Effect.Effect<unknown, never, TErrorRequirements>;
|
|
40
|
+
readonly retired?: readonly string[];
|
|
38
41
|
}
|
|
39
42
|
export interface PgBossDefinition<TIdentifier extends string = string> extends Context.Service<TIdentifier, PgBossService> {
|
|
40
43
|
readonly layer: <const TRegistrations extends readonly JobRegistration[], TErrorRequirements = never>(options: PgBossLayerOptions<TRegistrations, TErrorRequirements>) => Layer.Layer<TIdentifier, PgBossError | PgBossQueueNamesError | PgBossQueueOptionsError, PgBoss | Exclude<RegistrationRequirements<TRegistrations>, TIdentifier> | TErrorRequirements>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/server/service.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/server/service.ts"],"names":[],"mappings":"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"}
|
package/dist/server/service.js
CHANGED
|
@@ -11,15 +11,18 @@ import { validateQueueNames } from "#internal/validateQueueNames.ts";
|
|
|
11
11
|
import { PgBoss } from "#PgBoss.ts";
|
|
12
12
|
export function pgBossLayer(options) {
|
|
13
13
|
const { connectionString, clientFactory, clientCacheKey, stop, ...settings } = options;
|
|
14
|
+
const constructorOptions = {
|
|
15
|
+
...settings,
|
|
16
|
+
idleTimeoutMillis: settings.idleTimeoutMillis ?? 60_000,
|
|
17
|
+
maxLifetimeSeconds: settings.maxLifetimeSeconds ?? 600,
|
|
18
|
+
...(connectionString === undefined ? {} : { connectionString: Redacted.value(connectionString) }),
|
|
19
|
+
};
|
|
14
20
|
return Layer.effect(PgBoss, Effect.gen(function* () {
|
|
15
21
|
const report = yield* clientErrorReporter(logClientError);
|
|
16
22
|
const acquired = yield* Effect.acquireRelease(acquireClient({
|
|
17
23
|
clientCacheKey,
|
|
18
24
|
clientFactory,
|
|
19
|
-
constructor:
|
|
20
|
-
...settings,
|
|
21
|
-
...(connectionString === undefined ? {} : { connectionString: Redacted.value(connectionString) }),
|
|
22
|
-
},
|
|
25
|
+
constructor: constructorOptions,
|
|
23
26
|
}, report), (client) => releaseClient(client, stop));
|
|
24
27
|
return { ...acquired, schema: settings.schema, stop };
|
|
25
28
|
}));
|
|
@@ -38,7 +41,7 @@ export function makePgBoss(identifier, queueNames) {
|
|
|
38
41
|
const report = yield* clientErrorReporter(reportError).pipe(Effect.provide(context));
|
|
39
42
|
const unsubscribe = subscribeClientErrors(acquired.client, report);
|
|
40
43
|
yield* Effect.addFinalizer(() => Scope.close(workerScope, Exit.void).pipe(Effect.ensuring(Effect.sync(unsubscribe))));
|
|
41
|
-
yield* registerReleasedJobs(acquired.client, options.jobs, context, acquired.reused, acquired.schema, acquired.stop?.graceful !== false).pipe(Effect.provideService(Scope.Scope, workerScope), Effect.provide(dependencies));
|
|
44
|
+
yield* registerReleasedJobs(acquired.client, options.jobs, context, acquired.reused, acquired.schema, acquired.stop?.graceful !== false, options.retired).pipe(Effect.provideService(Scope.Scope, workerScope), Effect.provide(dependencies));
|
|
42
45
|
return service;
|
|
43
46
|
}),
|
|
44
47
|
methods: (service) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/server/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAe,QAAQ,EAAe,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEjG,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAKvE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/server/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAe,QAAQ,EAAe,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEjG,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAKvE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAkCpC,MAAM,UAAU,WAAW,CAAC,OAAsB;IACjD,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC;IACvF,MAAM,kBAAkB,GAAG;QAC1B,GAAG,QAAQ;QACX,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,IAAI,MAAM;QACvD,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB,IAAI,GAAG;QACtD,GAAG,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC;KACjG,CAAC;IACF,OAAO,KAAK,CAAC,MAAM,CAClB,MAAM,EACN,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACnB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAC,cAAc,CAAC,CAAC;QAC1D,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CAC5C,aAAa,CACZ;YACC,cAAc;YACd,aAAa;YACb,WAAW,EAAE,kBAAkB;SAC/B,EACD,MAAM,CACN,EACD,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CACvC,CAAC;QACF,OAAO,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;IACvD,CAAC,CAAC,CACF,CAAC;AACH,CAAC;AAkBD,MAAM,UAAU,UAAU,CAAmC,UAAuB,EAAE,UAA8B;IACnH,SAAS,UAAU,CAAI,OAA0D,EAAE,YAAgC;QAClH,OAAO,aAAa,CAAC;YACpB,EAAE,EAAE,UAAU;YACd,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAC/B,KAAK,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;gBACpD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC;gBAC/B,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAClG,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC5D,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,IAAI,cAAc,CAAC;gBACtD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;gBACrF,MAAM,WAAW,GAAG,qBAAqB,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBACnE,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;gBACtH,KAAK,CAAC,CAAC,oBAAoB,CAC1B,QAAQ,CAAC,MAAM,EACf,OAAO,CAAC,IAAI,EACZ,OAAO,EACP,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,IAAI,EAAE,QAAQ,KAAK,KAAK,EACjC,OAAO,CAAC,OAAO,CACf,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;gBACtF,OAAO,OAAO,CAAC;YAChB,CAAC,CAAC;YACF,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACtB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,gBAAgB,EAAE,aAAa,CAAC,OAAO,CAAC,gBAAgB,CAAC;gBACzD,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC;gBACvC,UAAU,EAAE,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC;gBAC7C,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC;gBACrC,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,KAAK,EAAE,OAAO,CAAC,KAAK;aACpB,CAAC;YACF,QAAQ,EAAE,CAAC,MAAM,CAAC;SAClB,CAAC,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAgD,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACvG,SAAS,KAAK,CACb,OAA+D;QAG/D,OAAO,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,EAAgB,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5H,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/jobs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Effect-native jobs and lifecycle management for pg-boss",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"effect"
|
|
@@ -48,16 +48,16 @@
|
|
|
48
48
|
"README.md"
|
|
49
49
|
],
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@shivaedev/errors": "0.
|
|
51
|
+
"@shivaedev/errors": "0.3.0",
|
|
52
52
|
"@shivaedev/service": "0.6.0",
|
|
53
|
-
"@shivaedev/sql": "0.
|
|
53
|
+
"@shivaedev/sql": "0.28.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@shivaedev/http": "0.3.1",
|
|
57
|
-
"@shivaedev/quality": "0.
|
|
57
|
+
"@shivaedev/quality": "0.51.0",
|
|
58
58
|
"@shivaedev/test": "0.12.0",
|
|
59
|
-
"@shivaedev/test-sql": "0.15.
|
|
60
|
-
"@shivaedev/test-story": "0.
|
|
59
|
+
"@shivaedev/test-sql": "0.15.1",
|
|
60
|
+
"@shivaedev/test-story": "0.31.0",
|
|
61
61
|
"@types/node": "24.19.2",
|
|
62
62
|
"effect": "4.0.6",
|
|
63
63
|
"pg-boss": "12.38.0",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { PgBossClient } from "#client.ts";
|
|
3
|
+
import type { JobRegistration } from "#definition.ts";
|
|
4
|
+
import { toPgBossError } from "#error.ts";
|
|
5
|
+
import { deadLetterQueueName } from "#health.ts";
|
|
6
|
+
import { registrationNames } from "#internal/register.ts";
|
|
7
|
+
|
|
8
|
+
export const retireJobs = Effect.fnUntraced(function* (client: PgBossClient, jobs: readonly JobRegistration[], retired: readonly string[]) {
|
|
9
|
+
yield* Effect.try({
|
|
10
|
+
catch: (error) => toPgBossError("register", error),
|
|
11
|
+
try: () => {
|
|
12
|
+
const active = registrationNames(jobs).flatMap((name) => [name, deadLetterQueueName(name)]);
|
|
13
|
+
if (retired.some((name) => active.includes(name))) {
|
|
14
|
+
throw new TypeError("Retired queues must not be registered or used as dead-letter queues");
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
for (const name of retired) {
|
|
19
|
+
yield* Effect.tryPromise({
|
|
20
|
+
catch: (error) => toPgBossError("register", error, name),
|
|
21
|
+
try: async () => {
|
|
22
|
+
if (client.deleteQueue === undefined) {
|
|
23
|
+
throw new TypeError("This pg-boss client does not support deleteQueue");
|
|
24
|
+
}
|
|
25
|
+
await client.offWork(name);
|
|
26
|
+
await client.deleteQueue(name);
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
package/src/server/client.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
export interface PgBossClient {
|
|
16
16
|
readonly complete?: PgBoss["complete"];
|
|
17
17
|
readonly createQueue: (name: string, options?: Omit<Queue, "name">) => Promise<void>;
|
|
18
|
+
readonly deleteQueue?: PgBoss["deleteQueue"];
|
|
18
19
|
readonly fail?: PgBoss["fail"];
|
|
19
20
|
readonly findJobs?: (name: string, options?: FindJobsOptions) => Promise<readonly JobWithMetadata<unknown>[]>;
|
|
20
21
|
readonly getDb?: PgBoss["getDb"];
|
|
@@ -29,6 +30,7 @@ export interface PgBossClient {
|
|
|
29
30
|
readonly send: (name: string, data?: object | null, options?: SendOptions) => Promise<string | null>;
|
|
30
31
|
readonly start: () => Promise<unknown>;
|
|
31
32
|
readonly stop: (options?: StopOptions) => Promise<void>;
|
|
33
|
+
readonly unschedule?: PgBoss["unschedule"];
|
|
32
34
|
readonly update?: PgBoss["update"];
|
|
33
35
|
readonly updateQueue?: PgBoss["updateQueue"];
|
|
34
36
|
readonly work: (name: string, options: WorkOptions, handler: (jobs: readonly Job<unknown>[]) => Promise<unknown>) => Promise<string>;
|
|
@@ -13,7 +13,7 @@ export function makeService(client: PgBossClient, names: readonly string[], sche
|
|
|
13
13
|
enqueue: enqueueFor(client),
|
|
14
14
|
failedJobs: failedJobsFor(client, schema),
|
|
15
15
|
getJob: getJobFor(client),
|
|
16
|
-
health: () => healthFor(client, names),
|
|
16
|
+
health: (queues) => healthFor(client, queues === undefined ? names : queues.map((queue) => queue.name)),
|
|
17
17
|
retry: retryFor(client),
|
|
18
18
|
};
|
|
19
19
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Context, Effect, Option, Scope } from "effect";
|
|
2
2
|
import { WorkerRelease } from "@shivaedev/sql/WorkerRelease.ts";
|
|
3
|
+
import { retireJobs } from "#adapters/retireJobs.ts";
|
|
3
4
|
import type { PgBossClient } from "#client.ts";
|
|
4
5
|
import type { JobRegistration } from "#definition.ts";
|
|
5
6
|
import { toPgBossError } from "#error.ts";
|
|
@@ -12,12 +13,16 @@ export const registerReleasedJobs = Effect.fnUntraced(function* <R>(
|
|
|
12
13
|
replaceWorkers: boolean,
|
|
13
14
|
schema: string | undefined,
|
|
14
15
|
graceful: boolean,
|
|
16
|
+
retired: readonly string[] = [],
|
|
15
17
|
) {
|
|
16
18
|
const signal = yield* Effect.serviceOption(WorkerRelease);
|
|
17
19
|
const workers = jobs.filter((job) => job._tag !== "QueueDefinition");
|
|
18
20
|
const scope = yield* Effect.scope;
|
|
19
|
-
const register =
|
|
20
|
-
|
|
21
|
+
const register = retireJobs(client, jobs, retired).pipe(
|
|
22
|
+
Effect.andThen(registerJobs(client, jobs, context, replaceWorkers, schema, true, graceful)),
|
|
23
|
+
Effect.provideService(Scope.Scope, scope),
|
|
24
|
+
);
|
|
25
|
+
if (Option.isNone(signal) || (workers.length === 0 && retired.length === 0)) {
|
|
21
26
|
return yield* register;
|
|
22
27
|
}
|
|
23
28
|
yield* registerJobs(client, jobs, context, replaceWorkers, schema, false, graceful);
|
package/src/server/service.ts
CHANGED
|
@@ -34,12 +34,14 @@ export interface PgBossService {
|
|
|
34
34
|
queue: { readonly name: TName; readonly schema: TPayload },
|
|
35
35
|
id: string,
|
|
36
36
|
) => Effect.Effect<Option.Option<JobWithMetadata<unknown>>, PgBossError | PgBossPayloadError, TPayload["DecodingServices"]>;
|
|
37
|
-
readonly health: () => Effect.Effect<JobsHealth, PgBossError>;
|
|
37
|
+
readonly health: (queues?: readonly Pick<QueueDefinition, "name">[]) => Effect.Effect<JobsHealth, PgBossError>;
|
|
38
38
|
readonly retry: (queue: Pick<QueueDefinition, "name">, id: string) => Effect.Effect<void, PgBossError>;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export type PgBossOptions = Omit<ConstructorOptions, "connectionString"> & {
|
|
42
42
|
readonly connectionString?: Redacted.Redacted<string>;
|
|
43
|
+
readonly idleTimeoutMillis?: number;
|
|
44
|
+
readonly maxLifetimeSeconds?: number;
|
|
43
45
|
readonly clientFactory?: PgBossClientFactory;
|
|
44
46
|
readonly clientCacheKey?: string | symbol | undefined;
|
|
45
47
|
readonly stop?: StopOptions;
|
|
@@ -47,6 +49,12 @@ export type PgBossOptions = Omit<ConstructorOptions, "connectionString"> & {
|
|
|
47
49
|
|
|
48
50
|
export function pgBossLayer(options: PgBossOptions): Layer.Layer<PgBoss, PgBossError | PgBossClientOptionsError> {
|
|
49
51
|
const { connectionString, clientFactory, clientCacheKey, stop, ...settings } = options;
|
|
52
|
+
const constructorOptions = {
|
|
53
|
+
...settings,
|
|
54
|
+
idleTimeoutMillis: settings.idleTimeoutMillis ?? 60_000,
|
|
55
|
+
maxLifetimeSeconds: settings.maxLifetimeSeconds ?? 600,
|
|
56
|
+
...(connectionString === undefined ? {} : { connectionString: Redacted.value(connectionString) }),
|
|
57
|
+
};
|
|
50
58
|
return Layer.effect(
|
|
51
59
|
PgBoss,
|
|
52
60
|
Effect.gen(function* () {
|
|
@@ -56,10 +64,7 @@ export function pgBossLayer(options: PgBossOptions): Layer.Layer<PgBoss, PgBossE
|
|
|
56
64
|
{
|
|
57
65
|
clientCacheKey,
|
|
58
66
|
clientFactory,
|
|
59
|
-
constructor:
|
|
60
|
-
...settings,
|
|
61
|
-
...(connectionString === undefined ? {} : { connectionString: Redacted.value(connectionString) }),
|
|
62
|
-
},
|
|
67
|
+
constructor: constructorOptions,
|
|
63
68
|
},
|
|
64
69
|
report,
|
|
65
70
|
),
|
|
@@ -73,6 +78,7 @@ export function pgBossLayer(options: PgBossOptions): Layer.Layer<PgBoss, PgBossE
|
|
|
73
78
|
export interface PgBossLayerOptions<TRegistrations extends readonly JobRegistration[], TErrorRequirements> {
|
|
74
79
|
readonly jobs: TRegistrations;
|
|
75
80
|
readonly onError?: (error: Error) => Effect.Effect<unknown, never, TErrorRequirements>;
|
|
81
|
+
readonly retired?: readonly string[];
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
export interface PgBossDefinition<TIdentifier extends string = string> extends Context.Service<TIdentifier, PgBossService> {
|
|
@@ -99,10 +105,15 @@ export function makePgBoss<const TIdentifier extends string>(identifier: TIdenti
|
|
|
99
105
|
const report = yield* clientErrorReporter(reportError).pipe(Effect.provide(context));
|
|
100
106
|
const unsubscribe = subscribeClientErrors(acquired.client, report);
|
|
101
107
|
yield* Effect.addFinalizer(() => Scope.close(workerScope, Exit.void).pipe(Effect.ensuring(Effect.sync(unsubscribe))));
|
|
102
|
-
yield* registerReleasedJobs(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
yield* registerReleasedJobs(
|
|
109
|
+
acquired.client,
|
|
110
|
+
options.jobs,
|
|
111
|
+
context,
|
|
112
|
+
acquired.reused,
|
|
113
|
+
acquired.schema,
|
|
114
|
+
acquired.stop?.graceful !== false,
|
|
115
|
+
options.retired,
|
|
116
|
+
).pipe(Effect.provideService(Scope.Scope, workerScope), Effect.provide(dependencies));
|
|
106
117
|
return service;
|
|
107
118
|
}),
|
|
108
119
|
methods: (service) => ({
|