@shivaedev/jobs 0.31.0 → 0.34.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 +40 -0
- package/README.md +75 -30
- package/dist/server/adapters/inspection.d.ts +5 -0
- package/dist/server/adapters/inspection.d.ts.map +1 -0
- package/dist/server/adapters/inspection.js +25 -0
- package/dist/server/adapters/inspection.js.map +1 -0
- package/dist/server/adapters/inspectionChanges.d.ts +7 -0
- package/dist/server/adapters/inspectionChanges.d.ts.map +1 -0
- package/dist/server/adapters/inspectionChanges.js +23 -0
- package/dist/server/adapters/inspectionChanges.js.map +1 -0
- package/dist/server/adapters/inspectionDeferrals.d.ts +10 -0
- package/dist/server/adapters/inspectionDeferrals.d.ts.map +1 -0
- package/dist/server/adapters/inspectionDeferrals.js +13 -0
- package/dist/server/adapters/inspectionDeferrals.js.map +1 -0
- package/dist/server/adapters/inspectionJobs.d.ts +50 -0
- package/dist/server/adapters/inspectionJobs.d.ts.map +1 -0
- package/dist/server/adapters/inspectionJobs.js +21 -0
- package/dist/server/adapters/inspectionJobs.js.map +1 -0
- package/dist/server/adapters/inspectionOperation.d.ts +3 -0
- package/dist/server/adapters/inspectionOperation.d.ts.map +1 -0
- package/dist/server/adapters/inspectionOperation.js +6 -0
- package/dist/server/adapters/inspectionOperation.js.map +1 -0
- package/dist/server/adapters/inspectionPlan.d.ts +3 -0
- package/dist/server/adapters/inspectionPlan.d.ts.map +1 -0
- package/dist/server/adapters/inspectionPlan.js +20 -0
- package/dist/server/adapters/inspectionPlan.js.map +1 -0
- package/dist/server/adapters/inspectionReads.d.ts +59 -0
- package/dist/server/adapters/inspectionReads.d.ts.map +1 -0
- package/dist/server/adapters/inspectionReads.js +44 -0
- package/dist/server/adapters/inspectionReads.js.map +1 -0
- package/dist/server/adapters/inspectionSnapshot.d.ts +6 -0
- package/dist/server/adapters/inspectionSnapshot.d.ts.map +1 -0
- package/dist/server/{internal/testingSnapshot.js → adapters/inspectionSnapshot.js} +9 -7
- package/dist/server/adapters/inspectionSnapshot.js.map +1 -0
- package/dist/server/adapters/jobEngine.d.ts.map +1 -1
- package/dist/server/adapters/jobEngine.js +0 -4
- package/dist/server/adapters/jobEngine.js.map +1 -1
- package/dist/server/adapters/payloadIdentity.d.ts +3 -0
- package/dist/server/adapters/payloadIdentity.d.ts.map +1 -0
- package/dist/server/adapters/payloadIdentity.js +14 -0
- package/dist/server/adapters/payloadIdentity.js.map +1 -0
- package/dist/server/{internal/testingSignal.d.ts → adapters/queueSignal.d.ts} +2 -2
- package/dist/server/adapters/queueSignal.d.ts.map +1 -0
- package/dist/server/{internal/testingSignal.js → adapters/queueSignal.js} +2 -2
- package/dist/server/adapters/queueSignal.js.map +1 -0
- package/dist/server/adapters/settleDeferral.d.ts.map +1 -1
- package/dist/server/adapters/settleDeferral.js +8 -2
- package/dist/server/adapters/settleDeferral.js.map +1 -1
- package/dist/server/adapters/testingClient.d.ts +1 -2
- package/dist/server/adapters/testingClient.d.ts.map +1 -1
- package/dist/server/adapters/testingClient.js +25 -45
- package/dist/server/adapters/testingClient.js.map +1 -1
- package/dist/server/adapters/testingController.d.ts +58 -12
- package/dist/server/adapters/testingController.d.ts.map +1 -1
- package/dist/server/adapters/testingController.js +40 -18
- package/dist/server/adapters/testingController.js.map +1 -1
- package/dist/server/adapters/testingDueNow.js +1 -1
- package/dist/server/adapters/testingDueNow.js.map +1 -1
- package/dist/server/adapters/testingEngine.d.ts.map +1 -1
- package/dist/server/adapters/testingEngine.js +0 -11
- package/dist/server/adapters/testingEngine.js.map +1 -1
- package/dist/server/adapters/testingInspectionClient.d.ts +5 -0
- package/dist/server/adapters/testingInspectionClient.d.ts.map +1 -0
- package/dist/server/adapters/testingInspectionClient.js +52 -0
- package/dist/server/adapters/testingInspectionClient.js.map +1 -0
- package/dist/server/adapters/testingTime.d.ts +10 -0
- package/dist/server/adapters/testingTime.d.ts.map +1 -0
- package/dist/server/adapters/testingTime.js +18 -0
- package/dist/server/adapters/testingTime.js.map +1 -0
- package/dist/server/client.d.ts +3 -0
- package/dist/server/client.d.ts.map +1 -1
- package/dist/server/clientOptions.d.ts +0 -1
- package/dist/server/clientOptions.d.ts.map +1 -1
- package/dist/server/definition.d.ts +12 -11
- package/dist/server/definition.d.ts.map +1 -1
- package/dist/server/definition.js +2 -1
- package/dist/server/definition.js.map +1 -1
- package/dist/server/engineClient.d.ts +0 -5
- package/dist/server/engineClient.d.ts.map +1 -1
- package/dist/server/enqueueOptions.d.ts +6 -0
- package/dist/server/enqueueOptions.d.ts.map +1 -1
- package/dist/server/error.d.ts +1 -1
- package/dist/server/error.d.ts.map +1 -1
- package/dist/server/error.js.map +1 -1
- package/dist/server/inspection.d.ts +102 -0
- package/dist/server/inspection.d.ts.map +1 -0
- package/dist/server/inspection.js +30 -0
- package/dist/server/inspection.js.map +1 -0
- package/dist/server/internal/adapters/deferralChanges.d.ts +3 -0
- package/dist/server/internal/adapters/deferralChanges.d.ts.map +1 -0
- package/dist/server/internal/adapters/deferralChanges.js +2 -0
- package/dist/server/internal/adapters/deferralChanges.js.map +1 -0
- package/dist/server/internal/adapters/testingFetches.d.ts +2 -2
- package/dist/server/internal/adapters/testingFetches.d.ts.map +1 -1
- package/dist/server/internal/adapters/testingFetches.js.map +1 -1
- package/dist/server/internal/deferral.d.ts +0 -2
- package/dist/server/internal/deferral.d.ts.map +1 -1
- package/dist/server/internal/deferral.js +0 -1
- package/dist/server/internal/deferral.js.map +1 -1
- package/dist/server/internal/engine.d.ts +0 -5
- package/dist/server/internal/engine.d.ts.map +1 -1
- package/dist/server/internal/engine.js.map +1 -1
- package/dist/server/internal/enqueueFor.d.ts.map +1 -1
- package/dist/server/internal/enqueueFor.js +11 -1
- package/dist/server/internal/enqueueFor.js.map +1 -1
- package/dist/server/internal/jobStorePlans.d.ts.map +1 -1
- package/dist/server/internal/jobStorePlans.js +2 -1
- package/dist/server/internal/jobStorePlans.js.map +1 -1
- package/dist/server/internal/makeService.d.ts.map +1 -1
- package/dist/server/internal/makeService.js +7 -6
- package/dist/server/internal/makeService.js.map +1 -1
- package/dist/server/internal/register.d.ts.map +1 -1
- package/dist/server/internal/register.js +0 -4
- package/dist/server/internal/register.js.map +1 -1
- package/dist/server/internal/testingIdle.d.ts +4 -3
- package/dist/server/internal/testingIdle.d.ts.map +1 -1
- package/dist/server/internal/testingIdle.js +7 -26
- package/dist/server/internal/testingIdle.js.map +1 -1
- package/dist/server/internal/testingOperation.d.ts +5 -0
- package/dist/server/internal/testingOperation.d.ts.map +1 -0
- package/dist/server/internal/testingOperation.js +12 -0
- package/dist/server/internal/testingOperation.js.map +1 -0
- package/dist/server/internal/testingSchedules.d.ts +8 -5
- package/dist/server/internal/testingSchedules.d.ts.map +1 -1
- package/dist/server/internal/testingSchedules.js +14 -9
- package/dist/server/internal/testingSchedules.js.map +1 -1
- package/dist/server/internal/testingWaits.d.ts +7 -4
- package/dist/server/internal/testingWaits.d.ts.map +1 -1
- package/dist/server/internal/testingWaits.js +7 -10
- package/dist/server/internal/testingWaits.js.map +1 -1
- package/dist/server/schema.d.ts.map +1 -1
- package/dist/server/schema.js +5 -0
- package/dist/server/schema.js.map +1 -1
- package/dist/server/service.d.ts +4 -4
- package/dist/server/service.d.ts.map +1 -1
- package/dist/server/service.js +1 -0
- package/dist/server/service.js.map +1 -1
- package/dist/server/testing.d.ts +63 -25
- package/dist/server/testing.d.ts.map +1 -1
- package/dist/server/testing.js.map +1 -1
- package/package.json +7 -7
- package/src/server/adapters/inspection.ts +31 -0
- package/src/server/adapters/inspectionChanges.ts +31 -0
- package/src/server/{internal/testingDeferrals.ts → adapters/inspectionDeferrals.ts} +10 -12
- package/src/server/adapters/inspectionJobs.ts +28 -0
- package/src/server/adapters/inspectionOperation.ts +6 -0
- package/src/server/adapters/inspectionPlan.ts +21 -0
- package/src/server/adapters/inspectionReads.ts +55 -0
- package/src/server/{internal/testingSnapshot.ts → adapters/inspectionSnapshot.ts} +15 -17
- package/src/server/adapters/jobEngine.ts +0 -4
- package/src/server/adapters/payloadIdentity.ts +15 -0
- package/src/server/{internal/testingSignal.ts → adapters/queueSignal.ts} +1 -1
- package/src/server/adapters/settleDeferral.ts +8 -2
- package/src/server/adapters/testingClient.ts +11 -30
- package/src/server/adapters/testingController.ts +49 -21
- package/src/server/adapters/testingDueNow.ts +1 -1
- package/src/server/adapters/testingEngine.ts +0 -13
- package/src/server/adapters/testingInspectionClient.ts +70 -0
- package/src/server/adapters/testingTime.ts +25 -0
- package/src/server/client.ts +3 -0
- package/src/server/clientOptions.ts +0 -1
- package/src/server/definition.ts +18 -12
- package/src/server/engineClient.ts +0 -2
- package/src/server/enqueueOptions.ts +5 -0
- package/src/server/error.ts +1 -0
- package/src/server/inspection.ts +50 -0
- package/src/server/internal/adapters/deferralChanges.ts +3 -0
- package/src/server/internal/adapters/testingFetches.ts +2 -2
- package/src/server/internal/deferral.ts +0 -2
- package/src/server/internal/engine.ts +0 -6
- package/src/server/internal/enqueueFor.ts +14 -1
- package/src/server/internal/jobStorePlans.ts +2 -1
- package/src/server/internal/makeService.ts +7 -6
- package/src/server/internal/register.ts +0 -4
- package/src/server/internal/testingIdle.ts +10 -31
- package/src/server/internal/testingOperation.ts +18 -0
- package/src/server/internal/testingSchedules.ts +28 -16
- package/src/server/internal/testingWaits.ts +11 -16
- package/src/server/schema.ts +5 -0
- package/src/server/service.ts +5 -2
- package/src/server/testing.ts +3 -12
- package/dist/server/adapters/observeTestingSettlements.d.ts +0 -6
- package/dist/server/adapters/observeTestingSettlements.d.ts.map +0 -1
- package/dist/server/adapters/observeTestingSettlements.js +0 -35
- package/dist/server/adapters/observeTestingSettlements.js.map +0 -1
- package/dist/server/internal/testingDeferrals.d.ts +0 -10
- package/dist/server/internal/testingDeferrals.d.ts.map +0 -1
- package/dist/server/internal/testingDeferrals.js +0 -15
- package/dist/server/internal/testingDeferrals.js.map +0 -1
- package/dist/server/internal/testingReadout.d.ts +0 -10
- package/dist/server/internal/testingReadout.d.ts.map +0 -1
- package/dist/server/internal/testingReadout.js +0 -13
- package/dist/server/internal/testingReadout.js.map +0 -1
- package/dist/server/internal/testingRegistrations.d.ts +0 -4
- package/dist/server/internal/testingRegistrations.d.ts.map +0 -1
- package/dist/server/internal/testingRegistrations.js +0 -8
- package/dist/server/internal/testingRegistrations.js.map +0 -1
- package/dist/server/internal/testingSignal.d.ts.map +0 -1
- package/dist/server/internal/testingSignal.js.map +0 -1
- package/dist/server/internal/testingSnapshot.d.ts +0 -6
- package/dist/server/internal/testingSnapshot.d.ts.map +0 -1
- package/dist/server/internal/testingSnapshot.js.map +0 -1
- package/src/server/adapters/observeTestingSettlements.ts +0 -36
- package/src/server/internal/testingReadout.ts +0 -25
- package/src/server/internal/testingRegistrations.ts +0 -10
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ClientDatabase } from "#server/ClientDatabase.ts";
|
|
2
|
+
import type { QueueDefinition } from "#server/definition.ts";
|
|
2
3
|
import type { RetryOptions } from "#server/queueOptions.ts";
|
|
3
4
|
|
|
4
5
|
export interface EnqueueOptions extends RetryOptions {
|
|
@@ -13,6 +14,10 @@ export interface EnqueueOptions extends RetryOptions {
|
|
|
13
14
|
readonly startAfter?: number | string | Date;
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
export type QueueEnqueueOptions<TQueue extends QueueDefinition> = Omit<EnqueueOptions, "id" | "singletonKey"> &
|
|
18
|
+
(TQueue["id"] extends undefined ? Pick<EnqueueOptions, "id"> : { readonly id?: never }) &
|
|
19
|
+
(TQueue["key"] extends undefined ? Pick<EnqueueOptions, "singletonKey"> : { readonly singletonKey?: never });
|
|
20
|
+
|
|
16
21
|
export interface ScheduleOptions extends EnqueueOptions {
|
|
17
22
|
readonly key?: string;
|
|
18
23
|
readonly missed?: "skip" | "once";
|
package/src/server/error.ts
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type DateTime, Effect } from "effect";
|
|
2
|
+
import { defineService } from "@shivaedev/service/defineService.ts";
|
|
3
|
+
import { genericMethod } from "@shivaedev/service/genericMethod.ts";
|
|
4
|
+
import { inspection } from "#server/adapters/inspection.ts";
|
|
5
|
+
import type { inspectionChanges } from "#server/adapters/inspectionChanges.ts";
|
|
6
|
+
import type { inspectionReads } from "#server/adapters/inspectionReads.ts";
|
|
7
|
+
import type { JobPayloadSchema, QueueDefinition } from "#server/definition.ts";
|
|
8
|
+
import { PgBoss } from "#server/PgBoss.ts";
|
|
9
|
+
import type { PgBossService } from "#server/service.ts";
|
|
10
|
+
|
|
11
|
+
export type SnapshotQueue = Pick<QueueDefinition<string, JobPayloadSchema>, "name" | "schema">;
|
|
12
|
+
|
|
13
|
+
export interface UnfinishedJob<TQueue extends SnapshotQueue> {
|
|
14
|
+
readonly data: TQueue["schema"]["Type"];
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly queue: TQueue["name"];
|
|
17
|
+
readonly startAfter: DateTime.Utc;
|
|
18
|
+
readonly state: "active" | "created" | "deferred" | "failed" | "retry";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const PgBossInspection = defineService({
|
|
22
|
+
id: "@shivaedev/jobs/PgBossInspection",
|
|
23
|
+
initialize: Effect.gen(function* () {
|
|
24
|
+
const acquired = yield* PgBoss;
|
|
25
|
+
return yield* inspection(acquired.client, acquired.schema);
|
|
26
|
+
}),
|
|
27
|
+
methods: (service) => ({
|
|
28
|
+
busy: service.busy,
|
|
29
|
+
changes: service.changes,
|
|
30
|
+
counts: service.counts,
|
|
31
|
+
deadLetteredJobs: genericMethod(service.deadLetteredJobs),
|
|
32
|
+
deferred: service.deferred,
|
|
33
|
+
failedJobs: genericMethod(service.failedJobs),
|
|
34
|
+
getJob: genericMethod(service.getJob),
|
|
35
|
+
health: service.health,
|
|
36
|
+
jobs: genericMethod(service.jobs),
|
|
37
|
+
queue: service.queue,
|
|
38
|
+
schedules: service.schedules,
|
|
39
|
+
schemaVersion: service.schemaVersion,
|
|
40
|
+
snapshot: genericMethod(service.snapshot),
|
|
41
|
+
storedJobs: service.storedJobs,
|
|
42
|
+
}),
|
|
43
|
+
requires: [PgBoss] as const,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export type PgBossInspectionService = ReturnType<typeof inspectionReads> &
|
|
47
|
+
Pick<PgBossService, "counts" | "deadLetteredJobs" | "failedJobs" | "getJob"> & {
|
|
48
|
+
readonly health: (queues: readonly { readonly name: string }[]) => ReturnType<PgBossService["health"]>;
|
|
49
|
+
readonly changes: (queue?: { readonly name: string }) => ReturnType<typeof inspectionChanges>;
|
|
50
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ClientDatabase } from "#server/ClientDatabase.ts";
|
|
2
2
|
|
|
3
3
|
// pg-boss offers no hook for a worker fetch that finds nothing, so the controller recognizes its claim statement on the client's database.
|
|
4
4
|
const claim = /UPDATE\s+\S+\s+j\s+SET\s+state\s*=\s*'active'/u;
|
|
@@ -9,7 +9,7 @@ export interface TestingFetches {
|
|
|
9
9
|
readonly passedSince: (queue: string, begun: number) => number;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export function testingFetches(db:
|
|
12
|
+
export function testingFetches(db: ClientDatabase, changed: () => void): TestingFetches {
|
|
13
13
|
const begun = new Map<string, number>();
|
|
14
14
|
const passed = new Map<string, number[]>();
|
|
15
15
|
const executeSql = db.executeSql.bind(db);
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
-
import type { PgBossClient } from "#server/client.ts";
|
|
3
2
|
import type { WorkerJob } from "#server/job.ts";
|
|
4
3
|
|
|
5
4
|
export const deferredAttempt = Symbol("deferredAttempt");
|
|
6
|
-
export const deferralObservers = new WeakMap<PgBossClient, () => void>();
|
|
7
5
|
export const STATELY_DEFERRAL_POLICY = "effect-stately-deferred";
|
|
8
6
|
|
|
9
7
|
export const Deferral = Schema.Struct({
|
|
@@ -27,15 +27,9 @@ export class JobEngine extends Context.Service<
|
|
|
27
27
|
}
|
|
28
28
|
>()("@shivaedev/jobs/JobEngine") {}
|
|
29
29
|
|
|
30
|
-
export interface TestingSettlements {
|
|
31
|
-
readonly close: Effect.Effect<void>;
|
|
32
|
-
readonly watch: (name: string) => Effect.Effect<void, PgBossTestingError>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
30
|
export class TestingEngine extends Context.Service<
|
|
36
31
|
TestingEngine,
|
|
37
32
|
{
|
|
38
33
|
readonly expireAttempt: (job: JobAttempt, cause?: "expiry" | "heartbeat") => Effect.Effect<void, PgBossTestingError>;
|
|
39
|
-
readonly observeSettlements: (settled: (name: string) => void) => Effect.Effect<TestingSettlements>;
|
|
40
34
|
}
|
|
41
35
|
>()("@shivaedev/jobs/TestingEngine") {}
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
import { Effect, Option, Redacted, Schema } from "effect";
|
|
2
|
+
import { payloadJobId, payloadKey } from "#server/adapters/payloadIdentity.ts";
|
|
2
3
|
import { transactionDb } from "#server/adapters/transactionDb.ts";
|
|
3
4
|
import type { PgBossClient } from "#server/client.ts";
|
|
5
|
+
import type { QueueDefinition } from "#server/definition.ts";
|
|
6
|
+
import type { EnqueueOptions } from "#server/enqueueOptions.ts";
|
|
4
7
|
import { PgBossPayloadError, toPgBossError } from "#server/error.ts";
|
|
5
8
|
import { capturePayload } from "#server/internal/tracing.ts";
|
|
6
9
|
import type { PgBossService } from "#server/service.ts";
|
|
7
10
|
|
|
11
|
+
function identityOptions(queue: Pick<QueueDefinition, "id" | "key" | "name">, payload: object, options?: EnqueueOptions) {
|
|
12
|
+
return queue.id === undefined && queue.key === undefined
|
|
13
|
+
? options
|
|
14
|
+
: {
|
|
15
|
+
...options,
|
|
16
|
+
...(queue.id === undefined ? {} : { id: payloadJobId(queue.name, queue.id, payload) }),
|
|
17
|
+
...(queue.key === undefined ? {} : { singletonKey: payloadKey(queue.key, payload) }),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
8
21
|
export function enqueueFor(client: PgBossClient): PgBossService["enqueue"] {
|
|
9
22
|
return (queue, payload, options) =>
|
|
10
23
|
Effect.gen(function* () {
|
|
@@ -20,7 +33,7 @@ export function enqueueFor(client: PgBossClient): PgBossService["enqueue"] {
|
|
|
20
33
|
}
|
|
21
34
|
const data = yield* capturePayload(encoded);
|
|
22
35
|
const db = yield* transactionDb;
|
|
23
|
-
const sendOptions = queue
|
|
36
|
+
const sendOptions = identityOptions(queue, payload, options);
|
|
24
37
|
const send = Effect.tryPromise({
|
|
25
38
|
catch: (error) => toPgBossError("enqueue", error, queue.name),
|
|
26
39
|
try: () => client.send(queue.name, data, db === undefined ? sendOptions : { ...sendOptions, db }),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { inspectionPlan } from "#server/adapters/inspectionPlan.ts";
|
|
1
2
|
import { deadLetterResolutionPlan } from "#server/internal/deadLetterResolutionPlan.ts";
|
|
2
3
|
import { deferralStorePlan } from "#server/internal/deferralStorePlan.ts";
|
|
3
4
|
|
|
4
5
|
export function jobStorePlans(schema: string): readonly string[] {
|
|
5
|
-
return [deferralStorePlan(schema), deadLetterResolutionPlan(schema)];
|
|
6
|
+
return [deferralStorePlan(schema), deadLetterResolutionPlan(schema), inspectionPlan(schema)];
|
|
6
7
|
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
+
import { inspection } from "#server/adapters/inspection.ts";
|
|
2
3
|
import type { PgBossClient } from "#server/client.ts";
|
|
3
|
-
import { countsFor } from "#server/internal/countsFor.ts";
|
|
4
4
|
import { JobEngine } from "#server/internal/engine.ts";
|
|
5
5
|
import { enqueueFor } from "#server/internal/enqueueFor.ts";
|
|
6
|
-
import { healthFor } from "#server/internal/healthFor.ts";
|
|
7
6
|
import { jobControl } from "#server/internal/jobControl.ts";
|
|
8
|
-
import { jobListings } from "#server/internal/jobListings.ts";
|
|
9
7
|
import type { PgBossService } from "#server/service.ts";
|
|
10
8
|
|
|
11
9
|
export const makeService = Effect.fnUntraced(function* (
|
|
@@ -14,13 +12,16 @@ export const makeService = Effect.fnUntraced(function* (
|
|
|
14
12
|
schema = "pgboss",
|
|
15
13
|
): Effect.fn.Return<PgBossService, never, JobEngine> {
|
|
16
14
|
const engine = yield* JobEngine;
|
|
15
|
+
const reads = yield* inspection(client, schema);
|
|
17
16
|
return {
|
|
18
|
-
counts: (queue) =>
|
|
17
|
+
counts: (queue) => reads.counts(queue),
|
|
18
|
+
deadLetteredJobs: reads.deadLetteredJobs,
|
|
19
19
|
deleteQueue: engine.deleteQueue,
|
|
20
|
-
...(yield* jobListings),
|
|
21
20
|
enqueue: enqueueFor(client),
|
|
21
|
+
failedJobs: reads.failedJobs,
|
|
22
|
+
inspection: () => Effect.succeed(reads),
|
|
22
23
|
...(yield* jobControl),
|
|
23
|
-
health: (queues) =>
|
|
24
|
+
health: (queues) => reads.health(queues ?? names.map((name) => ({ name }))),
|
|
24
25
|
refreshQueueStats: engine.refreshQueueStats,
|
|
25
26
|
unschedule: engine.unschedule,
|
|
26
27
|
};
|
|
@@ -7,7 +7,6 @@ import type { JobPayloadSchema, JobRegistration, QueueDefinition, QueueWorker, S
|
|
|
7
7
|
import { PgBossQueueOptionsError, toPgBossError } from "#server/error.ts";
|
|
8
8
|
import { ensureQueue } from "#server/internal/ensureQueue.ts";
|
|
9
9
|
import { runQueueWorker } from "#server/internal/runQueueWorker.ts";
|
|
10
|
-
import { registerTestingQueue } from "#server/internal/testingRegistrations.ts";
|
|
11
10
|
|
|
12
11
|
function registrationDefinition(registration: JobRegistration): QueueDefinition | ScheduleDefinition {
|
|
13
12
|
if (registration._tag === "QueueDefinition") {
|
|
@@ -107,9 +106,6 @@ export const registerJobs = Effect.fnUntraced(function* <R>(
|
|
|
107
106
|
const scope = yield* Scope.fork(yield* Effect.scope, "parallel");
|
|
108
107
|
yield* Effect.try({ catch: (error) => toPgBossError("register", error), try: () => registrationNames(registrations) });
|
|
109
108
|
yield* prepareQueues(client, registrations, replaceWorkers);
|
|
110
|
-
for (const registration of registrations) {
|
|
111
|
-
registerTestingQueue(client, registrationName(registration));
|
|
112
|
-
}
|
|
113
109
|
if (!startWorkers) {
|
|
114
110
|
return;
|
|
115
111
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { EngineClient } from "#server/engineClient.ts";
|
|
1
|
+
import { Effect } from "effect";
|
|
3
2
|
import type { PgBossTestingError } from "#server/error.ts";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import type { PgBossInspectionService } from "#server/inspection.ts";
|
|
4
|
+
import { testingInspection } from "#server/internal/testingOperation.ts";
|
|
6
5
|
|
|
7
6
|
export interface TestingBatch {
|
|
7
|
+
readonly jobs: ReadonlyMap<string, number>;
|
|
8
8
|
readonly name: string;
|
|
9
9
|
settled: boolean;
|
|
10
10
|
}
|
|
@@ -14,30 +14,13 @@ export interface TestingWork {
|
|
|
14
14
|
readonly queues: Set<string>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const Busy = Schema.Struct({ busy: Schema.Boolean });
|
|
18
|
-
|
|
19
17
|
export function testingIdle(
|
|
20
|
-
|
|
21
|
-
schema: () => string,
|
|
18
|
+
inspection: () => PgBossInspectionService,
|
|
22
19
|
work: TestingWork,
|
|
23
20
|
signal: { readonly revision: Effect.Effect<number>; readonly waitForChange: (after: number) => Effect.Effect<number> },
|
|
21
|
+
wake: Effect.Effect<void> = Effect.void,
|
|
24
22
|
): Effect.Effect<void, PgBossTestingError> {
|
|
25
|
-
const busy =
|
|
26
|
-
const quoted = quotedSchema(schema());
|
|
27
|
-
const { rows } = await client()
|
|
28
|
-
.getDb()
|
|
29
|
-
.executeSql(
|
|
30
|
-
`/* jobs testing idle */ SELECT EXISTS (
|
|
31
|
-
SELECT 1 FROM ${quoted}.job
|
|
32
|
-
WHERE name = ANY($1::text[]) AND (
|
|
33
|
-
(state < 'active' AND NOT blocked AND start_after <= ${quoted}.job_now())
|
|
34
|
-
OR state = 'active'
|
|
35
|
-
)
|
|
36
|
-
) AS busy`,
|
|
37
|
-
[[...work.queues]],
|
|
38
|
-
);
|
|
39
|
-
return (await Schema.decodeUnknownPromise(Busy)(rows[0])).busy;
|
|
40
|
-
});
|
|
23
|
+
const busy = Effect.suspend(() => testingInspection("waitForIdle", inspection().busy([...work.queues].map((name) => ({ name })))));
|
|
41
24
|
return Effect.gen(function* () {
|
|
42
25
|
while (true) {
|
|
43
26
|
const revision = yield* signal.revision;
|
|
@@ -46,12 +29,8 @@ export function testingIdle(
|
|
|
46
29
|
if (work.queues.size === 0 || !(unsettled || (yield* busy))) {
|
|
47
30
|
return;
|
|
48
31
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
} else {
|
|
52
|
-
// Other clients have no local callback; PostgreSQL remains the source of idle state.
|
|
53
|
-
yield* Effect.raceFirst(signal.waitForChange(revision), Effect.sleep("50 millis"));
|
|
54
|
-
}
|
|
32
|
+
yield* wake;
|
|
33
|
+
yield* signal.waitForChange(revision);
|
|
55
34
|
}
|
|
56
|
-
})
|
|
35
|
+
});
|
|
57
36
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Effect, Redacted } from "effect";
|
|
2
|
+
import { PgBossError, PgBossTestingError } from "#server/error.ts";
|
|
3
|
+
|
|
4
|
+
export function testingOperation<A>(operation: string, run: () => Promise<A>, queue?: string) {
|
|
5
|
+
return Effect.tryPromise({
|
|
6
|
+
catch: (original) => new PgBossTestingError({ operation, original: Redacted.make(original), queue }),
|
|
7
|
+
try: run,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function testingInspection<A, E, R>(operation: string, effect: Effect.Effect<A, E | PgBossError, R>, queue?: string) {
|
|
12
|
+
return effect.pipe(
|
|
13
|
+
Effect.catchIf(
|
|
14
|
+
(error): error is PgBossError => error instanceof PgBossError,
|
|
15
|
+
(error) => Effect.fail(new PgBossTestingError({ operation, original: error.original, queue: queue ?? error.queue })),
|
|
16
|
+
),
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -1,23 +1,35 @@
|
|
|
1
|
+
import { Effect, Redacted } from "effect";
|
|
2
|
+
import type { PgBossClient } from "#server/client.ts";
|
|
1
3
|
import type { ScheduleDefinition } from "#server/definition.ts";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
+
import { PgBossTestingError } from "#server/error.ts";
|
|
5
|
+
import type { PgBossInspectionService } from "#server/inspection.ts";
|
|
6
|
+
import { testingInspection, testingOperation } from "#server/internal/testingOperation.ts";
|
|
4
7
|
|
|
5
|
-
export function testingSchedules(client: () =>
|
|
8
|
+
export function testingSchedules(client: () => PgBossClient, inspection: () => PgBossInspectionService) {
|
|
6
9
|
return {
|
|
7
10
|
schedules: () =>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
testingOperation(
|
|
11
|
-
"trigger",
|
|
12
|
-
async () => {
|
|
13
|
-
const [registered] = await client().getSchedules(schedule.name, schedule.scheduleOptions.key ?? "");
|
|
14
|
-
if (registered === undefined) {
|
|
15
|
-
throw new Error("Schedule is not registered");
|
|
16
|
-
}
|
|
17
|
-
await client().send(registered.name, registered.data, { ...registered.options, startAfter: 0 });
|
|
18
|
-
changed();
|
|
19
|
-
},
|
|
20
|
-
schedule.name,
|
|
11
|
+
Effect.suspend(() => testingInspection("schedules", inspection().schedules())).pipe(
|
|
12
|
+
Effect.map((schedules) => schedules.map(({ name, cron, timezone }) => ({ cron, name, timezone }))),
|
|
21
13
|
),
|
|
14
|
+
trigger: (schedule: Pick<ScheduleDefinition, "name" | "scheduleOptions">) =>
|
|
15
|
+
Effect.gen(function* () {
|
|
16
|
+
const [registered] = yield* testingInspection(
|
|
17
|
+
"trigger",
|
|
18
|
+
inspection().schedules(schedule.name, schedule.scheduleOptions.key ?? ""),
|
|
19
|
+
schedule.name,
|
|
20
|
+
);
|
|
21
|
+
if (registered === undefined) {
|
|
22
|
+
return yield* new PgBossTestingError({
|
|
23
|
+
operation: "trigger",
|
|
24
|
+
original: Redacted.make(new Error("Schedule is not registered")),
|
|
25
|
+
queue: schedule.name,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return yield* testingOperation(
|
|
29
|
+
"trigger",
|
|
30
|
+
() => client().send(registered.name, registered.data, { ...registered.options, startAfter: 0 }),
|
|
31
|
+
schedule.name,
|
|
32
|
+
);
|
|
33
|
+
}),
|
|
22
34
|
};
|
|
23
35
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Duration, Effect, Option, Redacted, type Schema } from "effect";
|
|
2
2
|
import type { JobPayloadSchema, QueueDefinition } from "#server/definition.ts";
|
|
3
|
-
import type { EngineClient } from "#server/engineClient.ts";
|
|
4
3
|
import { type PgBossPayloadError, PgBossTestingError, PgBossWaitError } from "#server/error.ts";
|
|
4
|
+
import type { PgBossInspectionService } from "#server/inspection.ts";
|
|
5
5
|
import type { TestingFetches } from "#server/internal/adapters/testingFetches.ts";
|
|
6
|
-
import {
|
|
7
|
-
import { testingOperation } from "#server/internal/testingReadout.ts";
|
|
6
|
+
import { testingInspection } from "#server/internal/testingOperation.ts";
|
|
8
7
|
import type { Job, JobState } from "#server/job.ts";
|
|
9
8
|
import type { PgBossTestingWaitOptions } from "#server/testing.ts";
|
|
10
9
|
|
|
@@ -38,11 +37,7 @@ function waitUntil<A, E, R>(
|
|
|
38
37
|
yield* signal.waitForChange(revision);
|
|
39
38
|
}
|
|
40
39
|
});
|
|
41
|
-
return wait.pipe(
|
|
42
|
-
Effect.timeoutOrElse({ duration: within, orElse: () => Effect.fail(new PgBossWaitError({ lastSeen, waitingFor, within })) }),
|
|
43
|
-
// The budget is wall time, so a story's TestClock neither ends the wait early nor holds it open.
|
|
44
|
-
Effect.provideService(Clock.Clock, Clock.Clock.defaultValue()),
|
|
45
|
-
);
|
|
40
|
+
return wait.pipe(Effect.timeoutOrElse({ duration: within, orElse: () => Effect.fail(new PgBossWaitError({ lastSeen, waitingFor, within })) }));
|
|
46
41
|
});
|
|
47
42
|
}
|
|
48
43
|
|
|
@@ -50,7 +45,7 @@ function fetchesRefused(queue: Pick<QueueDefinition, "name">, original: Error) {
|
|
|
50
45
|
return new PgBossTestingError({ operation: "fetchesPass", original: Redacted.make(original), queue: queue.name });
|
|
51
46
|
}
|
|
52
47
|
|
|
53
|
-
export function testingWaits(
|
|
48
|
+
export function testingWaits(inspection: () => PgBossInspectionService, fetches: () => TestingFetches | undefined, signal: Signal) {
|
|
54
49
|
return {
|
|
55
50
|
fetchesPass: (queue: Pick<QueueDefinition, "name">, count: number, options?: PgBossTestingWaitOptions) =>
|
|
56
51
|
Effect.gen(function* () {
|
|
@@ -73,8 +68,8 @@ export function testingWaits(client: () => EngineClient, fetches: () => TestingF
|
|
|
73
68
|
options,
|
|
74
69
|
);
|
|
75
70
|
}),
|
|
76
|
-
untilJob: <TName extends string, TPayload extends JobPayloadSchema>(
|
|
77
|
-
queue:
|
|
71
|
+
untilJob: <TName extends string, TPayload extends JobPayloadSchema | typeof Schema.Null>(
|
|
72
|
+
queue: { readonly name: TName; readonly schema: TPayload },
|
|
78
73
|
id: string,
|
|
79
74
|
state: JobState,
|
|
80
75
|
options?: PgBossTestingWaitOptions,
|
|
@@ -82,15 +77,15 @@ export function testingWaits(client: () => EngineClient, fetches: () => TestingF
|
|
|
82
77
|
waitUntil(
|
|
83
78
|
signal,
|
|
84
79
|
`job ${id} in ${queue.name} is ${state}`,
|
|
85
|
-
|
|
86
|
-
Effect.flatMap((job): Effect.Effect<Reading<Job<TPayload["Type"]>>, PgBossPayloadError, TPayload["DecodingServices"]> => {
|
|
87
|
-
if (job ===
|
|
80
|
+
Effect.suspend(() => testingInspection("untilJob", inspection().jobs(queue, { id }), queue.name)).pipe(
|
|
81
|
+
Effect.flatMap(([job]): Effect.Effect<Reading<Job<TPayload["Type"]>>, PgBossPayloadError, TPayload["DecodingServices"]> => {
|
|
82
|
+
if (job === undefined) {
|
|
88
83
|
return Effect.succeed({ arrived: Option.none(), seen: "no such job" });
|
|
89
84
|
}
|
|
90
85
|
if (job.state !== state) {
|
|
91
86
|
return Effect.succeed({ arrived: Option.none(), seen: job.state });
|
|
92
87
|
}
|
|
93
|
-
return Effect.
|
|
88
|
+
return Effect.succeed({ arrived: Option.some(job), seen: job.state });
|
|
94
89
|
}),
|
|
95
90
|
),
|
|
96
91
|
options,
|
package/src/server/schema.ts
CHANGED
|
@@ -43,10 +43,15 @@ export function pgBossSchema(options: PgBossSchemaOptions = {}): SchemaComponent
|
|
|
43
43
|
const deferrals = sql`${sql(schema)}.${sql("effect_job_deferral")}`;
|
|
44
44
|
const cleanup = sql`${sql(schema)}.${sql("effect_job_deferral_keep_until")}`;
|
|
45
45
|
const stately = sql`${sql(schema)}.${sql("effect_stately_deferral")}()`;
|
|
46
|
+
const changed = sql`${sql(schema)}.${sql("effect_job_changed")}()`;
|
|
46
47
|
const missing = yield* sql`SELECT name FROM (VALUES
|
|
47
48
|
('dead-letter resolution trigger', EXISTS (
|
|
48
49
|
SELECT 1 FROM pg_trigger WHERE tgrelid = to_regclass(${job.compile()[0]}) AND tgname = 'effect_dead_letter_resolution'
|
|
49
50
|
)),
|
|
51
|
+
('effect_job_changed()', to_regprocedure(${changed.compile()[0]}) IS NOT NULL),
|
|
52
|
+
('effect_job_changed trigger', EXISTS (
|
|
53
|
+
SELECT 1 FROM pg_trigger WHERE tgrelid = to_regclass(${job.compile()[0]}) AND tgname = 'effect_job_changed'
|
|
54
|
+
)),
|
|
50
55
|
('effect_job_deferral', to_regclass(${deferrals.compile()[0]}) IS NOT NULL),
|
|
51
56
|
('effect_job_deferral_keep_until', to_regclass(${cleanup.compile()[0]}) IS NOT NULL),
|
|
52
57
|
('effect_stately_deferral()', to_regprocedure(${stately.compile()[0]}) IS NOT NULL),
|
package/src/server/service.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { clientEngine } from "#server/adapters/lifecycle.ts";
|
|
|
7
7
|
import type { PgBossClientFactory } from "#server/client.ts";
|
|
8
8
|
import type { ClientOptions, StopOptions } from "#server/clientOptions.ts";
|
|
9
9
|
import type { JobPayloadSchema, JobRegistration, QueueDefinition, RegistrationRequirements, ScheduleDefinition } from "#server/definition.ts";
|
|
10
|
-
import type {
|
|
10
|
+
import type { QueueEnqueueOptions } from "#server/enqueueOptions.ts";
|
|
11
11
|
import type {
|
|
12
12
|
PgBossClientOptionsError,
|
|
13
13
|
PgBossError,
|
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
PgBossQueueOptionsError,
|
|
18
18
|
} from "#server/error.ts";
|
|
19
19
|
import type { DeadLetteredJob, JobPage, JobPageOptions, JobsHealth, ListedJob, QueueCounts } from "#server/health.ts";
|
|
20
|
+
import type { PgBossInspectionService } from "#server/inspection.ts";
|
|
20
21
|
import { acquireClient } from "#server/internal/acquireClient.ts";
|
|
21
22
|
import { logClientError, subscribeClientErrors } from "#server/internal/clientErrors.ts";
|
|
22
23
|
import { JobEngine } from "#server/internal/engine.ts";
|
|
@@ -38,7 +39,7 @@ export interface PgBossService {
|
|
|
38
39
|
readonly enqueue: <const TName extends string, const TPayload extends JobPayloadSchema, const TQueue extends QueueDefinition<TName, TPayload>>(
|
|
39
40
|
queue: QueueDefinition<TName, TPayload> & TQueue,
|
|
40
41
|
payload: NoInfer<Schema.Schema.Type<TPayload>>,
|
|
41
|
-
options?: NoInfer<TQueue
|
|
42
|
+
options?: NoInfer<QueueEnqueueOptions<TQueue>>,
|
|
42
43
|
) => Effect.Effect<Option.Option<string>, PgBossError | PgBossPayloadError, TPayload["EncodingServices"]>;
|
|
43
44
|
readonly failedJobs: <const TName extends string, const TPayload extends JobPayloadSchema | typeof Schema.Null>(
|
|
44
45
|
queue: { readonly name: TName; readonly schema: TPayload },
|
|
@@ -49,6 +50,7 @@ export interface PgBossService {
|
|
|
49
50
|
id: string,
|
|
50
51
|
) => Effect.Effect<Option.Option<Job<unknown>>, PgBossError | PgBossPayloadError, TPayload["DecodingServices"]>;
|
|
51
52
|
readonly health: (queues?: readonly Pick<QueueDefinition, "name">[]) => Effect.Effect<JobsHealth, PgBossError>;
|
|
53
|
+
readonly inspection: () => Effect.Effect<PgBossInspectionService>;
|
|
52
54
|
readonly refreshQueueStats: (queue?: Pick<QueueDefinition, "name">) => Effect.Effect<void, PgBossError>;
|
|
53
55
|
readonly retry: (queue: Pick<QueueDefinition, "name">, id: string) => Effect.Effect<void, PgBossError>;
|
|
54
56
|
readonly unschedule: (schedule: Pick<ScheduleDefinition, "name" | "scheduleOptions">) => Effect.Effect<void, PgBossError | PgBossNotFoundError>;
|
|
@@ -117,6 +119,7 @@ export function makePgBoss<const TIdentifier extends string>(identifier: TIdenti
|
|
|
117
119
|
failedJobs: genericMethod(service.failedJobs),
|
|
118
120
|
getJob: genericMethod(service.getJob),
|
|
119
121
|
health: service.health,
|
|
122
|
+
inspection: service.inspection,
|
|
120
123
|
refreshQueueStats: service.refreshQueueStats,
|
|
121
124
|
retry: service.retry,
|
|
122
125
|
unschedule: service.unschedule,
|
package/src/server/testing.ts
CHANGED
|
@@ -1,21 +1,11 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Duration, Effect, type Tracer } from "effect";
|
|
2
|
+
import type { TestClock } from "effect/testing";
|
|
2
3
|
import { testingController } from "#server/adapters/testingController.ts";
|
|
3
|
-
import type { JobPayloadSchema, QueueDefinition } from "#server/definition.ts";
|
|
4
4
|
|
|
5
5
|
export function makePgBossTesting(options: PgBossTestingOptions = {}) {
|
|
6
6
|
return testingController(options);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export type SnapshotQueue = Pick<QueueDefinition<string, JobPayloadSchema>, "name" | "schema">;
|
|
10
|
-
|
|
11
|
-
export interface UnfinishedJob<TQueue extends SnapshotQueue> {
|
|
12
|
-
readonly data: TQueue["schema"]["Type"];
|
|
13
|
-
readonly id: string;
|
|
14
|
-
readonly queue: TQueue["name"];
|
|
15
|
-
readonly startAfter: DateTime.Utc;
|
|
16
|
-
readonly state: "active" | "created" | "deferred" | "failed" | "retry";
|
|
17
|
-
}
|
|
18
|
-
|
|
19
9
|
export interface PgBossTestingWaitOptions {
|
|
20
10
|
readonly within?: Duration.Input;
|
|
21
11
|
}
|
|
@@ -23,6 +13,7 @@ export interface PgBossTestingWaitOptions {
|
|
|
23
13
|
export const testRetryPolicy = Object.freeze({ retryBackoff: false, retryDelay: 0 });
|
|
24
14
|
|
|
25
15
|
export interface PgBossTestingOptions {
|
|
16
|
+
readonly clock?: TestClock.TestClock;
|
|
26
17
|
readonly retryPolicy?: typeof testRetryPolicy;
|
|
27
18
|
}
|
|
28
19
|
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { EngineClient } from "#server/engineClient.ts";
|
|
2
|
-
export declare function observeTestingSettlements(client: EngineClient, settled: (name: string) => void): {
|
|
3
|
-
close(): void;
|
|
4
|
-
watch(name: string): void;
|
|
5
|
-
};
|
|
6
|
-
//# sourceMappingURL=observeTestingSettlements.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"observeTestingSettlements.d.ts","sourceRoot":"","sources":["../../../src/server/adapters/observeTestingSettlements.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;IAG7F,KAAK;IAML,KAAK,OAAO,MAAM;EAwBnB"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export function observeTestingSettlements(client, settled) {
|
|
2
|
-
const observers = new Map();
|
|
3
|
-
return {
|
|
4
|
-
close() {
|
|
5
|
-
for (const close of observers.values()) {
|
|
6
|
-
close();
|
|
7
|
-
}
|
|
8
|
-
observers.clear();
|
|
9
|
-
},
|
|
10
|
-
watch(name) {
|
|
11
|
-
if (observers.has(name)) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
const spy = client.getSpy(name);
|
|
15
|
-
let open = true;
|
|
16
|
-
async function observe() {
|
|
17
|
-
while (true) {
|
|
18
|
-
await Promise.race([spy.waitForJob(() => true, "completed"), spy.waitForJob(() => true, "failed")]);
|
|
19
|
-
if (!open) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
// This controller owns the spy; clear history and the losing wait before rearming both outcomes.
|
|
23
|
-
spy.clear();
|
|
24
|
-
settled(name);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
observers.set(name, () => {
|
|
28
|
-
open = false;
|
|
29
|
-
spy.clear();
|
|
30
|
-
});
|
|
31
|
-
void observe().catch((error) => client.emit("error", error instanceof Error ? error : new Error(String(error))));
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=observeTestingSettlements.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"observeTestingSettlements.js","sourceRoot":"","sources":["../../../src/server/adapters/observeTestingSettlements.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,yBAAyB,CAAC,MAAoB,EAAE,OAA+B;IAC9F,MAAM,SAAS,GAAG,IAAI,GAAG,EAAsB,CAAC;IAChD,OAAO;QACN,KAAK;YACJ,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;gBACxC,KAAK,EAAE,CAAC;YACT,CAAC;YACD,SAAS,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;QACD,KAAK,CAAC,IAAY;YACjB,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzB,OAAO;YACR,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,IAAI,GAAG,IAAI,CAAC;YAChB,KAAK,UAAU,OAAO;gBACrB,OAAO,IAAI,EAAE,CAAC;oBACb,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;oBACpG,IAAI,CAAC,IAAI,EAAE,CAAC;wBACX,OAAO;oBACR,CAAC;oBACD,iGAAiG;oBACjG,GAAG,CAAC,KAAK,EAAE,CAAC;oBACZ,OAAO,CAAC,IAAI,CAAC,CAAC;gBACf,CAAC;YACF,CAAC;YACD,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE;gBACxB,IAAI,GAAG,KAAK,CAAC;gBACb,GAAG,CAAC,KAAK,EAAE,CAAC;YACb,CAAC,CAAC,CAAC;YACH,KAAK,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3H,CAAC;KACD,CAAC;AACH,CAAC"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { DateTime } from "effect";
|
|
2
|
-
import type { QueueDefinition } from "#server/definition.ts";
|
|
3
|
-
import type { EngineClient } from "#server/engineClient.ts";
|
|
4
|
-
export declare function testingDeferrals(client: () => EngineClient): {
|
|
5
|
-
deferred: (queue: Pick<QueueDefinition, "name">) => import("effect/Effect").Effect<{
|
|
6
|
-
at: DateTime.Utc;
|
|
7
|
-
reason: string;
|
|
8
|
-
}[], import("../error.ts").PgBossTestingError, never>;
|
|
9
|
-
};
|
|
10
|
-
//# sourceMappingURL=testingDeferrals.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"testingDeferrals.d.ts","sourceRoot":"","sources":["../../../src/server/internal/testingDeferrals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAI5D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,YAAY;IAEzD,QAAQ,UAAU,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC;;;;EAahD"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { DateTime } from "effect";
|
|
2
|
-
import { deferralOf } from "#server/internal/deferral.ts";
|
|
3
|
-
import { testingOperation } from "#server/internal/testingReadout.ts";
|
|
4
|
-
export function testingDeferrals(client) {
|
|
5
|
-
return {
|
|
6
|
-
deferred: (queue) => testingOperation("deferred", async () => {
|
|
7
|
-
const jobs = await client().findJobs(queue.name);
|
|
8
|
-
return jobs.flatMap((job) => {
|
|
9
|
-
const deferral = job.state === "retry" && job.startedOn === null ? deferralOf(job) : undefined;
|
|
10
|
-
return deferral === undefined ? [] : [{ at: DateTime.makeUnsafe(job.startAfter), reason: deferral.reason }];
|
|
11
|
-
});
|
|
12
|
-
}, queue.name),
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=testingDeferrals.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"testingDeferrals.js","sourceRoot":"","sources":["../../../src/server/internal/testingDeferrals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGlC,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,MAAM,UAAU,gBAAgB,CAAC,MAA0B;IAC1D,OAAO;QACN,QAAQ,EAAE,CAAC,KAAoC,EAAE,EAAE,CAClD,gBAAgB,CACf,UAAU,EACV,KAAK,IAAI,EAAE;YACV,MAAM,IAAI,GAAG,MAAM,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjD,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;gBAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,KAAK,OAAO,IAAI,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC/F,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7G,CAAC,CAAC,CAAC;QACJ,CAAC,EACD,KAAK,CAAC,IAAI,CACV;KACF,CAAC;AACH,CAAC"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Effect } from "effect";
|
|
2
|
-
import type { JobReadOptions } from "#server/client.ts";
|
|
3
|
-
import type { JobPayloadSchema, QueueDefinition } from "#server/definition.ts";
|
|
4
|
-
import type { EngineClient } from "#server/engineClient.ts";
|
|
5
|
-
import type { PgBossPayloadError } from "#server/error.ts";
|
|
6
|
-
import { PgBossTestingError } from "#server/error.ts";
|
|
7
|
-
import type { Job } from "#server/job.ts";
|
|
8
|
-
export declare function testingOperation<A>(operation: string, run: () => Promise<A>, queue?: string): Effect.Effect<A, PgBossTestingError, never>;
|
|
9
|
-
export declare function testingReadout(client: () => EngineClient): <TName extends string, TPayload extends JobPayloadSchema>(queue: QueueDefinition<TName, TPayload>, options?: JobReadOptions) => Effect.Effect<Job<TPayload["Type"]>[], PgBossTestingError | PgBossPayloadError, TPayload["DecodingServices"]>;
|
|
10
|
-
//# sourceMappingURL=testingReadout.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"testingReadout.d.ts","sourceRoot":"","sources":["../../../src/server/internal/testingReadout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAY,MAAM,QAAQ,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAE1C,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,+CAK3F;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,YAAY,IAChD,KAAK,SAAS,MAAM,EAAE,QAAQ,SAAS,gBAAgB,SACvD,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,YAC7B,cAAc,KACtB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAIhH"}
|