@oatscenter/trellis 0.100.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -0
- package/auth/authorization/client_context.d.ts +61 -0
- package/auth/authorization/client_context.js +266 -0
- package/auth/authorization/nats_registry.d.ts +41 -0
- package/auth/authorization/nats_registry.js +283 -0
- package/auth/authorization/provider_cache.d.ts +90 -0
- package/auth/authorization/provider_cache.js +783 -0
- package/auth/authorization/refresh.d.ts +46 -0
- package/auth/authorization/refresh.js +246 -0
- package/auth/authorization/types.d.ts +207 -0
- package/auth/authorization/types.js +60 -0
- package/auth/authorization_context.d.ts +11 -0
- package/auth/authorization_context.js +10 -0
- package/auth/browser/flow_types.d.ts +84 -0
- package/auth/browser/flow_types.js +70 -0
- package/auth/browser/portal.d.ts +21 -0
- package/auth/browser/portal.js +307 -0
- package/auth/browser/storage.d.ts +26 -0
- package/auth/browser/storage.js +224 -0
- package/auth/browser.d.ts +11 -0
- package/auth/browser.js +10 -0
- package/auth/browser_recovery.d.ts +13 -0
- package/auth/browser_recovery.js +38 -0
- package/auth/device_activation.d.ts +134 -0
- package/auth/device_activation.js +376 -0
- package/auth/http_error.d.ts +12 -0
- package/auth/http_error.js +32 -0
- package/auth/keys.d.ts +5 -0
- package/auth/keys.js +63 -0
- package/auth/mod.d.ts +16 -0
- package/auth/mod.js +16 -0
- package/auth/proof.d.ts +31 -0
- package/auth/proof.js +95 -0
- package/auth/protocol_wasm/trellis_protocol_wasm.d.ts +138 -0
- package/auth/protocol_wasm/trellis_protocol_wasm.js +605 -0
- package/auth/protocol_wasm/trellis_protocol_wasm_bg.wasm +0 -0
- package/auth/protocol_wasm/trellis_protocol_wasm_bytes.d.ts +1 -0
- package/auth/protocol_wasm/trellis_protocol_wasm_bytes.js +2 -0
- package/auth/protocol_wasm.d.ts +179 -0
- package/auth/protocol_wasm.js +133 -0
- package/auth/session_auth.d.ts +30 -0
- package/auth/session_auth.js +77 -0
- package/auth/session_proof.d.ts +53 -0
- package/auth/session_proof.js +43 -0
- package/auth/time.d.ts +6 -0
- package/auth/time.js +7 -0
- package/auth/trellis_id.d.ts +1 -0
- package/auth/trellis_id.js +5 -0
- package/auth/utils.d.ts +10 -0
- package/auth/utils.js +69 -0
- package/auth.d.ts +1 -0
- package/auth.js +1 -0
- package/caller.d.ts +111 -0
- package/caller.js +85 -0
- package/client.d.ts +14 -0
- package/client.js +1 -0
- package/client_connect.d.ts +143 -0
- package/client_connect.js +1097 -0
- package/codec.d.ts +13 -0
- package/codec.js +192 -0
- package/connection.d.ts +107 -0
- package/connection.js +396 -0
- package/device/activation.d.ts +42 -0
- package/device/activation.js +319 -0
- package/device.d.ts +80 -0
- package/device.js +687 -0
- package/env.d.ts +2 -0
- package/env.js +10 -0
- package/errors/AuthError.d.ts +30 -0
- package/errors/AuthError.js +34 -0
- package/errors/KVError.d.ts +30 -0
- package/errors/KVError.js +36 -0
- package/errors/OperationLifecycleError.d.ts +110 -0
- package/errors/OperationLifecycleError.js +142 -0
- package/errors/RemoteError.d.ts +61 -0
- package/errors/RemoteError.js +72 -0
- package/errors/SchemaValidationError.d.ts +48 -0
- package/errors/SchemaValidationError.js +49 -0
- package/errors/StoreError.d.ts +21 -0
- package/errors/StoreError.js +31 -0
- package/errors/TransferError.d.ts +21 -0
- package/errors/TransferError.js +31 -0
- package/errors/TransportError.d.ts +29 -0
- package/errors/TransportError.js +33 -0
- package/errors/TrellisError.d.ts +15 -0
- package/errors/TrellisError.js +15 -0
- package/errors/ValidationError.d.ts +50 -0
- package/errors/ValidationError.js +59 -0
- package/errors/index.d.ts +254 -0
- package/errors/index.js +238 -0
- package/generated.d.ts +4 -0
- package/generated.js +3 -0
- package/generated_support.d.ts +120 -0
- package/generated_support.js +359 -0
- package/globals.d.ts +9 -0
- package/globals.js +16 -0
- package/health_transport.d.ts +18 -0
- package/health_transport.js +32 -0
- package/helpers.d.ts +11 -0
- package/helpers.js +53 -0
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/internal_sdk/generated/apis/auth/mod.d.ts +805 -0
- package/internal_sdk/generated/apis/auth/mod.js +958 -0
- package/internal_sdk/generated/apis/core/mod.d.ts +79 -0
- package/internal_sdk/generated/apis/core/mod.js +93 -0
- package/internal_sdk/generated/apis/events/mod.d.ts +224 -0
- package/internal_sdk/generated/apis/events/mod.js +313 -0
- package/internal_sdk/generated/apis/health/mod.d.ts +106 -0
- package/internal_sdk/generated/apis/health/mod.js +132 -0
- package/internal_sdk/generated/apis/index.d.ts +7 -0
- package/internal_sdk/generated/apis/index.js +8 -0
- package/internal_sdk/generated/apis/jobs/mod.d.ts +176 -0
- package/internal_sdk/generated/apis/jobs/mod.js +209 -0
- package/internal_sdk/generated/apis/state/mod.d.ts +104 -0
- package/internal_sdk/generated/apis/state/mod.js +139 -0
- package/internal_sdk/generated/index.d.ts +4 -0
- package/internal_sdk/generated/index.js +5 -0
- package/internal_sdk/generated/package.json +18 -0
- package/internal_sdk/generated/participants/cli/mod.d.ts +402 -0
- package/internal_sdk/generated/participants/cli/mod.js +460 -0
- package/internal_sdk/generated/participants/cli/types.d.ts +2 -0
- package/internal_sdk/generated/participants/cli/types.js +3 -0
- package/internal_sdk/generated/participants/console/mod.d.ts +489 -0
- package/internal_sdk/generated/participants/console/mod.js +579 -0
- package/internal_sdk/generated/participants/console/types.d.ts +2 -0
- package/internal_sdk/generated/participants/console/types.js +3 -0
- package/internal_sdk/generated/participants/eventsRuntime/mod.d.ts +64 -0
- package/internal_sdk/generated/participants/eventsRuntime/mod.js +42 -0
- package/internal_sdk/generated/participants/eventsRuntime/types.d.ts +2 -0
- package/internal_sdk/generated/participants/eventsRuntime/types.js +3 -0
- package/internal_sdk/generated/participants/healthRuntime/mod.d.ts +58 -0
- package/internal_sdk/generated/participants/healthRuntime/mod.js +36 -0
- package/internal_sdk/generated/participants/healthRuntime/types.d.ts +2 -0
- package/internal_sdk/generated/participants/healthRuntime/types.js +3 -0
- package/internal_sdk/generated/participants/index.d.ts +8 -0
- package/internal_sdk/generated/participants/index.js +9 -0
- package/internal_sdk/generated/participants/jobsRuntime/mod.d.ts +64 -0
- package/internal_sdk/generated/participants/jobsRuntime/mod.js +42 -0
- package/internal_sdk/generated/participants/jobsRuntime/types.d.ts +2 -0
- package/internal_sdk/generated/participants/jobsRuntime/types.js +3 -0
- package/internal_sdk/generated/participants/platform/mod.d.ts +164 -0
- package/internal_sdk/generated/participants/platform/mod.js +149 -0
- package/internal_sdk/generated/participants/platform/types.d.ts +7 -0
- package/internal_sdk/generated/participants/platform/types.js +5 -0
- package/internal_sdk/generated/participants/portal/mod.d.ts +131 -0
- package/internal_sdk/generated/participants/portal/mod.js +109 -0
- package/internal_sdk/generated/participants/portal/types.d.ts +2 -0
- package/internal_sdk/generated/participants/portal/types.js +3 -0
- package/internal_sdk/generated/types/_internal/p0.d.ts +13511 -0
- package/internal_sdk/generated/types/_internal/p0.js +6105 -0
- package/internal_sdk/generated/types/index.d.ts +2951 -0
- package/internal_sdk/generated/types/index.js +1477 -0
- package/jobs.d.ts +309 -0
- package/jobs.js +389 -0
- package/kv.d.ts +85 -0
- package/kv.js +330 -0
- package/operations.d.ts +189 -0
- package/operations.js +847 -0
- package/package.json +73 -0
- package/pagination.d.ts +25 -0
- package/pagination.js +117 -0
- package/participant.d.ts +6 -0
- package/participant.js +6 -0
- package/participant_runtime/api.d.ts +131 -0
- package/participant_runtime/api.js +42 -0
- package/participant_runtime/json.d.ts +16 -0
- package/participant_runtime/json.js +193 -0
- package/participant_runtime/metadata.d.ts +34 -0
- package/participant_runtime/metadata.js +4 -0
- package/participant_runtime/participant.d.ts +200 -0
- package/participant_runtime/participant.js +330 -0
- package/participant_runtime/schemas.d.ts +347 -0
- package/participant_runtime/schemas.js +211 -0
- package/participant_runtime/surface_names.d.ts +16 -0
- package/participant_runtime/surface_names.js +34 -0
- package/portable.d.ts +30 -0
- package/portable.js +14 -0
- package/provider.d.ts +69 -0
- package/provider.js +68 -0
- package/runtime_transport.d.ts +25 -0
- package/runtime_transport.js +48 -0
- package/service/mod.d.ts +14 -0
- package/service/mod.js +13 -0
- package/service/outbox_inbox.d.ts +259 -0
- package/service/outbox_inbox.js +908 -0
- package/service/runtime/bootstrap.d.ts +56 -0
- package/service/runtime/bootstrap.js +226 -0
- package/service/runtime/core.d.ts +46 -0
- package/service/runtime/core.js +1747 -0
- package/service/runtime/health.d.ts +97 -0
- package/service/runtime/health.js +153 -0
- package/service/runtime/health_schemas.d.ts +23 -0
- package/service/runtime/health_schemas.js +20 -0
- package/service/runtime/internal_jobs/active-job.d.ts +40 -0
- package/service/runtime/internal_jobs/active-job.js +91 -0
- package/service/runtime/internal_jobs/bindings.d.ts +40 -0
- package/service/runtime/internal_jobs/bindings.js +1 -0
- package/service/runtime/internal_jobs/cancellation-registry.d.ts +13 -0
- package/service/runtime/internal_jobs/cancellation-registry.js +55 -0
- package/service/runtime/internal_jobs/heartbeat.d.ts +33 -0
- package/service/runtime/internal_jobs/heartbeat.js +65 -0
- package/service/runtime/internal_jobs/job-manager.d.ts +126 -0
- package/service/runtime/internal_jobs/job-manager.js +821 -0
- package/service/runtime/internal_jobs/key-coordinator.d.ts +280 -0
- package/service/runtime/internal_jobs/key-coordinator.js +747 -0
- package/service/runtime/internal_jobs/projection.d.ts +3 -0
- package/service/runtime/internal_jobs/projection.js +42 -0
- package/service/runtime/internal_jobs/runtime-worker.d.ts +126 -0
- package/service/runtime/internal_jobs/runtime-worker.js +454 -0
- package/service/runtime/internal_jobs/types.d.ts +246 -0
- package/service/runtime/internal_jobs/types.js +163 -0
- package/service/runtime/logger.d.ts +2 -0
- package/service/runtime/logger.js +7 -0
- package/service/runtime/runtime.d.ts +16 -0
- package/service/runtime/runtime.js +1 -0
- package/service/runtime/service.d.ts +372 -0
- package/service/runtime/service.js +1896 -0
- package/service/runtime/transfer/download.d.ts +27 -0
- package/service/runtime/transfer/download.js +1 -0
- package/service/runtime/transfer/protocol.d.ts +15 -0
- package/service/runtime/transfer/protocol.js +46 -0
- package/service/runtime/transfer/queue.d.ts +18 -0
- package/service/runtime/transfer/queue.js +136 -0
- package/service/runtime/transfer/upload.d.ts +40 -0
- package/service/runtime/transfer/upload.js +27 -0
- package/service/runtime/transfer.d.ts +62 -0
- package/service/runtime/transfer.js +763 -0
- package/session.d.ts +862 -0
- package/session.js +3407 -0
- package/store.d.ts +71 -0
- package/store.js +412 -0
- package/store_entry.d.ts +20 -0
- package/store_entry.js +75 -0
- package/tasks.d.ts +10 -0
- package/tasks.js +28 -0
- package/telemetry/carrier.d.ts +8 -0
- package/telemetry/carrier.js +20 -0
- package/telemetry/core.d.ts +7 -0
- package/telemetry/core.js +14 -0
- package/telemetry/env.d.ts +2 -0
- package/telemetry/env.js +10 -0
- package/telemetry/init.d.ts +2 -0
- package/telemetry/init.js +7 -0
- package/telemetry/metrics.d.ts +81 -0
- package/telemetry/metrics.js +267 -0
- package/telemetry/mod.d.ts +13 -0
- package/telemetry/mod.js +8 -0
- package/telemetry/nats.d.ts +6 -0
- package/telemetry/nats.js +6 -0
- package/telemetry/result.d.ts +1 -0
- package/telemetry/result.js +18 -0
- package/telemetry/runtime.d.ts +1 -0
- package/telemetry/runtime.js +141 -0
- package/telemetry/trace.d.ts +4 -0
- package/telemetry/trace.js +26 -0
- package/telemetry/trellis.d.ts +1 -0
- package/telemetry/trellis.js +1 -0
- package/telemetry.d.ts +1 -0
- package/telemetry.js +1 -0
- package/transfer.d.ts +112 -0
- package/transfer.js +525 -0
- package/transfer_protocol.d.ts +1 -0
- package/transfer_protocol.js +13 -0
package/jobs.d.ts
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { AsyncResult, BaseError, Result } from "@oatscenter/result";
|
|
2
|
+
import { type StaticDecode, Type } from "typebox";
|
|
3
|
+
export declare const JobLogEntrySchema: Type.TObject<{
|
|
4
|
+
timestamp: Type.TString;
|
|
5
|
+
level: Type.TUnion<[Type.TLiteral<"info">, Type.TLiteral<"warn">, Type.TLiteral<"error">]>;
|
|
6
|
+
message: Type.TString;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const JobProgressSchema: Type.TObject<{
|
|
9
|
+
step: Type.TOptional<Type.TString>;
|
|
10
|
+
message: Type.TOptional<Type.TString>;
|
|
11
|
+
current: Type.TOptional<Type.TInteger>;
|
|
12
|
+
total: Type.TOptional<Type.TInteger>;
|
|
13
|
+
}>;
|
|
14
|
+
export type JobProgress = StaticDecode<typeof JobProgressSchema>;
|
|
15
|
+
export type JobLogEntry = StaticDecode<typeof JobLogEntrySchema>;
|
|
16
|
+
export declare const JobContextSchema: Type.TObject<{
|
|
17
|
+
requestId: Type.TString;
|
|
18
|
+
traceId: Type.TString;
|
|
19
|
+
traceparent: Type.TString;
|
|
20
|
+
tracestate: Type.TOptional<Type.TString>;
|
|
21
|
+
}>;
|
|
22
|
+
export type JobContext = StaticDecode<typeof JobContextSchema>;
|
|
23
|
+
export declare const JobTriggerSchema: Type.TObject<{
|
|
24
|
+
kind: Type.TUnion<[Type.TLiteral<"schedule">, Type.TLiteral<"operation">, Type.TLiteral<"rpc">, Type.TLiteral<"event">, Type.TLiteral<"manualReplay">, Type.TLiteral<"serviceCode">, Type.TLiteral<"parentJob">]>;
|
|
25
|
+
id: Type.TOptional<Type.TString>;
|
|
26
|
+
subject: Type.TOptional<Type.TString>;
|
|
27
|
+
operationId: Type.TOptional<Type.TString>;
|
|
28
|
+
parentJobId: Type.TOptional<Type.TString>;
|
|
29
|
+
traceId: Type.TOptional<Type.TString>;
|
|
30
|
+
requestId: Type.TOptional<Type.TString>;
|
|
31
|
+
}>;
|
|
32
|
+
export declare const JobLineageSchema: Type.TObject<{
|
|
33
|
+
parentJobId: Type.TOptional<Type.TString>;
|
|
34
|
+
rootJobId: Type.TOptional<Type.TString>;
|
|
35
|
+
operationId: Type.TOptional<Type.TString>;
|
|
36
|
+
relatedKeys: Type.TOptional<Type.TArray<Type.TString>>;
|
|
37
|
+
}>;
|
|
38
|
+
export declare const JobWaitTargetSchema: Type.TObject<{
|
|
39
|
+
kind: Type.TUnion<[Type.TLiteral<"job">, Type.TLiteral<"operation">, Type.TLiteral<"external">]>;
|
|
40
|
+
id: Type.TOptional<Type.TString>;
|
|
41
|
+
operationId: Type.TOptional<Type.TString>;
|
|
42
|
+
service: Type.TOptional<Type.TString>;
|
|
43
|
+
system: Type.TOptional<Type.TString>;
|
|
44
|
+
type: Type.TOptional<Type.TString>;
|
|
45
|
+
operation: Type.TOptional<Type.TString>;
|
|
46
|
+
key: Type.TOptional<Type.TString>;
|
|
47
|
+
label: Type.TOptional<Type.TString>;
|
|
48
|
+
}>;
|
|
49
|
+
export declare const JobWaitEdgeSchema: Type.TObject<{
|
|
50
|
+
id: Type.TString;
|
|
51
|
+
target: Type.TObject<{
|
|
52
|
+
kind: Type.TUnion<[Type.TLiteral<"job">, Type.TLiteral<"operation">, Type.TLiteral<"external">]>;
|
|
53
|
+
id: Type.TOptional<Type.TString>;
|
|
54
|
+
operationId: Type.TOptional<Type.TString>;
|
|
55
|
+
service: Type.TOptional<Type.TString>;
|
|
56
|
+
system: Type.TOptional<Type.TString>;
|
|
57
|
+
type: Type.TOptional<Type.TString>;
|
|
58
|
+
operation: Type.TOptional<Type.TString>;
|
|
59
|
+
key: Type.TOptional<Type.TString>;
|
|
60
|
+
label: Type.TOptional<Type.TString>;
|
|
61
|
+
}>;
|
|
62
|
+
startedAt: Type.TString;
|
|
63
|
+
label: Type.TOptional<Type.TString>;
|
|
64
|
+
}>;
|
|
65
|
+
export type JobTrigger = StaticDecode<typeof JobTriggerSchema>;
|
|
66
|
+
export type JobLineage = StaticDecode<typeof JobLineageSchema>;
|
|
67
|
+
export type JobWaitTarget = StaticDecode<typeof JobWaitTargetSchema>;
|
|
68
|
+
export type JobWaitEdge = StaticDecode<typeof JobWaitEdgeSchema>;
|
|
69
|
+
export type JobState = "pending" | "active" | "retry" | "completed" | "failed" | "cancelled" | "expired" | "skipped" | "stale" | "dead" | "dismissed";
|
|
70
|
+
export type JobIdentity = {
|
|
71
|
+
service: string;
|
|
72
|
+
jobType: string;
|
|
73
|
+
id: string;
|
|
74
|
+
};
|
|
75
|
+
export type JobNotEnqueuedReason = "active-limit" | "queue-depth" | "stale-blocked" | "coalesced";
|
|
76
|
+
export type JobNotEnqueuedErrorData = {
|
|
77
|
+
id: string;
|
|
78
|
+
type: "JobNotEnqueuedError";
|
|
79
|
+
message: string;
|
|
80
|
+
reason: JobNotEnqueuedReason;
|
|
81
|
+
key: string;
|
|
82
|
+
active: number;
|
|
83
|
+
queued: number;
|
|
84
|
+
limit: number;
|
|
85
|
+
existingJobId?: string;
|
|
86
|
+
context?: Record<string, unknown>;
|
|
87
|
+
traceId?: string;
|
|
88
|
+
};
|
|
89
|
+
export type RetryJobErrorData = {
|
|
90
|
+
id: string;
|
|
91
|
+
type: "RetryJobError";
|
|
92
|
+
message: string;
|
|
93
|
+
context?: Record<string, unknown>;
|
|
94
|
+
traceId?: string;
|
|
95
|
+
};
|
|
96
|
+
/** Error returned when keyed job admission does not create a new job. */
|
|
97
|
+
export declare class JobNotEnqueuedError extends BaseError<JobNotEnqueuedErrorData> {
|
|
98
|
+
readonly name: "JobNotEnqueuedError";
|
|
99
|
+
readonly reason: JobNotEnqueuedReason;
|
|
100
|
+
readonly key: string;
|
|
101
|
+
readonly active: number;
|
|
102
|
+
readonly queued: number;
|
|
103
|
+
readonly limit: number;
|
|
104
|
+
readonly existingJobId?: string;
|
|
105
|
+
constructor(options: ErrorOptions & {
|
|
106
|
+
reason: JobNotEnqueuedReason;
|
|
107
|
+
key: string;
|
|
108
|
+
active: number;
|
|
109
|
+
queued: number;
|
|
110
|
+
limit: number;
|
|
111
|
+
existingJobId?: string;
|
|
112
|
+
message?: string;
|
|
113
|
+
context?: Record<string, unknown>;
|
|
114
|
+
id?: string;
|
|
115
|
+
traceId?: string;
|
|
116
|
+
});
|
|
117
|
+
/** Serializes the admission error for transport or logging. */
|
|
118
|
+
toSerializable(): JobNotEnqueuedErrorData;
|
|
119
|
+
}
|
|
120
|
+
/** Error returned or thrown by a job handler to request JetStream redelivery. */
|
|
121
|
+
export declare class RetryJobError extends BaseError<RetryJobErrorData> {
|
|
122
|
+
readonly name: "RetryJobError";
|
|
123
|
+
constructor(options?: ErrorOptions & {
|
|
124
|
+
message?: string;
|
|
125
|
+
context?: Record<string, unknown>;
|
|
126
|
+
id?: string;
|
|
127
|
+
traceId?: string;
|
|
128
|
+
});
|
|
129
|
+
/** Serializes the retry signal for worker lifecycle logging. */
|
|
130
|
+
toSerializable(): RetryJobErrorData;
|
|
131
|
+
}
|
|
132
|
+
export type JobSubmitOutcome<TPayload, TResult, TUpdate = never> = {
|
|
133
|
+
kind: "accepted";
|
|
134
|
+
ref: JobRef<TPayload, TResult, TUpdate>;
|
|
135
|
+
key?: string;
|
|
136
|
+
} | {
|
|
137
|
+
kind: "rejected";
|
|
138
|
+
key: string;
|
|
139
|
+
reason: "active-limit" | "queue-depth" | "stale-blocked";
|
|
140
|
+
active: number;
|
|
141
|
+
queued: number;
|
|
142
|
+
limit: number;
|
|
143
|
+
} | {
|
|
144
|
+
kind: "coalesced";
|
|
145
|
+
key: string;
|
|
146
|
+
existing: JobIdentity;
|
|
147
|
+
reason: string;
|
|
148
|
+
} | {
|
|
149
|
+
kind: "replaced";
|
|
150
|
+
key: string;
|
|
151
|
+
replaced: JobIdentity;
|
|
152
|
+
ref: JobRef<TPayload, TResult, TUpdate>;
|
|
153
|
+
};
|
|
154
|
+
export type JobSnapshot<TPayload, TResult> = {
|
|
155
|
+
id: string;
|
|
156
|
+
service: string;
|
|
157
|
+
type: string;
|
|
158
|
+
state: JobState;
|
|
159
|
+
context: JobContext;
|
|
160
|
+
payload: TPayload;
|
|
161
|
+
result?: TResult;
|
|
162
|
+
createdAt: string;
|
|
163
|
+
updatedAt: string;
|
|
164
|
+
startedAt?: string;
|
|
165
|
+
completedAt?: string;
|
|
166
|
+
tries: number;
|
|
167
|
+
maxTries: number;
|
|
168
|
+
lastError?: string;
|
|
169
|
+
deadline?: string;
|
|
170
|
+
progress?: JobProgress;
|
|
171
|
+
logs?: JobLogEntry[];
|
|
172
|
+
trigger?: JobTrigger;
|
|
173
|
+
lineage?: JobLineage;
|
|
174
|
+
waitingOn?: JobWaitEdge[];
|
|
175
|
+
};
|
|
176
|
+
export type Job<TPayload = unknown, TResult = unknown> = JobSnapshot<TPayload, TResult>;
|
|
177
|
+
export type TerminalJob<TPayload, TResult> = JobSnapshot<TPayload, TResult> & {
|
|
178
|
+
state: "completed" | "failed" | "cancelled" | "expired" | "skipped" | "stale" | "dead" | "dismissed";
|
|
179
|
+
};
|
|
180
|
+
export type JobFilter = {
|
|
181
|
+
service?: string;
|
|
182
|
+
jobType?: string;
|
|
183
|
+
state?: JobState | JobState[];
|
|
184
|
+
since?: string;
|
|
185
|
+
limit?: number;
|
|
186
|
+
};
|
|
187
|
+
export type WorkerInfo = {
|
|
188
|
+
service: string;
|
|
189
|
+
jobType: string;
|
|
190
|
+
instanceId: string;
|
|
191
|
+
concurrency?: number;
|
|
192
|
+
version?: string;
|
|
193
|
+
timestamp: string;
|
|
194
|
+
};
|
|
195
|
+
export type ServiceInfo = {
|
|
196
|
+
name: string;
|
|
197
|
+
workers: WorkerInfo[];
|
|
198
|
+
healthy: boolean;
|
|
199
|
+
};
|
|
200
|
+
export type JobTypeMetadata = {
|
|
201
|
+
payload: unknown;
|
|
202
|
+
update: unknown;
|
|
203
|
+
result: unknown;
|
|
204
|
+
};
|
|
205
|
+
/** A transient update emitted by one job handler attempt. */
|
|
206
|
+
export type JobUpdateEnvelope<TUpdate = unknown> = {
|
|
207
|
+
jobId: string;
|
|
208
|
+
attempt: number;
|
|
209
|
+
sequence: number;
|
|
210
|
+
timestamp: string;
|
|
211
|
+
update: TUpdate;
|
|
212
|
+
};
|
|
213
|
+
/** Options for a queue-scoped job update subscription. */
|
|
214
|
+
export type JobUpdatesOptions = {
|
|
215
|
+
signal?: AbortSignal;
|
|
216
|
+
};
|
|
217
|
+
/** A live stream of typed transient job updates. */
|
|
218
|
+
export type JobUpdateSubscription<TUpdate> = AsyncIterable<TUpdate> & {
|
|
219
|
+
/** Stops the subscription immediately. */
|
|
220
|
+
unsubscribe(): void;
|
|
221
|
+
};
|
|
222
|
+
/** Decodes the structural Core NATS envelope used for transient job updates. */
|
|
223
|
+
export declare function decodeJobUpdateEnvelope(data: Uint8Array): JobUpdateEnvelope | undefined;
|
|
224
|
+
export declare class JobRef<TPayload, TResult, TUpdate = never> {
|
|
225
|
+
#private;
|
|
226
|
+
readonly id: string;
|
|
227
|
+
readonly service: string;
|
|
228
|
+
readonly type: string;
|
|
229
|
+
constructor(ref: JobIdentity, impl: {
|
|
230
|
+
get: () => AsyncResult<JobSnapshot<TPayload, TResult>, BaseError>;
|
|
231
|
+
wait: () => AsyncResult<TerminalJob<TPayload, TResult>, BaseError>;
|
|
232
|
+
cancel: () => AsyncResult<JobSnapshot<TPayload, TResult>, BaseError>;
|
|
233
|
+
updates?: (options?: JobUpdatesOptions) => AsyncResult<JobUpdateSubscription<TUpdate>, BaseError>;
|
|
234
|
+
});
|
|
235
|
+
get(): AsyncResult<JobSnapshot<TPayload, TResult>, BaseError>;
|
|
236
|
+
wait(): AsyncResult<TerminalJob<TPayload, TResult>, BaseError>;
|
|
237
|
+
cancel(): AsyncResult<JobSnapshot<TPayload, TResult>, BaseError>;
|
|
238
|
+
/** Subscribes to transient updates for this job. */
|
|
239
|
+
updates(options?: JobUpdatesOptions): AsyncResult<JobUpdateSubscription<TUpdate>, BaseError>;
|
|
240
|
+
}
|
|
241
|
+
export declare class ActiveJob<TPayload, TResult, TUpdate = never> {
|
|
242
|
+
#private;
|
|
243
|
+
readonly ref: JobRef<TPayload, TResult, TUpdate>;
|
|
244
|
+
readonly payload: TPayload;
|
|
245
|
+
readonly context: Readonly<JobContext>;
|
|
246
|
+
readonly signal: AbortSignal;
|
|
247
|
+
constructor(ref: JobRef<TPayload, TResult, TUpdate>, payload: TPayload, context: JobContext, cancelled: boolean | (() => boolean), impl: {
|
|
248
|
+
heartbeat: () => AsyncResult<void, BaseError>;
|
|
249
|
+
progress: (value: JobProgress) => AsyncResult<void, BaseError>;
|
|
250
|
+
log: (entry: JobLogEntry) => AsyncResult<void, BaseError>;
|
|
251
|
+
emitUpdate?: (value: TUpdate) => AsyncResult<void, BaseError>;
|
|
252
|
+
waitFor: <T>(target: JobWaitTarget, fn: () => Promise<T>) => Promise<T>;
|
|
253
|
+
redeliveryCount?: number;
|
|
254
|
+
signal?: AbortSignal;
|
|
255
|
+
});
|
|
256
|
+
get cancelled(): boolean;
|
|
257
|
+
heartbeat(): AsyncResult<void, BaseError>;
|
|
258
|
+
progress(value: JobProgress): AsyncResult<void, BaseError>;
|
|
259
|
+
log(entry: JobLogEntry): AsyncResult<void, BaseError>;
|
|
260
|
+
/** Emits a validated transient update for the current handler attempt. */
|
|
261
|
+
emitUpdate(value: TUpdate): AsyncResult<void, BaseError>;
|
|
262
|
+
/**
|
|
263
|
+
* Records that this job is waiting on another job, operation, or external async work.
|
|
264
|
+
* The wrapped function's return value or thrown error is preserved.
|
|
265
|
+
*/
|
|
266
|
+
waitFor<T>(target: JobWaitTarget, fn: () => Promise<T> | T): Promise<T>;
|
|
267
|
+
redeliveryCount(): number;
|
|
268
|
+
isRedelivery(): boolean;
|
|
269
|
+
}
|
|
270
|
+
export declare class JobQueue<TPayload, TResult, TUpdate = never> {
|
|
271
|
+
#private;
|
|
272
|
+
constructor(impl: {
|
|
273
|
+
create: (payload: TPayload) => AsyncResult<JobRef<TPayload, TResult, TUpdate>, BaseError>;
|
|
274
|
+
handle: (handler: (job: ActiveJob<TPayload, TResult, TUpdate>) => Promise<Result<TResult, BaseError>>, options?: JobHandlerOptions) => void;
|
|
275
|
+
submit?: (payload: TPayload) => AsyncResult<JobSubmitOutcome<TPayload, TResult, TUpdate>, BaseError>;
|
|
276
|
+
updates?: (jobId: string, options?: JobUpdatesOptions) => AsyncResult<JobUpdateSubscription<TUpdate>, BaseError>;
|
|
277
|
+
});
|
|
278
|
+
create(payload: TPayload): AsyncResult<JobRef<TPayload, TResult, TUpdate>, BaseError>;
|
|
279
|
+
/** Subscribes to transient updates for a known or preallocated job id. */
|
|
280
|
+
updates(jobId: string, options?: JobUpdatesOptions): AsyncResult<JobUpdateSubscription<TUpdate>, BaseError>;
|
|
281
|
+
/**
|
|
282
|
+
* Submits a job using queue policy outcomes for keyed queues.
|
|
283
|
+
* Unkeyed queues accept and return a new job reference.
|
|
284
|
+
*/
|
|
285
|
+
submit(payload: TPayload): AsyncResult<JobSubmitOutcome<TPayload, TResult, TUpdate>, BaseError>;
|
|
286
|
+
handle(handler: (job: ActiveJob<TPayload, TResult, TUpdate>) => Promise<Result<TResult, BaseError>>, options?: JobHandlerOptions): void;
|
|
287
|
+
}
|
|
288
|
+
/** Per-service-instance job handler configuration. */
|
|
289
|
+
export type JobHandlerOptions = {
|
|
290
|
+
/** Worker loops started for this job type. Defaults to one. */
|
|
291
|
+
concurrency?: number;
|
|
292
|
+
};
|
|
293
|
+
export interface JobWorkerHost {
|
|
294
|
+
stop(): AsyncResult<void, BaseError>;
|
|
295
|
+
join(): AsyncResult<void, BaseError>;
|
|
296
|
+
}
|
|
297
|
+
export declare class JobWorkerHostAdapter implements JobWorkerHost {
|
|
298
|
+
#private;
|
|
299
|
+
constructor(impl: {
|
|
300
|
+
stop: () => AsyncResult<void, BaseError>;
|
|
301
|
+
join: () => AsyncResult<void, BaseError>;
|
|
302
|
+
});
|
|
303
|
+
stop(): AsyncResult<void, BaseError>;
|
|
304
|
+
join(): AsyncResult<void, BaseError>;
|
|
305
|
+
}
|
|
306
|
+
export type JobsFacade = {};
|
|
307
|
+
export type JobsFacadeOf<TJobs extends Record<string, JobTypeMetadata>> = {
|
|
308
|
+
[K in keyof TJobs]: JobQueue<TJobs[K]["payload"], TJobs[K]["result"], TJobs[K]["update"]>;
|
|
309
|
+
} & JobsFacade;
|
package/jobs.js
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { AsyncResult, BaseError, Result } from "@oatscenter/result";
|
|
2
|
+
import { Type } from "typebox";
|
|
3
|
+
import { UnexpectedError } from "./errors/index.js";
|
|
4
|
+
import { setActiveJobWaitHook } from "./operations.js";
|
|
5
|
+
export const JobLogEntrySchema = Type.Object({
|
|
6
|
+
timestamp: Type.String({ format: "date-time" }),
|
|
7
|
+
level: Type.Union([
|
|
8
|
+
Type.Literal("info"),
|
|
9
|
+
Type.Literal("warn"),
|
|
10
|
+
Type.Literal("error"),
|
|
11
|
+
]),
|
|
12
|
+
message: Type.String(),
|
|
13
|
+
});
|
|
14
|
+
export const JobProgressSchema = Type.Object({
|
|
15
|
+
step: Type.Optional(Type.String()),
|
|
16
|
+
message: Type.Optional(Type.String()),
|
|
17
|
+
current: Type.Optional(Type.Integer({ minimum: 0 })),
|
|
18
|
+
total: Type.Optional(Type.Integer({ minimum: 0 })),
|
|
19
|
+
});
|
|
20
|
+
export const JobContextSchema = Type.Object({
|
|
21
|
+
requestId: Type.String({ minLength: 1 }),
|
|
22
|
+
traceId: Type.String({ pattern: "^[0-9a-f]{32}$" }),
|
|
23
|
+
traceparent: Type.String({
|
|
24
|
+
pattern: "^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$",
|
|
25
|
+
}),
|
|
26
|
+
tracestate: Type.Optional(Type.String({ minLength: 1 })),
|
|
27
|
+
});
|
|
28
|
+
export const JobTriggerSchema = Type.Object({
|
|
29
|
+
kind: Type.Union([
|
|
30
|
+
Type.Literal("schedule"),
|
|
31
|
+
Type.Literal("operation"),
|
|
32
|
+
Type.Literal("rpc"),
|
|
33
|
+
Type.Literal("event"),
|
|
34
|
+
Type.Literal("manualReplay"),
|
|
35
|
+
Type.Literal("serviceCode"),
|
|
36
|
+
Type.Literal("parentJob"),
|
|
37
|
+
]),
|
|
38
|
+
id: Type.Optional(Type.String({ minLength: 1 })),
|
|
39
|
+
subject: Type.Optional(Type.String({ minLength: 1 })),
|
|
40
|
+
operationId: Type.Optional(Type.String({ minLength: 1 })),
|
|
41
|
+
parentJobId: Type.Optional(Type.String({ minLength: 1 })),
|
|
42
|
+
traceId: Type.Optional(Type.String({ pattern: "^[0-9a-f]{32}$" })),
|
|
43
|
+
requestId: Type.Optional(Type.String({ minLength: 1 })),
|
|
44
|
+
});
|
|
45
|
+
export const JobLineageSchema = Type.Object({
|
|
46
|
+
parentJobId: Type.Optional(Type.String({ minLength: 1 })),
|
|
47
|
+
rootJobId: Type.Optional(Type.String({ minLength: 1 })),
|
|
48
|
+
operationId: Type.Optional(Type.String({ minLength: 1 })),
|
|
49
|
+
relatedKeys: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
|
|
50
|
+
});
|
|
51
|
+
export const JobWaitTargetSchema = Type.Object({
|
|
52
|
+
kind: Type.Union([
|
|
53
|
+
Type.Literal("job"),
|
|
54
|
+
Type.Literal("operation"),
|
|
55
|
+
Type.Literal("external"),
|
|
56
|
+
]),
|
|
57
|
+
id: Type.Optional(Type.String({ minLength: 1 })),
|
|
58
|
+
operationId: Type.Optional(Type.String({ minLength: 1 })),
|
|
59
|
+
service: Type.Optional(Type.String({ minLength: 1 })),
|
|
60
|
+
system: Type.Optional(Type.String({ minLength: 1 })),
|
|
61
|
+
type: Type.Optional(Type.String({ minLength: 1 })),
|
|
62
|
+
operation: Type.Optional(Type.String({ minLength: 1 })),
|
|
63
|
+
key: Type.Optional(Type.String({ minLength: 1 })),
|
|
64
|
+
label: Type.Optional(Type.String({ minLength: 1 })),
|
|
65
|
+
});
|
|
66
|
+
export const JobWaitEdgeSchema = Type.Object({
|
|
67
|
+
id: Type.String({ minLength: 1 }),
|
|
68
|
+
target: JobWaitTargetSchema,
|
|
69
|
+
startedAt: Type.String({ format: "date-time" }),
|
|
70
|
+
label: Type.Optional(Type.String({ minLength: 1 })),
|
|
71
|
+
});
|
|
72
|
+
/** Error returned when keyed job admission does not create a new job. */
|
|
73
|
+
export class JobNotEnqueuedError extends BaseError {
|
|
74
|
+
name = "JobNotEnqueuedError";
|
|
75
|
+
reason;
|
|
76
|
+
key;
|
|
77
|
+
active;
|
|
78
|
+
queued;
|
|
79
|
+
limit;
|
|
80
|
+
existingJobId;
|
|
81
|
+
constructor(options) {
|
|
82
|
+
const { reason, key, active, queued, limit, existingJobId, message, ...baseOptions } = options;
|
|
83
|
+
super(message ?? `Job was not enqueued for key '${key}': ${reason}`, baseOptions);
|
|
84
|
+
this.reason = reason;
|
|
85
|
+
this.key = key;
|
|
86
|
+
this.active = active;
|
|
87
|
+
this.queued = queued;
|
|
88
|
+
this.limit = limit;
|
|
89
|
+
this.existingJobId = existingJobId;
|
|
90
|
+
}
|
|
91
|
+
/** Serializes the admission error for transport or logging. */
|
|
92
|
+
toSerializable() {
|
|
93
|
+
const base = this.baseSerializable();
|
|
94
|
+
return {
|
|
95
|
+
id: base.id,
|
|
96
|
+
type: this.name,
|
|
97
|
+
message: base.message,
|
|
98
|
+
reason: this.reason,
|
|
99
|
+
key: this.key,
|
|
100
|
+
active: this.active,
|
|
101
|
+
queued: this.queued,
|
|
102
|
+
limit: this.limit,
|
|
103
|
+
...(this.existingJobId !== undefined
|
|
104
|
+
? { existingJobId: this.existingJobId }
|
|
105
|
+
: {}),
|
|
106
|
+
...(base.context !== undefined ? { context: base.context } : {}),
|
|
107
|
+
...(base.traceId !== undefined ? { traceId: base.traceId } : {}),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Error returned or thrown by a job handler to request JetStream redelivery. */
|
|
112
|
+
export class RetryJobError extends BaseError {
|
|
113
|
+
name = "RetryJobError";
|
|
114
|
+
constructor(options = {}) {
|
|
115
|
+
super(options.message ?? "Retry job", options);
|
|
116
|
+
}
|
|
117
|
+
/** Serializes the retry signal for worker lifecycle logging. */
|
|
118
|
+
toSerializable() {
|
|
119
|
+
return this.baseSerializable();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** Decodes the structural Core NATS envelope used for transient job updates. */
|
|
123
|
+
export function decodeJobUpdateEnvelope(data) {
|
|
124
|
+
try {
|
|
125
|
+
const value = JSON.parse(new TextDecoder().decode(data));
|
|
126
|
+
if (!value || typeof value !== "object")
|
|
127
|
+
return undefined;
|
|
128
|
+
const jobId = Reflect.get(value, "jobId");
|
|
129
|
+
const attempt = Reflect.get(value, "attempt");
|
|
130
|
+
const sequence = Reflect.get(value, "sequence");
|
|
131
|
+
const timestamp = Reflect.get(value, "timestamp");
|
|
132
|
+
if (typeof jobId !== "string" || jobId.length === 0 ||
|
|
133
|
+
!Number.isInteger(attempt) || attempt < 1 ||
|
|
134
|
+
!Number.isInteger(sequence) || sequence < 1 ||
|
|
135
|
+
typeof timestamp !== "string" || Number.isNaN(Date.parse(timestamp)) ||
|
|
136
|
+
!Reflect.has(value, "update")) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
jobId,
|
|
141
|
+
attempt,
|
|
142
|
+
sequence,
|
|
143
|
+
timestamp,
|
|
144
|
+
update: Reflect.get(value, "update"),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function toUnexpectedError(cause) {
|
|
152
|
+
return cause instanceof UnexpectedError
|
|
153
|
+
? cause
|
|
154
|
+
: new UnexpectedError({ cause });
|
|
155
|
+
}
|
|
156
|
+
let activeJobStorage;
|
|
157
|
+
/** @internal Runs work with the current active job available to child job creation and waits. */
|
|
158
|
+
export async function runWithActiveJobContext(context, fn) {
|
|
159
|
+
if (activeJobStorage === undefined) {
|
|
160
|
+
const { AsyncLocalStorage } = await import("node:async_hooks");
|
|
161
|
+
activeJobStorage ??= new AsyncLocalStorage();
|
|
162
|
+
}
|
|
163
|
+
return activeJobStorage.run(context, fn);
|
|
164
|
+
}
|
|
165
|
+
/** @internal Returns the current active job, if called inside a job handler. */
|
|
166
|
+
export function getActiveJobSnapshot() {
|
|
167
|
+
return activeJobStorage?.getStore()?.job;
|
|
168
|
+
}
|
|
169
|
+
/** @internal Records a current active-job wait if called inside a job handler. */
|
|
170
|
+
export function runActiveJobWait(target, fn) {
|
|
171
|
+
return activeJobStorage?.getStore()?.waitFor(target, fn);
|
|
172
|
+
}
|
|
173
|
+
setActiveJobWaitHook(runActiveJobWait);
|
|
174
|
+
export class JobRef {
|
|
175
|
+
id;
|
|
176
|
+
service;
|
|
177
|
+
type;
|
|
178
|
+
#get;
|
|
179
|
+
#wait;
|
|
180
|
+
#cancel;
|
|
181
|
+
#updates;
|
|
182
|
+
constructor(ref, impl) {
|
|
183
|
+
this.id = ref.id;
|
|
184
|
+
this.service = ref.service;
|
|
185
|
+
this.type = ref.jobType;
|
|
186
|
+
this.#get = impl.get;
|
|
187
|
+
this.#wait = impl.wait;
|
|
188
|
+
this.#cancel = impl.cancel;
|
|
189
|
+
this.#updates = impl.updates;
|
|
190
|
+
}
|
|
191
|
+
get() {
|
|
192
|
+
try {
|
|
193
|
+
return this.#get();
|
|
194
|
+
}
|
|
195
|
+
catch (cause) {
|
|
196
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
wait() {
|
|
200
|
+
return AsyncResult.from((async () => {
|
|
201
|
+
try {
|
|
202
|
+
const waited = runActiveJobWait({
|
|
203
|
+
kind: "job",
|
|
204
|
+
id: this.id,
|
|
205
|
+
service: this.service,
|
|
206
|
+
type: this.type,
|
|
207
|
+
}, async () => await this.#wait());
|
|
208
|
+
if (waited)
|
|
209
|
+
return await waited;
|
|
210
|
+
return await this.#wait();
|
|
211
|
+
}
|
|
212
|
+
catch (cause) {
|
|
213
|
+
return Result.err(toUnexpectedError(cause));
|
|
214
|
+
}
|
|
215
|
+
})());
|
|
216
|
+
}
|
|
217
|
+
cancel() {
|
|
218
|
+
try {
|
|
219
|
+
return this.#cancel();
|
|
220
|
+
}
|
|
221
|
+
catch (cause) {
|
|
222
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/** Subscribes to transient updates for this job. */
|
|
226
|
+
updates(options) {
|
|
227
|
+
if (!this.#updates) {
|
|
228
|
+
return AsyncResult.err(toUnexpectedError(new Error("Job updates are unavailable for this reference")));
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
return this.#updates(options);
|
|
232
|
+
}
|
|
233
|
+
catch (cause) {
|
|
234
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
export class ActiveJob {
|
|
239
|
+
ref;
|
|
240
|
+
payload;
|
|
241
|
+
context;
|
|
242
|
+
signal;
|
|
243
|
+
#cancelled;
|
|
244
|
+
#heartbeat;
|
|
245
|
+
#progress;
|
|
246
|
+
#log;
|
|
247
|
+
#emitUpdate;
|
|
248
|
+
#waitFor;
|
|
249
|
+
#redeliveryCount;
|
|
250
|
+
constructor(ref, payload, context, cancelled, impl) {
|
|
251
|
+
this.ref = ref;
|
|
252
|
+
this.payload = payload;
|
|
253
|
+
this.context = Object.freeze({ ...context });
|
|
254
|
+
this.#cancelled = typeof cancelled === "function"
|
|
255
|
+
? cancelled
|
|
256
|
+
: () => cancelled;
|
|
257
|
+
this.#heartbeat = impl.heartbeat;
|
|
258
|
+
this.#progress = impl.progress;
|
|
259
|
+
this.#log = impl.log;
|
|
260
|
+
this.#emitUpdate = impl.emitUpdate ??
|
|
261
|
+
(() => AsyncResult.err(toUnexpectedError(new Error("Job updates are not configured for this queue"))));
|
|
262
|
+
this.#waitFor = impl.waitFor;
|
|
263
|
+
this.#redeliveryCount = impl.redeliveryCount ?? 0;
|
|
264
|
+
this.signal = impl.signal ?? new AbortController().signal;
|
|
265
|
+
}
|
|
266
|
+
get cancelled() {
|
|
267
|
+
try {
|
|
268
|
+
return this.#cancelled();
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
heartbeat() {
|
|
275
|
+
try {
|
|
276
|
+
return this.#heartbeat();
|
|
277
|
+
}
|
|
278
|
+
catch (cause) {
|
|
279
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
progress(value) {
|
|
283
|
+
try {
|
|
284
|
+
return this.#progress(value);
|
|
285
|
+
}
|
|
286
|
+
catch (cause) {
|
|
287
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
log(entry) {
|
|
291
|
+
try {
|
|
292
|
+
return this.#log(entry);
|
|
293
|
+
}
|
|
294
|
+
catch (cause) {
|
|
295
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/** Emits a validated transient update for the current handler attempt. */
|
|
299
|
+
emitUpdate(value) {
|
|
300
|
+
try {
|
|
301
|
+
return this.#emitUpdate(value);
|
|
302
|
+
}
|
|
303
|
+
catch (cause) {
|
|
304
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Records that this job is waiting on another job, operation, or external async work.
|
|
309
|
+
* The wrapped function's return value or thrown error is preserved.
|
|
310
|
+
*/
|
|
311
|
+
waitFor(target, fn) {
|
|
312
|
+
return this.#waitFor(target, async () => await fn());
|
|
313
|
+
}
|
|
314
|
+
redeliveryCount() {
|
|
315
|
+
return this.#redeliveryCount;
|
|
316
|
+
}
|
|
317
|
+
isRedelivery() {
|
|
318
|
+
return this.#redeliveryCount > 0;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
export class JobQueue {
|
|
322
|
+
#create;
|
|
323
|
+
#handle;
|
|
324
|
+
#submit;
|
|
325
|
+
#updates;
|
|
326
|
+
constructor(impl) {
|
|
327
|
+
this.#create = impl.create;
|
|
328
|
+
this.#handle = impl.handle;
|
|
329
|
+
this.#submit = impl.submit ??
|
|
330
|
+
((payload) => impl.create(payload).map((ref) => ({ kind: "accepted", ref })));
|
|
331
|
+
this.#updates = impl.updates ?? (() => AsyncResult.err(toUnexpectedError(new Error("Job updates are not configured for this queue"))));
|
|
332
|
+
}
|
|
333
|
+
create(payload) {
|
|
334
|
+
try {
|
|
335
|
+
return this.#create(payload);
|
|
336
|
+
}
|
|
337
|
+
catch (cause) {
|
|
338
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/** Subscribes to transient updates for a known or preallocated job id. */
|
|
342
|
+
updates(jobId, options) {
|
|
343
|
+
try {
|
|
344
|
+
return this.#updates(jobId, options);
|
|
345
|
+
}
|
|
346
|
+
catch (cause) {
|
|
347
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Submits a job using queue policy outcomes for keyed queues.
|
|
352
|
+
* Unkeyed queues accept and return a new job reference.
|
|
353
|
+
*/
|
|
354
|
+
submit(payload) {
|
|
355
|
+
try {
|
|
356
|
+
return this.#submit(payload);
|
|
357
|
+
}
|
|
358
|
+
catch (cause) {
|
|
359
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
handle(handler, options) {
|
|
363
|
+
this.#handle(handler, options);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
export class JobWorkerHostAdapter {
|
|
367
|
+
#stop;
|
|
368
|
+
#join;
|
|
369
|
+
constructor(impl) {
|
|
370
|
+
this.#stop = impl.stop;
|
|
371
|
+
this.#join = impl.join;
|
|
372
|
+
}
|
|
373
|
+
stop() {
|
|
374
|
+
try {
|
|
375
|
+
return this.#stop();
|
|
376
|
+
}
|
|
377
|
+
catch (cause) {
|
|
378
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
join() {
|
|
382
|
+
try {
|
|
383
|
+
return this.#join();
|
|
384
|
+
}
|
|
385
|
+
catch (cause) {
|
|
386
|
+
return AsyncResult.err(toUnexpectedError(cause));
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|