@shivaedev/jobs 0.22.1 → 0.23.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 +24 -0
- package/README.md +47 -53
- package/dist/JobFailure.d.ts +7 -0
- package/dist/JobFailure.d.ts.map +1 -0
- package/dist/JobFailure.js +8 -0
- package/dist/JobFailure.js.map +1 -0
- package/dist/server/PgBoss.d.ts +11 -0
- package/dist/server/PgBoss.d.ts.map +1 -0
- package/dist/server/PgBoss.js +4 -0
- package/dist/server/PgBoss.js.map +1 -0
- package/dist/server/client.d.ts +1 -1
- package/dist/server/client.d.ts.map +1 -1
- package/dist/server/health.d.ts +3 -2
- package/dist/server/health.d.ts.map +1 -1
- package/dist/server/health.js.map +1 -1
- package/dist/server/internal/batchHandler.d.ts +2 -1
- package/dist/server/internal/batchHandler.d.ts.map +1 -1
- package/dist/server/internal/batchHandler.js +49 -31
- package/dist/server/internal/batchHandler.js.map +1 -1
- package/dist/server/internal/clientErrors.d.ts.map +1 -1
- package/dist/server/internal/clientErrors.js +2 -1
- package/dist/server/internal/clientErrors.js.map +1 -1
- package/dist/server/internal/deferrableAttempt.d.ts +1 -1
- package/dist/server/internal/deferrableAttempt.d.ts.map +1 -1
- package/dist/server/internal/deferrableAttempt.js +5 -1
- package/dist/server/internal/deferrableAttempt.js.map +1 -1
- package/dist/server/internal/ensureQueue.d.ts +2 -1
- package/dist/server/internal/ensureQueue.d.ts.map +1 -1
- package/dist/server/internal/ensureQueue.js +16 -21
- package/dist/server/internal/ensureQueue.js.map +1 -1
- package/dist/server/internal/failureOutput.d.ts +4 -0
- package/dist/server/internal/failureOutput.d.ts.map +1 -0
- package/dist/server/internal/failureOutput.js +9 -0
- package/dist/server/internal/failureOutput.js.map +1 -0
- package/dist/server/internal/lifecycle.d.ts +1 -1
- package/dist/server/internal/lifecycle.d.ts.map +1 -1
- package/dist/server/internal/lifecycle.js +10 -16
- package/dist/server/internal/lifecycle.js.map +1 -1
- package/dist/server/internal/listJobs.d.ts.map +1 -1
- package/dist/server/internal/listJobs.js +44 -39
- package/dist/server/internal/listJobs.js.map +1 -1
- package/dist/server/internal/makeService.js +1 -1
- package/dist/server/internal/makeService.js.map +1 -1
- package/dist/server/internal/register.d.ts +4 -3
- package/dist/server/internal/register.d.ts.map +1 -1
- package/dist/server/internal/register.js +34 -48
- package/dist/server/internal/register.js.map +1 -1
- package/dist/server/internal/registerReleasedJobs.d.ts +2 -1
- package/dist/server/internal/registerReleasedJobs.d.ts.map +1 -1
- package/dist/server/internal/registerReleasedJobs.js +3 -3
- package/dist/server/internal/registerReleasedJobs.js.map +1 -1
- package/dist/server/internal/registerWorker.d.ts +3 -2
- package/dist/server/internal/registerWorker.d.ts.map +1 -1
- package/dist/server/internal/registerWorker.js +26 -33
- package/dist/server/internal/registerWorker.js.map +1 -1
- package/dist/server/internal/retryWake.d.ts +4 -0
- package/dist/server/internal/retryWake.d.ts.map +1 -0
- package/dist/server/internal/retryWake.js +32 -0
- package/dist/server/internal/retryWake.js.map +1 -0
- package/dist/server/internal/runQueueWorker.d.ts +5 -0
- package/dist/server/internal/runQueueWorker.d.ts.map +1 -0
- package/dist/server/internal/runQueueWorker.js +12 -0
- package/dist/server/internal/runQueueWorker.js.map +1 -0
- package/dist/server/internal/schemaIndexBuilds.d.ts.map +1 -1
- package/dist/server/internal/schemaIndexBuilds.js +5 -2
- package/dist/server/internal/schemaIndexBuilds.js.map +1 -1
- package/dist/server/schema.d.ts.map +1 -1
- package/dist/server/schema.js +16 -5
- package/dist/server/schema.js.map +1 -1
- package/dist/server/service.d.ts +13 -8
- package/dist/server/service.d.ts.map +1 -1
- package/dist/server/service.js +53 -22
- package/dist/server/service.js.map +1 -1
- package/package.json +14 -8
- package/src/JobFailure.ts +9 -0
- package/src/server/PgBoss.ts +8 -0
- package/src/server/client.ts +1 -1
- package/src/server/health.ts +3 -2
- package/src/server/internal/batchHandler.ts +61 -42
- package/src/server/internal/clientErrors.ts +2 -1
- package/src/server/internal/deferrableAttempt.ts +5 -1
- package/src/server/internal/ensureQueue.ts +18 -20
- package/src/server/internal/failureOutput.ts +9 -0
- package/src/server/internal/lifecycle.ts +13 -16
- package/src/server/internal/listJobs.ts +57 -47
- package/src/server/internal/makeService.ts +1 -1
- package/src/server/internal/register.ts +68 -66
- package/src/server/internal/registerReleasedJobs.ts +8 -3
- package/src/server/internal/registerWorker.ts +35 -46
- package/src/server/internal/retryWake.ts +33 -0
- package/src/server/internal/runQueueWorker.ts +19 -0
- package/src/server/internal/schemaIndexBuilds.ts +6 -2
- package/src/server/schema.ts +22 -6
- package/src/server/service.ts +84 -49
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.23.0 - 2026-10-30
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Export modules under `internal/` in `contract` and `react` and `server/internal/` in `jobs` through the existing `.ts` wildcard, so consumers can import those modules directly by their file paths.
|
|
8
|
+
- Jobs services share one scoped pg-boss client through the Effect environment. Registration, worker and producer Layers use the same connection and pool settings.
|
|
9
|
+
- Service definitions accept marked generic methods alongside declared dependencies. Generic signatures retain their caller requirements unchanged; initialization can capture declared dependencies as private state.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Retry wake-up reads run within the worker scope and log redacted failures without failing other jobs in the batch or spending their retries.
|
|
14
|
+
- Default pg-boss client error logs redact secrets in messages through `@shivaedev/errors`.
|
|
15
|
+
- Keep job batches, handler timeouts, retry wakeups and client error callbacks in the Layer's captured Effect environment, preserving worker logging context, Clock and scoped interruption while allowing native graceful stop to drain active handlers.
|
|
16
|
+
- Retry queue creation deadlocks with an Effect Schedule, and report RetryAt settlement failures as typed PgBossError failures.
|
|
17
|
+
- Decode schema inspection and index recovery rows before using them.
|
|
18
|
+
|
|
19
|
+
### Breaking
|
|
20
|
+
|
|
21
|
+
- Jobs handler failures persist only `JobFailure` (`_tag` and a redacted `message`); failed and dead-letter listings and admin job responses expose that shape or `null`. Consumers can import the shared `JobFailure` Schema from `@shivaedev/jobs/JobFailure.ts` and must read these fields instead of arbitrary error properties, stacks or causes. Older and native pg-boss failures without a tag decode with `_tag: "Error"`, and their messages are redacted when read; outputs without a string message fail decoding.
|
|
22
|
+
- Jobs listings reject invalid page limits and cursors with `SchemaError`; consumers must handle it alongside `PgBossError` and `PgBossPayloadError`. Admin listings report these inputs as `BadRequest`; clients must handle that rejection instead of `JobsUnavailable`.
|
|
23
|
+
- Custom `PgBossClient` implementations must honor pg-boss's `offWork(name, { id, wait })` options. Scoped workers now unregister their own registration and drain its active batch before releasing handler services, including when Layers share a cached client. Forward these options to native pg-boss; the default client needs no migration.
|
|
24
|
+
- Move connection, pool, client factory, cache key and stop options from each `Jobs.layer` call into one `pgBossLayer` from `@shivaedev/jobs/server/service.ts`. Supply `connectionString` as `Redacted<string>` and provide that Layer to the merged jobs services. Keep only `jobs` and `onError` in `Jobs.layer`.
|
|
25
|
+
- Call `jobs.health()` instead of yielding `jobs.health`. Custom jobs service implementations must expose health as a method. Admin's built-in jobs handlers call the method automatically. Jobs services passed to webhook routes and enqueue helpers must also implement the new method shape.
|
|
26
|
+
|
|
3
27
|
## 0.22.1 - 2026-10-30
|
|
4
28
|
|
|
5
29
|
### Changed
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ A **queue definition** names a pg-boss queue and the Schema of its payload. Appl
|
|
|
29
29
|
|
|
30
30
|
A **schedule definition** describes a queue with a cron trigger. `schedule.run(effect)` pairs it with an Effect that needs no payload. Queue workers and scheduled workers are **registrations**: the values you put in the jobs Layer's `jobs` list.
|
|
31
31
|
|
|
32
|
-
The application creates one jobs service with `makePgBoss(identifier)`. Its Layer
|
|
32
|
+
The application creates one jobs service with `makePgBoss(identifier)`. Its Layer reads the shared `PgBoss` service, registers the job list and captures the services those workers need. One `pgBossLayer` owns the client and pool for the application; feature registrations drain before that Layer closes its client. Callers use the jobs service to enqueue a decoded payload, look up or retry a job, read queue health and live counts, or list failed and dead-lettered jobs.
|
|
33
33
|
|
|
34
34
|
Use a distinct literal identifier for each jobs service. The service and its Layer keep that identifier in their types, so providing a Layer for a different identifier leaves the required jobs service unprovided at compile time.
|
|
35
35
|
|
|
@@ -68,7 +68,7 @@ const jobsFixture = installPgBossSchema({ schema: "app_jobs" });
|
|
|
68
68
|
|
|
69
69
|
The Effect requires `SqlClient` and fails with `PgBossError` whose `operation` is `"install"`. The schema defaults to `"pgboss"`. Repeating installation preserves existing jobs. Upgrades apply pg-boss's migration SQL and concurrent index builds, including partition indexes, before returning. Pending index commands are recorded in pg-boss's BAM table in the same transaction as the schema version. A retry resumes unfinished commands and repairs invalid indexes left by failed builds, even when the schema version has already committed.
|
|
70
70
|
|
|
71
|
-
After installation, pass the same schema and `migrate: false` to `
|
|
71
|
+
After installation, pass the same schema and `migrate: false` to `pgBossLayer` to start producers and workers without schema installation or migration. Startup fails if the schema is missing. Ordinary Layer startup retains pg-boss's default migration behavior when `migrate` is omitted.
|
|
72
72
|
|
|
73
73
|
### Once per application: the jobs service
|
|
74
74
|
|
|
@@ -76,22 +76,22 @@ Define the application's jobs service and worker dependencies in `services.ts`:
|
|
|
76
76
|
|
|
77
77
|
```ts
|
|
78
78
|
import { makePgBoss } from "@shivaedev/jobs/server/service.ts";
|
|
79
|
-
import {
|
|
79
|
+
import { Effect } from "effect";
|
|
80
|
+
import { defineService } from "@shivaedev/service/defineService.ts";
|
|
80
81
|
|
|
81
82
|
export const Jobs = makePgBoss("@app/Jobs");
|
|
82
83
|
|
|
83
|
-
export
|
|
84
|
-
Mail,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
export const MailLive = Layer.succeed(Mail, {
|
|
92
|
-
send: (userId) => Effect.log({ event: "send_email", userId }),
|
|
93
|
-
removeExpired: Effect.log({ event: "remove_expired_mail" }),
|
|
84
|
+
export const Mail = defineService({
|
|
85
|
+
id: "@app/Mail",
|
|
86
|
+
requires: [],
|
|
87
|
+
initialize: Effect.void,
|
|
88
|
+
methods: () => ({
|
|
89
|
+
send: (userId: number) => Effect.log({ event: "send_email", userId }),
|
|
90
|
+
removeExpired: () => Effect.log({ event: "remove_expired_mail" }),
|
|
91
|
+
}),
|
|
94
92
|
});
|
|
93
|
+
|
|
94
|
+
export const MailLive = Mail.layer;
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
`Jobs` is the service that callers yield. `Mail` is a separate domain service that workers use. The example implementation logs calls so the wiring is complete; an application supplies its own implementation of those methods. The jobs package does not need a provider-specific interface.
|
|
@@ -124,7 +124,7 @@ export const Cleanup = defineSchedule({
|
|
|
124
124
|
cron: "17 3 * * *",
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
-
export const cleanupWorker = Cleanup.run(Effect.flatMap(Mail, (mail) => mail.removeExpired));
|
|
127
|
+
export const cleanupWorker = Cleanup.run(Effect.flatMap(Mail, (mail) => mail.removeExpired()));
|
|
128
128
|
```
|
|
129
129
|
|
|
130
130
|
The queue takes `{ userId: number }` in application code and stores `{ userId: string }`. Its handler receives the decoded number and a job context, including the job's `id`. Keep the queue definition available to producers; the runtime registers the worker created by `handle`.
|
|
@@ -150,7 +150,7 @@ const Compare = defineQueue({
|
|
|
150
150
|
|
|
151
151
|
This worker runs up to five handlers at once. `worker` accepts pg-boss 12's `WorkOptions`, including `batchSize`, `localConcurrency`, `pollingIntervalSeconds`, `notifyPollingIntervalSeconds` and the burst options. Explicit options override the adapter defaults. pg-boss ignores `burstWhenBatchFull` at `batchSize: 1`; keep a batch size of at least two for immediate backlog draining. Each job is settled separately through pg-boss: success completes that job, and a typed failure, payload decoding failure or defect fails only that job with its own error. A failed job does not spend the retries of other jobs in its batch or rerun their successful handlers. Interruption stops the batch and leaves the interrupted and remaining jobs to pg-boss expiry; handlers must still tolerate repeated side effects across retries and interrupted attempts.
|
|
152
152
|
|
|
153
|
-
Apps do not need to shorten the polling backstop to drain a backlog. With `notify: true` and an active LISTEN/NOTIFY listener, pg-boss wakes workers on notifications and defaults to a 30-second backstop (`notifyPollingIntervalSeconds`). Without active notifications its base poll defaults to two seconds (`pollingIntervalSeconds`). Bursting takes precedence over both intervals. After an adapter worker fails a job, it reads pg-boss's stored retry time and schedules a wake for every native worker in its registration at that time, so an idle sibling can retry while another worker is busy. The wake belongs to the worker Layer's scope and is canceled when that scope closes. Override the backstop when the application needs a different bound for other work that becomes runnable without a notification, such as delayed jobs or retries initiated outside the adapter worker.
|
|
153
|
+
Apps do not need to shorten the polling backstop to drain a backlog. With `notify: true` and an active LISTEN/NOTIFY listener, pg-boss wakes workers on notifications and defaults to a 30-second backstop (`notifyPollingIntervalSeconds`). Without active notifications its base poll defaults to two seconds (`pollingIntervalSeconds`). Bursting takes precedence over both intervals. After an adapter worker fails a job, it reads pg-boss's stored retry time and schedules a wake for every native worker in its registration at that time, so an idle sibling can retry while another worker is busy. The wake, including its retry-time read, belongs to the worker Layer's scope and is canceled when that scope closes. Wake failures are logged with redacted diagnostics and do not fail the batch. Override the backstop when the application needs a different bound for other work that becomes runnable without a notification, such as delayed jobs or retries initiated outside the adapter worker.
|
|
154
154
|
|
|
155
155
|
### Defer until a provider is ready
|
|
156
156
|
|
|
@@ -241,34 +241,34 @@ Keep handler work interruptible and use cancellation-aware Effect integrations f
|
|
|
241
241
|
Build the jobs Layer in `runtime.ts`:
|
|
242
242
|
|
|
243
243
|
```ts
|
|
244
|
-
import { Layer } from "effect";
|
|
244
|
+
import { Layer, type Redacted } from "effect";
|
|
245
|
+
import { pgBossLayer } from "@shivaedev/jobs/server/service.ts";
|
|
245
246
|
import { cleanupWorker, emailWorker } from "./jobs.ts";
|
|
246
247
|
import { Jobs, MailLive } from "./services.ts";
|
|
247
248
|
|
|
248
|
-
export const jobsLayer = (databaseUrl: string) =>
|
|
249
|
-
Jobs.layer({
|
|
250
|
-
|
|
251
|
-
schema: "app_jobs",
|
|
252
|
-
|
|
253
|
-
}).pipe(Layer.provide(MailLive));
|
|
249
|
+
export const jobsLayer = (databaseUrl: Redacted.Redacted<string>) =>
|
|
250
|
+
Jobs.layer({ jobs: [emailWorker, cleanupWorker] }).pipe(
|
|
251
|
+
Layer.provide(MailLive),
|
|
252
|
+
Layer.provide(pgBossLayer({ connectionString: databaseUrl, schema: "app_jobs" })),
|
|
253
|
+
);
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
-
The
|
|
256
|
+
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 startup or registration failure fails Layer acquisition with `PgBossError` or `PgBossQueueOptionsError` and closes its registrations. 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.
|
|
257
257
|
|
|
258
258
|
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.
|
|
259
259
|
|
|
260
|
-
Set `clientCacheKey` 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.
|
|
260
|
+
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.
|
|
261
261
|
|
|
262
262
|
```ts
|
|
263
|
-
import { Effect } from "effect";
|
|
263
|
+
import { Effect, type Redacted } from "effect";
|
|
264
264
|
import { jobsLayer } from "./runtime.ts";
|
|
265
265
|
import { Jobs } from "./services.ts";
|
|
266
266
|
|
|
267
|
-
const inspectJobs = (databaseUrl: string) =>
|
|
267
|
+
const inspectJobs = (databaseUrl: Redacted.Redacted<string>) =>
|
|
268
268
|
Effect.scoped(
|
|
269
269
|
Effect.gen(function* () {
|
|
270
270
|
const jobs = yield* Jobs;
|
|
271
|
-
return yield* jobs.health;
|
|
271
|
+
return yield* jobs.health();
|
|
272
272
|
}).pipe(Effect.provide(jobsLayer(databaseUrl))),
|
|
273
273
|
);
|
|
274
274
|
```
|
|
@@ -309,7 +309,7 @@ import { Jobs } from "./services.ts";
|
|
|
309
309
|
|
|
310
310
|
export const readJobCounts = Effect.gen(function* () {
|
|
311
311
|
const jobs = yield* Jobs;
|
|
312
|
-
const health = yield* jobs.health;
|
|
312
|
+
const health = yield* jobs.health();
|
|
313
313
|
return {
|
|
314
314
|
active: health.activeTotal,
|
|
315
315
|
deadLettered: health.deadLetteredTotal,
|
|
@@ -367,9 +367,9 @@ export const failedEmails = (cursor?: string) =>
|
|
|
367
367
|
|
|
368
368
|
`health` and `counts` say how many jobs failed; these two listings say which ones and why. `failedJobs(queue, options)` lists the queue's jobs in the `failed` state, the ones that used up their retries. `deadLetteredJobs(queue, options)` lists every job in the queue's dead-letter queue. Dead-letter entries live in the `-dlq` queue: each is a new job with its own ID that pg-boss copied there when the original failed for good. Both listings read pg-boss's `job` table on each call, through the jobs Layer's own pg-boss connection and in its configured schema, so applications never query pg-boss tables themselves. A custom client needs the native `getDb` capability for them.
|
|
369
369
|
|
|
370
|
-
Each page holds at most `limit` jobs, newest first by creation time; a dead-letter copy is created when its original fails for good. `limit` must be a positive integer. When more jobs remain, `next` is `Some` opaque cursor; pass it back as `cursor` for the following page, and stop when `next` is `None`. Paging continues from the last job it returned, so jobs that fail while you page appear in a fresh listing instead of shifting later pages, and no job appears twice. A malformed cursor or limit fails with `
|
|
370
|
+
Each page holds at most `limit` jobs, newest first by creation time; a dead-letter copy is created when its original fails for good. `limit` must be a positive integer. When more jobs remain, `next` is `Some` opaque cursor; pass it back as `cursor` for the following page, and stop when `next` is `None`. Paging continues from the last job it returned, so jobs that fail while you page appear in a fresh listing instead of shifting later pages, and no job appears twice. A malformed cursor or limit fails with `SchemaError` before pg-boss is called.
|
|
371
371
|
|
|
372
|
-
An entry carries the job's `id`, `queue`, native `state`, `retryCount`, `retryLimit` and `attempt`, the one-based number of its last started attempt (zero for a job that never started). `createdOn` is a UTC `DateTime`; `startedOn` and `completedOn` are `Option`s of UTC `DateTime`s. `output` is
|
|
372
|
+
An entry carries the job's `id`, `queue`, native `state`, `retryCount`, `retryLimit` and `attempt`, the one-based number of its last started attempt (zero for a job that never started). `createdOn` is a UTC `DateTime`; `startedOn` and `completedOn` are `Option`s of UTC `DateTime`s. `output` is `JobFailure | null`, decoded through `JobFailure` from `@shivaedev/jobs/JobFailure.ts`. Handler failures store only `{ _tag: string, message: string }`, with the message redacted through `@shivaedev/errors`; stack traces, cause chains and other error fields are omitted. `null` means pg-boss stored no output. Native pg-boss failures without a tag decode with `_tag: "Error"`; decoding also redacts messages from older stored failures. Stored output that does not match the Schema fails the listing with `PgBossPayloadError`. `data` is decoded by the queue's Schema, including traced payloads; invalid stored data fails the listing with `PgBossPayloadError`, as `getJob` does, and the Effect requires the Schema's decoding services. A dead-letter entry adds `sourceId`, the original job's ID as an `Option`, and `sourceOutput`, the original's decoded `JobFailure | null`. The copy has not run, so its own `output` stays `null` and its `attempt` is zero.
|
|
373
373
|
|
|
374
374
|
Pass a failed entry's `id` to `retry(queue, id)` to run that job again under its original ID; once it completes it leaves the failed listing. Dead-letter IDs belong to the `-dlq` queue, so `retry(queue, id)` does not find them and leaves them unchanged.
|
|
375
375
|
|
|
@@ -382,20 +382,19 @@ Startup creates missing queues and reconciles declared settings on existing queu
|
|
|
382
382
|
### Share a client between Layer builds
|
|
383
383
|
|
|
384
384
|
```ts
|
|
385
|
-
import { Layer } from "effect";
|
|
385
|
+
import { Layer, type Redacted } from "effect";
|
|
386
|
+
import { pgBossLayer } from "@shivaedev/jobs/server/service.ts";
|
|
386
387
|
import { cleanupWorker, emailWorker } from "./jobs.ts";
|
|
387
388
|
import { Jobs, MailLive } from "./services.ts";
|
|
388
389
|
|
|
389
|
-
const sharedJobsLayer = (databaseUrl: string) =>
|
|
390
|
-
Jobs.layer({
|
|
391
|
-
|
|
392
|
-
schema: "app_jobs",
|
|
393
|
-
|
|
394
|
-
jobs: [emailWorker, cleanupWorker],
|
|
395
|
-
}).pipe(Layer.provide(MailLive));
|
|
390
|
+
const sharedJobsLayer = (databaseUrl: Redacted.Redacted<string>) =>
|
|
391
|
+
Jobs.layer({ jobs: [emailWorker, cleanupWorker] }).pipe(
|
|
392
|
+
Layer.provide(MailLive),
|
|
393
|
+
Layer.provide(pgBossLayer({ connectionString: databaseUrl, schema: "app_jobs", clientCacheKey: "app-jobs" })),
|
|
394
|
+
);
|
|
396
395
|
```
|
|
397
396
|
|
|
398
|
-
Overlapping Layer builds with the same `clientCacheKey` share one started client. The later build replaces the registered worker, and the final scope release stops the shared client. A later build after that release starts a new client.
|
|
397
|
+
Overlapping Layer builds with the same `clientCacheKey` share one started client. The later build replaces the registered worker, and the final scope release stops the shared client. A later build after that release starts a new client. Within one Layer graph, merged feature services share the provided app client without a cache key. Separate app Layer builds create separate clients without a key. The application chooses whether to pass a key; give each distinct constructor configuration its own key.
|
|
399
398
|
|
|
400
399
|
### Separate producers and workers
|
|
401
400
|
|
|
@@ -405,10 +404,10 @@ Pass a queue definition directly in the jobs Layer to create its queue and dead-
|
|
|
405
404
|
import { SendEmail } from "./jobs.ts";
|
|
406
405
|
import { Jobs } from "./services.ts";
|
|
407
406
|
|
|
408
|
-
export const producerLayer =
|
|
407
|
+
export const producerLayer = Jobs.layer({ jobs: [SendEmail] });
|
|
409
408
|
```
|
|
410
409
|
|
|
411
|
-
Provide this Layer
|
|
410
|
+
Provide the app `pgBossLayer` to this Layer in the request runtime and call `jobs.enqueue(SendEmail, { userId })` as above. A separate worker process registers `SendEmail.handle(...)` against the same database. Producer queues use the same retry options and appear in `health`; only worker registrations capture handler services.
|
|
412
411
|
|
|
413
412
|
### Enqueue follow-ups from a handler
|
|
414
413
|
|
|
@@ -429,17 +428,14 @@ const sendAndQueueReceipt = SendEmail.handle(({ userId }) =>
|
|
|
429
428
|
}),
|
|
430
429
|
);
|
|
431
430
|
|
|
432
|
-
const live = Jobs.layer({
|
|
433
|
-
connectionString: databaseUrl,
|
|
434
|
-
jobs: [sendAndQueueReceipt, Receipt],
|
|
435
|
-
}).pipe(Layer.provide(MailLive));
|
|
431
|
+
const live = Jobs.layer({ jobs: [sendAndQueueReceipt, Receipt] }).pipe(Layer.provide(MailLive));
|
|
436
432
|
```
|
|
437
433
|
|
|
438
434
|
Include every target queue in `jobs`, as either a worker or a producer-only definition. Startup creates all queues before starting consumers. The example registers `Receipt` for another process to consume. A follow-up target can also have a worker in the same Layer. Scheduled effects can yield `Jobs` too. Keep one jobs Layer in the process's native Layer graph; that Layer owns one client for enqueueing and handling.
|
|
439
435
|
|
|
440
436
|
### Test through the queue contract
|
|
441
437
|
|
|
442
|
-
`testing.ts` gives story kits a controller for one real pg-boss client. Create a fresh controller per runtime, pass its `clientFactory` to
|
|
438
|
+
`testing.ts` gives story kits a controller for one real pg-boss client. Create a fresh controller per runtime, pass its `clientFactory` to `pgBossLayer`, and keep that Layer scoped as usual. `jobs(queue, options?)` returns native job metadata with `data` decoded through the queue's Schema, including traced payloads. Invalid durable data fails with `PgBossPayloadError`; decoding services remain in the Effect's requirements.
|
|
443
439
|
|
|
444
440
|
This producer story uses the `SendEmail` definition and `Jobs` service from above. `databaseUrl` points to the story's PostgreSQL database:
|
|
445
441
|
|
|
@@ -447,6 +443,7 @@ This producer story uses the `SendEmail` definition and `Jobs` service from abov
|
|
|
447
443
|
import { Context, Layer, Option } from "effect";
|
|
448
444
|
import { expect } from "vitest";
|
|
449
445
|
import { storyKit } from "@shivaedev/test-story/server/storyKit.ts";
|
|
446
|
+
import { pgBossLayer } from "@shivaedev/jobs/server/service.ts";
|
|
450
447
|
import { makePgBossTesting, testRetryPolicy } from "@shivaedev/jobs/server/testing.ts";
|
|
451
448
|
|
|
452
449
|
const emailStories = storyKit({
|
|
@@ -454,11 +451,7 @@ const emailStories = storyKit({
|
|
|
454
451
|
*create() {
|
|
455
452
|
const testing = makePgBossTesting({ retryPolicy: testRetryPolicy });
|
|
456
453
|
const context = yield* Layer.build(
|
|
457
|
-
Jobs.layer({
|
|
458
|
-
connectionString: databaseUrl,
|
|
459
|
-
clientFactory: testing.clientFactory,
|
|
460
|
-
jobs: [SendEmail],
|
|
461
|
-
}),
|
|
454
|
+
Jobs.layer({ jobs: [SendEmail] }).pipe(Layer.provide(pgBossLayer({ connectionString: databaseUrl, clientFactory: testing.clientFactory }))),
|
|
462
455
|
);
|
|
463
456
|
return { jobs: Context.get(context, Jobs), testing };
|
|
464
457
|
},
|
|
@@ -503,7 +496,8 @@ Import the module that defines the name; the package has no root entry.
|
|
|
503
496
|
| Module | Public names |
|
|
504
497
|
| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
505
498
|
| `@shivaedev/jobs/server/definition.ts` | `defineQueue`, `defineSchedule`, `jobContext`, `RetryAt`; `DefineQueueOptions`, `DefineScheduleOptions`, `JobContext`, `JobPayloadSchema`, `JobRegistration`, `QueueDefinition`, `QueueOptions`, `QueuePolicy`, `QueueWorker`, `RegistrationRequirements`, `ScheduleDefinition`, `ScheduledWorker` |
|
|
506
|
-
| `@shivaedev/jobs/server/service.ts` | `makePgBoss`; `PgBossDefinition`, `PgBossLayerOptions`, `PgBossService`
|
|
499
|
+
| `@shivaedev/jobs/server/service.ts` | `makePgBoss`, `pgBossLayer`; `PgBossDefinition`, `PgBossLayerOptions`, `PgBossOptions`, `PgBossService` |
|
|
500
|
+
| `@shivaedev/jobs/server/PgBoss.ts` | `PgBoss`: the shared client Context service. |
|
|
507
501
|
| `@shivaedev/jobs/server/schema.ts` | `installPgBossSchema`, `pgBossSchema`; `PgBossSchemaOptions` |
|
|
508
502
|
| `@shivaedev/jobs/server/health.ts` | `deadLetterQueueName`; `DeadLetteredJob`, `JobPage`, `JobPageOptions`, `JobsHealth`, `ListedJob`, `QueueCounts`, `QueueHealth` |
|
|
509
503
|
| `@shivaedev/jobs/server/error.ts` | `PgBossError`, `PgBossPayloadError`, `PgBossQueueOptionsError`, `PgBossClientOptionsError`, `PgBossTestingError`, `toPgBossError`; `PgBossOperation` |
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
export declare const JobFailure: Schema.Struct<{
|
|
3
|
+
readonly _tag: Schema.withDecodingDefaultKey<Schema.String, never>;
|
|
4
|
+
readonly message: Schema.decodeTo<Schema.String, Schema.String, never, never>;
|
|
5
|
+
}>;
|
|
6
|
+
export type JobFailure = typeof JobFailure.Type;
|
|
7
|
+
//# sourceMappingURL=JobFailure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JobFailure.d.ts","sourceRoot":"","sources":["../src/JobFailure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,MAAM,EAAgB,MAAM,QAAQ,CAAC;AAItD,eAAO,MAAM,UAAU;;;EAGrB,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Effect, Schema, SchemaGetter } from "effect";
|
|
2
|
+
import { isSensitiveKey, redactText } from "@shivaedev/errors/sensitive.ts";
|
|
3
|
+
const redactMessage = SchemaGetter.transform((message) => redactText(message, isSensitiveKey));
|
|
4
|
+
export const JobFailure = Schema.Struct({
|
|
5
|
+
_tag: Schema.String.pipe(Schema.withDecodingDefaultKey(Effect.succeed("Error"))),
|
|
6
|
+
message: Schema.String.pipe(Schema.decodeTo(Schema.String, { decode: redactMessage, encode: redactMessage })),
|
|
7
|
+
});
|
|
8
|
+
//# sourceMappingURL=JobFailure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JobFailure.js","sourceRoot":"","sources":["../src/JobFailure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAE5E,MAAM,aAAa,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;AACvG,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAChF,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;CAC7G,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
import type { StopOptions } from "pg-boss";
|
|
3
|
+
import type { AcquiredClient } from "#internal/lifecycle.ts";
|
|
4
|
+
declare const PgBoss_base: Context.ServiceClass<PgBoss, "@shivaedev/jobs/PgBoss", AcquiredClient & {
|
|
5
|
+
readonly schema: string | undefined;
|
|
6
|
+
readonly stop: StopOptions | undefined;
|
|
7
|
+
}>;
|
|
8
|
+
export declare class PgBoss extends PgBoss_base {
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=PgBoss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PgBoss.d.ts","sourceRoot":"","sources":["../../src/server/PgBoss.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;;qBAIxB,MAAM,GAAG,SAAS;mBAAiB,WAAW,GAAG,SAAS;;AAF/F,qBAAa,MAAO,SAAQ,WAGC;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PgBoss.js","sourceRoot":"","sources":["../../src/server/PgBoss.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAIjC,MAAM,OAAO,MAAO,SAAQ,OAAO,CAAC,OAAO,EAGxC,CAAC,wBAAwB,CAAC;CAAG"}
|
package/dist/server/client.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface PgBossClient {
|
|
|
9
9
|
readonly getWipData?: PgBoss["getWipData"];
|
|
10
10
|
readonly notifyWorker?: PgBoss["notifyWorker"];
|
|
11
11
|
readonly off: (event: "error", listener: (error: Error) => void) => unknown;
|
|
12
|
-
readonly offWork:
|
|
12
|
+
readonly offWork: PgBoss["offWork"];
|
|
13
13
|
readonly on: (event: "error", listener: (error: Error) => void) => unknown;
|
|
14
14
|
readonly retry?: PgBoss["retry"];
|
|
15
15
|
readonly schedule: (name: string, cron: string, data?: object | null, options?: ScheduleOptions) => Promise<void>;
|
|
@@ -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;AAGjB,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,
|
|
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;AAGjB,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;AAEhF,eAAO,MAAM,oBAAoB,EAAE,mBAAkC,CAAC"}
|
package/dist/server/health.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DateTime, Option } from "effect";
|
|
2
2
|
import type { JobWithMetadata } from "pg-boss";
|
|
3
|
+
import type { JobFailure } from "#JobFailure.ts";
|
|
3
4
|
export interface QueueCounts {
|
|
4
5
|
readonly activeCount: number;
|
|
5
6
|
readonly failedCount: number;
|
|
@@ -29,7 +30,7 @@ export interface ListedJob<TData> {
|
|
|
29
30
|
readonly createdOn: DateTime.Utc;
|
|
30
31
|
readonly data: TData;
|
|
31
32
|
readonly id: string;
|
|
32
|
-
readonly output:
|
|
33
|
+
readonly output: JobFailure | null;
|
|
33
34
|
readonly queue: string;
|
|
34
35
|
readonly retryCount: number;
|
|
35
36
|
readonly retryLimit: number;
|
|
@@ -38,7 +39,7 @@ export interface ListedJob<TData> {
|
|
|
38
39
|
}
|
|
39
40
|
export interface DeadLetteredJob<TData> extends ListedJob<TData> {
|
|
40
41
|
readonly sourceId: Option.Option<string>;
|
|
41
|
-
readonly sourceOutput:
|
|
42
|
+
readonly sourceOutput: JobFailure | null;
|
|
42
43
|
}
|
|
43
44
|
export interface JobPageOptions {
|
|
44
45
|
readonly cursor?: string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/server/health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/server/health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,MAAM,WAAW,SAAS,CAAC,KAAK;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAClD,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,eAAe,CAAC,KAAK,CAAE,SAAQ,SAAS,CAAC,KAAK,CAAC;IAC/D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACzC,QAAQ,CAAC,YAAY,EAAE,UAAU,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,OAAO,CAAC,IAAI;IAC5B,QAAQ,CAAC,IAAI,EAAE,SAAS,IAAI,EAAE,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;CACrC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/server/health.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/server/health.ts"],"names":[],"mappings":"AA6BA,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACpD,OAAO,GAAG,SAAS,MAAM,CAAC;AAC3B,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import type { Job } from "pg-boss";
|
|
3
3
|
import type { PgBossClient } from "#client.ts";
|
|
4
|
-
export
|
|
4
|
+
export type PgBossRunner = <A, E>(effect: Effect.Effect<A, E>) => Promise<A>;
|
|
5
|
+
export declare function batchHandler(client: PgBossClient, name: string, run: (job: Job<unknown>) => Effect.Effect<unknown, unknown>, afterFailure?: (job: Job<unknown>) => Effect.Effect<void, unknown>): (jobs: readonly Job<unknown>[]) => Effect.Effect<void, unknown, never>;
|
|
5
6
|
//# sourceMappingURL=batchHandler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batchHandler.d.ts","sourceRoot":"","sources":["../../../src/server/internal/batchHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAQ,MAAM,QAAQ,CAAC;AACpD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"batchHandler.d.ts","sourceRoot":"","sources":["../../../src/server/internal/batchHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAQ,MAAM,QAAQ,CAAC;AACpD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAuB/C,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAgB7E,wBAAgB,YAAY,CAC3B,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,EAC3D,YAAY,GAAE,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAqB,UA6BvE,SAAS,GAAG,CAAC,OAAO,CAAC,EAAE,yCAerC"}
|
|
@@ -1,51 +1,69 @@
|
|
|
1
1
|
import { Cause, Clock, Effect, Exit } from "effect";
|
|
2
|
+
import { toPgBossError } from "#error.ts";
|
|
2
3
|
import { deadlineOf } from "#internal/deadlineOf.ts";
|
|
3
4
|
import { deferredAttempt } from "#internal/deferral.ts";
|
|
5
|
+
import { failureOutput } from "#internal/failureOutput.ts";
|
|
4
6
|
import { waitForBatchExpiry } from "#internal/waitForBatchExpiry.ts";
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
function settleAttempt(complete, fail, name, job, exit) {
|
|
8
|
+
if (Exit.isSuccess(exit) && exit.value === deferredAttempt) {
|
|
9
|
+
return Effect.void;
|
|
10
|
+
}
|
|
11
|
+
return Effect.tryPromise({
|
|
12
|
+
catch: (error) => toPgBossError("settle", error, name),
|
|
13
|
+
try: () => (Exit.isSuccess(exit) ? complete(name, job) : fail(name, job, failureOutput(exit.cause))),
|
|
14
|
+
});
|
|
8
15
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
function aborted(signal) {
|
|
17
|
+
return Effect.callback((resume) => {
|
|
18
|
+
function interrupt() {
|
|
19
|
+
resume(Effect.interrupt);
|
|
13
20
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
if (signal.aborted) {
|
|
22
|
+
interrupt();
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
signal.addEventListener("abort", interrupt, { once: true });
|
|
26
|
+
}
|
|
27
|
+
return Effect.sync(() => signal.removeEventListener("abort", interrupt));
|
|
28
|
+
});
|
|
19
29
|
}
|
|
20
|
-
export function batchHandler(client, name, run, afterFailure
|
|
30
|
+
export function batchHandler(client, name, run, afterFailure = () => Effect.void) {
|
|
21
31
|
const complete = client.complete?.bind(client);
|
|
22
32
|
const fail = client.fail?.bind(client);
|
|
23
33
|
if (complete === undefined || fail === undefined) {
|
|
24
34
|
throw new TypeError("This pg-boss client does not support complete and fail");
|
|
25
35
|
}
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
36
|
+
const handle = Effect.fnUntraced(function* (job) {
|
|
37
|
+
if (job.signal.aborted) {
|
|
38
|
+
return "interrupted";
|
|
39
|
+
}
|
|
40
|
+
const remaining = deadlineOf(job) - (yield* Clock.currentTimeMillis);
|
|
41
|
+
if (remaining <= 0) {
|
|
42
|
+
return "expired";
|
|
43
|
+
}
|
|
44
|
+
const exit = yield* run(job).pipe(Effect.timeoutOrElse({ duration: remaining, orElse: () => Effect.interrupt }), Effect.raceFirst(aborted(job.signal)), Effect.exit);
|
|
45
|
+
if (job.signal.aborted || (Exit.isFailure(exit) && Cause.hasInterrupts(exit.cause))) {
|
|
46
|
+
return "interrupted";
|
|
47
|
+
}
|
|
48
|
+
yield* settleAttempt(complete, fail, name, job, exit);
|
|
49
|
+
if (Exit.isFailure(exit)) {
|
|
50
|
+
yield* afterFailure(job);
|
|
51
|
+
}
|
|
52
|
+
return "settled";
|
|
53
|
+
});
|
|
54
|
+
return (jobs) => Effect.gen(function* () {
|
|
55
|
+
const waitForExpiry = waitForBatchExpiry(client, name, jobs).pipe(Effect.tapError(Effect.logError));
|
|
30
56
|
let expired = false;
|
|
31
57
|
for (const job of jobs) {
|
|
32
|
-
const
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
const exit = await Effect.runPromiseExit(Effect.flatMap(Clock.currentTimeMillis, (now) => {
|
|
38
|
-
const remaining = deadline - now;
|
|
39
|
-
return remaining <= 0 ? Effect.interrupt : run(job).pipe(Effect.timeoutOrElse({ duration: remaining, orElse: () => Effect.interrupt }));
|
|
40
|
-
}), { signal: job.signal });
|
|
41
|
-
if (job.signal.aborted || (Exit.isFailure(exit) && Cause.hasInterrupts(exit.cause))) {
|
|
42
|
-
return waitForExpiry(jobs);
|
|
58
|
+
const outcome = yield* handle(job);
|
|
59
|
+
if (outcome === "interrupted") {
|
|
60
|
+
return yield* waitForExpiry;
|
|
43
61
|
}
|
|
44
|
-
|
|
62
|
+
expired ||= outcome === "expired";
|
|
45
63
|
}
|
|
46
64
|
if (expired) {
|
|
47
|
-
|
|
65
|
+
yield* waitForExpiry;
|
|
48
66
|
}
|
|
49
|
-
};
|
|
67
|
+
});
|
|
50
68
|
}
|
|
51
69
|
//# sourceMappingURL=batchHandler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batchHandler.js","sourceRoot":"","sources":["../../../src/server/internal/batchHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAGpD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,SAAS,aAAa,
|
|
1
|
+
{"version":3,"file":"batchHandler.js","sourceRoot":"","sources":["../../../src/server/internal/batchHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientErrors.d.ts","sourceRoot":"","sources":["../../../src/server/internal/clientErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"clientErrors.d.ts","sourceRoot":"","sources":["../../../src/server/internal/clientErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,KAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAYvC,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAGhE;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAelF;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,IAAI,CAO1F"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
+
import { isSensitiveKey, redactText } from "@shivaedev/errors/sensitive.ts";
|
|
2
3
|
const key = Symbol.for("@shivaedev/jobs/server/error-observers");
|
|
3
4
|
const shared = Reflect.get(globalThis, key);
|
|
4
5
|
const observers = shared instanceof WeakMap ? shared : new WeakMap();
|
|
5
6
|
Reflect.set(globalThis, key, observers);
|
|
6
7
|
export function logClientError(error) {
|
|
7
|
-
const message = { event: "pg_boss_error", message: error.message };
|
|
8
|
+
const message = { event: "pg_boss_error", message: redactText(error.message, isSensitiveKey) };
|
|
8
9
|
return Reflect.get(error, "code") === "57P01" ? Effect.logDebug(message) : Effect.logError(message);
|
|
9
10
|
}
|
|
10
11
|
export function observeClientErrors(client, fallback) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientErrors.js","sourceRoot":"","sources":["../../../src/server/internal/clientErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"clientErrors.js","sourceRoot":"","sources":["../../../src/server/internal/clientErrors.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,5 +3,5 @@ import type { Job } from "pg-boss";
|
|
|
3
3
|
import type { PgBossClient } from "#client.ts";
|
|
4
4
|
import { RetryAt } from "#definition.ts";
|
|
5
5
|
import { deferredAttempt } from "#internal/deferral.ts";
|
|
6
|
-
export declare function deferrableAttempt<A, E, R>(effect: Effect.Effect<A, E, R>, client: PgBossClient, schema: string, job: Job<unknown>, maxDeferrals: number): Effect.Effect<typeof deferredAttempt | A, Exclude<E, import("effect/Types").NoInfer<E> & RetryAt> | (import("effect/Types").NoInfer<E> & RetryAt), R>;
|
|
6
|
+
export declare function deferrableAttempt<A, E, R>(effect: Effect.Effect<A, E, R>, client: PgBossClient, schema: string, job: Job<unknown>, maxDeferrals: number): Effect.Effect<typeof deferredAttempt | A, import("#error.ts").PgBossError | Exclude<E, import("effect/Types").NoInfer<E> & RetryAt> | (import("effect/Types").NoInfer<E> & RetryAt), R>;
|
|
7
7
|
//# sourceMappingURL=deferrableAttempt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deferrableAttempt.d.ts","sourceRoot":"","sources":["../../../src/server/internal/deferrableAttempt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,MAAM,EAAU,MAAM,QAAQ,CAAC;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"deferrableAttempt.d.ts","sourceRoot":"","sources":["../../../src/server/internal/deferrableAttempt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,MAAM,EAAU,MAAM,QAAQ,CAAC;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAqB,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQ3E,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACxC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,EACjB,YAAY,EAAE,MAAM,2LA0BpB"}
|