nuxt-cf-jobs 0.12.2 → 0.12.4
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/dist/module.json +1 -1
- package/dist/runtime/server/d1.d.ts +8 -1
- package/dist/runtime/server/d1.js +2 -2
- package/dist/runtime/server/metrics.d.ts +9 -1
- package/dist/runtime/server/metrics.js +4 -3
- package/dist/runtime/server/outbox.d.ts +11 -2
- package/dist/runtime/server/outbox.js +1 -1
- package/dist/runtime/server/runtime.d.ts +6 -3
- package/dist/runtime/server/runtime.js +2 -2
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -87,10 +87,17 @@ export interface D1DurableJobRepositoryOptions<Queue extends string = string> {
|
|
|
87
87
|
durationMs: number | null;
|
|
88
88
|
result?: unknown;
|
|
89
89
|
}) => void;
|
|
90
|
-
/**
|
|
90
|
+
/**
|
|
91
|
+
* Fire-and-forget hook invoked after `failJob` writes succeed. Errors are swallowed.
|
|
92
|
+
*
|
|
93
|
+
* `error` is the HEADLINE (`"TypeError: <message>"`) — safe for issue titles,
|
|
94
|
+
* realtime payloads and Analytics Engine blobs. `cause` is the ORIGINAL thrown
|
|
95
|
+
* value: report it as-is (`captureException(cause)`) to keep the native stack.
|
|
96
|
+
*/
|
|
91
97
|
onJobFailed?: (input: {
|
|
92
98
|
job: D1DurableJobRecord<Queue>;
|
|
93
99
|
error: string;
|
|
100
|
+
cause?: unknown;
|
|
94
101
|
}) => void;
|
|
95
102
|
/** Fire-and-forget hook invoked after `releaseJob` writes succeed. Errors are swallowed. */
|
|
96
103
|
onJobReleased?: (input: {
|
|
@@ -149,7 +149,7 @@ export function createD1DurableJobRepository(db, opts = {}) {
|
|
|
149
149
|
assertOwnedMutation(resultUpdate, job.id);
|
|
150
150
|
fireHook(() => opts.onJobCompleted?.({ job, durationMs, result }));
|
|
151
151
|
},
|
|
152
|
-
async failJob(job, error) {
|
|
152
|
+
async failJob(job, error, failOpts) {
|
|
153
153
|
const insert = await db.prepare(`
|
|
154
154
|
INSERT OR REPLACE INTO ${failedJobsTable} (
|
|
155
155
|
id, queue, job_type, batch_id, user_id, site_id, partner_id, trace_id, unique_key, payload,
|
|
@@ -180,7 +180,7 @@ export function createD1DurableJobRepository(db, opts = {}) {
|
|
|
180
180
|
AND failed_at IS NULL
|
|
181
181
|
`).bind(job.id, job.reserved_at, job.attempts).run();
|
|
182
182
|
assertOwnedMutation(deleted, job.id);
|
|
183
|
-
fireHook(() => opts.onJobFailed?.({ job, error: headlineOf(error) }));
|
|
183
|
+
fireHook(() => opts.onJobFailed?.({ job, error: headlineOf(error), cause: failOpts?.cause }));
|
|
184
184
|
},
|
|
185
185
|
async releaseJob(job, releaseOpts) {
|
|
186
186
|
const result = await db.prepare(`
|
|
@@ -16,8 +16,16 @@ export interface JobMetricsEvent {
|
|
|
16
16
|
batchId: string | null;
|
|
17
17
|
siteId: string | null;
|
|
18
18
|
userId: number | null;
|
|
19
|
-
/** Present for `failed` / `released` (the release reason). */
|
|
19
|
+
/** Present for `failed` / `released` (the release reason). Single-line headline. */
|
|
20
20
|
error?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Present for `failed`: the ORIGINAL thrown value, not a rendering of it. An
|
|
23
|
+
* error-tracker sink should `captureException(cause)` so it groups on the real
|
|
24
|
+
* throw site and keeps the native stack + `cause` chain, rather than rebuilding a
|
|
25
|
+
* synthetic `new Error(error)`. Dimension-oriented sinks (Analytics Engine) must
|
|
26
|
+
* ignore it — it is an arbitrary object, not a blob.
|
|
27
|
+
*/
|
|
28
|
+
cause?: unknown;
|
|
21
29
|
/** Optional completion result supplied by the consumer. */
|
|
22
30
|
result?: unknown;
|
|
23
31
|
rowsFetched?: number;
|
|
@@ -21,7 +21,8 @@ function toEvent(job, status, extra) {
|
|
|
21
21
|
batchId: job.batch_id,
|
|
22
22
|
siteId: job.site_id,
|
|
23
23
|
userId: job.user_id,
|
|
24
|
-
error: extra.error
|
|
24
|
+
error: extra.error,
|
|
25
|
+
...extra.cause !== void 0 ? { cause: extra.cause } : {}
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
export function metricsSinkToRepoHooks(sink) {
|
|
@@ -32,8 +33,8 @@ export function metricsSinkToRepoHooks(sink) {
|
|
|
32
33
|
event.result = result;
|
|
33
34
|
return sink.record(event);
|
|
34
35
|
},
|
|
35
|
-
onJobFailed({ job, error }) {
|
|
36
|
-
return sink.record(toEvent(job, "failed", { durationMs: job.duration_ms ?? null, error }));
|
|
36
|
+
onJobFailed({ job, error, cause }) {
|
|
37
|
+
return sink.record(toEvent(job, "failed", { durationMs: job.duration_ms ?? null, error, cause }));
|
|
37
38
|
},
|
|
38
39
|
onJobReleased({ job, opts }) {
|
|
39
40
|
return sink.record(toEvent(job, "released", { error: opts?.error }));
|
|
@@ -97,11 +97,20 @@ export interface ReleaseDurableJobOptions {
|
|
|
97
97
|
availableAt?: number;
|
|
98
98
|
error?: string;
|
|
99
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Well-known `failJob` options, always available regardless of a repository's own
|
|
102
|
+
* `FailOptions` (`unknown & T` is `T`). `cause` is the ORIGINAL thrown value — the
|
|
103
|
+
* `error` string is a rendering for the `failed_jobs` row, but a telemetry hook
|
|
104
|
+
* wants the instance so it can report the real stack instead of rebuilding one.
|
|
105
|
+
*/
|
|
106
|
+
export interface FailDurableJobOptions {
|
|
107
|
+
cause?: unknown;
|
|
108
|
+
}
|
|
100
109
|
export interface DurableJobLifecycle<Job, CompleteResult = void, FailOptions = unknown, ReleaseResult = void> {
|
|
101
110
|
claimJob: (id: string) => Promise<Job | null>;
|
|
102
111
|
resolveClaimMiss?: (id: string) => Promise<DurableJobClaimMiss>;
|
|
103
112
|
completeJob: (job: Job, result?: unknown) => Promise<CompleteResult>;
|
|
104
|
-
failJob: (job: Job, error: string, opts?: FailOptions) => Promise<void>;
|
|
113
|
+
failJob: (job: Job, error: string, opts?: FailOptions & FailDurableJobOptions) => Promise<void>;
|
|
105
114
|
releaseJob?: (job: Job, opts?: ReleaseDurableJobOptions) => Promise<ReleaseResult>;
|
|
106
115
|
}
|
|
107
116
|
export interface QueuePublisher<Queue extends string = string, Message extends QueueJobMessage<Queue> = QueueJobMessage<Queue>> {
|
|
@@ -228,7 +237,7 @@ export declare function createQueuePublisher<Env extends Record<string, unknown>
|
|
|
228
237
|
}): QueuePublisher<Queue, Message>;
|
|
229
238
|
export declare function claimDurableJob<Job>(lifecycle: Pick<DurableJobLifecycle<Job>, 'claimJob' | 'resolveClaimMiss'>, id: string): Promise<DurableJobClaimResult<Job>>;
|
|
230
239
|
export declare function completeDurableJob<Job, CompleteResult>(lifecycle: Pick<DurableJobLifecycle<Job, CompleteResult>, 'completeJob'>, job: Job, result?: unknown): Promise<CompleteResult>;
|
|
231
|
-
export declare function failDurableJob<Job, FailOptions>(lifecycle: Pick<DurableJobLifecycle<Job, unknown, FailOptions>, 'failJob'>, job: Job, error: string, opts?: FailOptions): Promise<void>;
|
|
240
|
+
export declare function failDurableJob<Job, FailOptions>(lifecycle: Pick<DurableJobLifecycle<Job, unknown, FailOptions>, 'failJob'>, job: Job, error: string, opts?: FailOptions & FailDurableJobOptions): Promise<void>;
|
|
232
241
|
export declare function releaseDurableJob<Job, ReleaseResult>(lifecycle: Pick<DurableJobLifecycle<Job, unknown, unknown, ReleaseResult>, 'releaseJob'>, job: Job, opts?: ReleaseDurableJobOptions): Promise<ReleaseResult | undefined>;
|
|
233
242
|
export declare function findDispatchableDurableJobs<Queue extends string, Record extends Pick<DurableJobRecord<Queue>, 'id' | 'queue'>>(repository: Pick<DurableJobRecoveryRepository<Queue, Record>, 'findDispatchableJobs'>, query?: DurableJobRecoveryQuery): Promise<Record[]>;
|
|
234
243
|
export declare function releaseStaleReservedDurableJobs<Queue extends string, Record extends Pick<DurableJobRecord<Queue>, 'id' | 'queue'>>(repository: Pick<DurableJobRecoveryRepository<Queue, Record>, 'releaseStaleReservedJobs'>, query: DurableJobStaleRecoveryQuery): Promise<number>;
|
|
@@ -338,7 +338,7 @@ export async function runDurableJobMessage(opts) {
|
|
|
338
338
|
const permanent = opts.isPermanentFailure ? opts.isPermanentFailure({ error, storedJob, attempts: job.attempts, maxAttempts }) : typeof maxAttempts === "number" && job.attempts >= maxAttempts;
|
|
339
339
|
if (permanent) {
|
|
340
340
|
try {
|
|
341
|
-
await failDurableJob(opts.lifecycle, storedJob, describeCauseWithStack(error));
|
|
341
|
+
await failDurableJob(opts.lifecycle, storedJob, describeCauseWithStack(error), { cause: error });
|
|
342
342
|
} catch (failError) {
|
|
343
343
|
const obsolete = obsoleteDelivery(failError);
|
|
344
344
|
if (obsolete)
|
|
@@ -44,15 +44,16 @@ export interface RunLightweightMessageOptions<Env = unknown, Db = unknown, Logge
|
|
|
44
44
|
/** Mark an id as terminally handled. Retried/released messages must not be marked. */
|
|
45
45
|
markDuplicate?: (id: string | undefined) => void;
|
|
46
46
|
/**
|
|
47
|
-
* Diagnostic sink for dropped/invalid messages (no throw).
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
* Diagnostic sink for dropped/invalid messages (no throw). When the entry came from
|
|
48
|
+
* a thrown defect, `cause` is the original value (report it directly) and `stack` its
|
|
49
|
+
* rendering — so a consumer never has to reconstruct `new Error(error)`.
|
|
50
50
|
*/
|
|
51
51
|
onLog?: (event: {
|
|
52
52
|
stage: string;
|
|
53
53
|
taskName?: string;
|
|
54
54
|
error?: string;
|
|
55
55
|
stack?: string;
|
|
56
|
+
cause?: unknown;
|
|
56
57
|
}) => void;
|
|
57
58
|
}
|
|
58
59
|
export type RunLightweightMessageResult = {
|
|
@@ -84,6 +85,7 @@ export interface ConsumeQueueBatchOptions<Queue extends string, Env, Db, Logger>
|
|
|
84
85
|
jobId?: string;
|
|
85
86
|
error?: string;
|
|
86
87
|
stack?: string;
|
|
88
|
+
cause?: unknown;
|
|
87
89
|
}) => void;
|
|
88
90
|
createJobScope?: (storedJob: D1DurableJobRecord<Queue>) => DurableJobScope<D1DurableJobRecord<Queue>>;
|
|
89
91
|
isPermanentFailure?: (input: {
|
|
@@ -177,6 +179,7 @@ export interface CreateDurableJobsRuntimeOptions<Queue extends string = string,
|
|
|
177
179
|
jobId?: string;
|
|
178
180
|
error?: string;
|
|
179
181
|
stack?: string;
|
|
182
|
+
cause?: unknown;
|
|
180
183
|
}) => void;
|
|
181
184
|
/** Per-job scope: wrap dispatch (e.g. telemetry) + observe each settlement. */
|
|
182
185
|
createJobScope?: (storedJob: D1DurableJobRecord<Queue>) => DurableJobScope<D1DurableJobRecord<Queue>>;
|
|
@@ -93,7 +93,7 @@ export async function runLightweightMessage(opts) {
|
|
|
93
93
|
return { status: "completed" };
|
|
94
94
|
} catch (error) {
|
|
95
95
|
const delaySeconds = resolveJobRetryDelay(definition, message.attempts);
|
|
96
|
-
opts.onLog?.({ stage: "unexpected", taskName, error: describeCause(error), stack: describeCauseWithStack(error) });
|
|
96
|
+
opts.onLog?.({ stage: "unexpected", taskName, error: describeCause(error), stack: describeCauseWithStack(error), cause: error });
|
|
97
97
|
message.retry({ delaySeconds });
|
|
98
98
|
return { status: "errored" };
|
|
99
99
|
}
|
|
@@ -246,7 +246,7 @@ export function createDurableJobsRuntime(opts) {
|
|
|
246
246
|
});
|
|
247
247
|
}
|
|
248
248
|
} catch (error) {
|
|
249
|
-
opts.onLog?.({ stage: "onfinish-failed", taskName: c.name, jobId: batch.id, error: describeCause(error), stack: describeCauseWithStack(error) });
|
|
249
|
+
opts.onLog?.({ stage: "onfinish-failed", taskName: c.name, jobId: batch.id, error: describeCause(error), stack: describeCauseWithStack(error), cause: error });
|
|
250
250
|
}
|
|
251
251
|
});
|
|
252
252
|
const dedup = opts.dedup ? createMessageDedup(opts.dedup) : void 0;
|