@xemahq/temporal-runtime 0.6.0 → 0.8.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/README.md +203 -11
- package/dist/bin/controller-token-publisher.d.ts +3 -0
- package/dist/bin/controller-token-publisher.d.ts.map +1 -0
- package/dist/bin/controller-token-publisher.js +18 -0
- package/dist/bin/controller-token-publisher.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/access-token.d.ts +11 -0
- package/dist/lib/access-token.d.ts.map +1 -0
- package/dist/lib/access-token.js +30 -0
- package/dist/lib/access-token.js.map +1 -0
- package/dist/lib/base-temporal-client.service.d.ts +3 -2
- package/dist/lib/base-temporal-client.service.d.ts.map +1 -1
- package/dist/lib/base-temporal-client.service.js +5 -5
- package/dist/lib/base-temporal-client.service.js.map +1 -1
- package/dist/lib/biome-worker.d.ts +107 -0
- package/dist/lib/biome-worker.d.ts.map +1 -0
- package/dist/lib/biome-worker.js +348 -0
- package/dist/lib/biome-worker.js.map +1 -0
- package/dist/lib/bounded-retry.d.ts +22 -0
- package/dist/lib/bounded-retry.d.ts.map +1 -0
- package/dist/lib/bounded-retry.js +67 -0
- package/dist/lib/bounded-retry.js.map +1 -0
- package/dist/lib/client-credentials-token-source.d.ts +23 -0
- package/dist/lib/client-credentials-token-source.d.ts.map +1 -0
- package/dist/lib/client-credentials-token-source.js +108 -0
- package/dist/lib/client-credentials-token-source.js.map +1 -0
- package/dist/lib/connection.d.ts +48 -9
- package/dist/lib/connection.d.ts.map +1 -1
- package/dist/lib/connection.js +153 -41
- package/dist/lib/connection.js.map +1 -1
- package/dist/lib/controller-token-publisher.d.ts +51 -0
- package/dist/lib/controller-token-publisher.d.ts.map +1 -0
- package/dist/lib/controller-token-publisher.js +116 -0
- package/dist/lib/controller-token-publisher.js.map +1 -0
- package/dist/lib/fairness-constants.d.ts +4 -0
- package/dist/lib/fairness-constants.d.ts.map +1 -0
- package/dist/lib/fairness-constants.js +7 -0
- package/dist/lib/fairness-constants.js.map +1 -0
- package/dist/lib/fairness.d.ts +13 -0
- package/dist/lib/fairness.d.ts.map +1 -0
- package/dist/lib/fairness.js +56 -0
- package/dist/lib/fairness.js.map +1 -0
- package/dist/lib/nexus-constants.d.ts +8 -0
- package/dist/lib/nexus-constants.d.ts.map +1 -0
- package/dist/lib/nexus-constants.js +14 -0
- package/dist/lib/nexus-constants.js.map +1 -0
- package/dist/lib/nexus-contract.d.ts +43 -0
- package/dist/lib/nexus-contract.d.ts.map +1 -0
- package/dist/lib/nexus-contract.js +101 -0
- package/dist/lib/nexus-contract.js.map +1 -0
- package/dist/lib/nexus-handler.d.ts +32 -0
- package/dist/lib/nexus-handler.d.ts.map +1 -0
- package/dist/lib/nexus-handler.js +144 -0
- package/dist/lib/nexus-handler.js.map +1 -0
- package/dist/lib/nexus-workflow.d.ts +22 -0
- package/dist/lib/nexus-workflow.d.ts.map +1 -0
- package/dist/lib/nexus-workflow.js +74 -0
- package/dist/lib/nexus-workflow.js.map +1 -0
- package/dist/lib/org-erasure.d.ts +13 -0
- package/dist/lib/org-erasure.d.ts.map +1 -0
- package/dist/lib/org-erasure.js +68 -0
- package/dist/lib/org-erasure.js.map +1 -0
- package/dist/lib/proactive-token-refresher.d.ts +47 -0
- package/dist/lib/proactive-token-refresher.d.ts.map +1 -0
- package/dist/lib/proactive-token-refresher.js +147 -0
- package/dist/lib/proactive-token-refresher.js.map +1 -0
- package/dist/lib/search-attribute-constants.d.ts +3 -0
- package/dist/lib/search-attribute-constants.d.ts.map +1 -0
- package/dist/lib/search-attribute-constants.js +6 -0
- package/dist/lib/search-attribute-constants.js.map +1 -0
- package/dist/lib/search-attributes.d.ts +4 -18
- package/dist/lib/search-attributes.d.ts.map +1 -1
- package/dist/lib/search-attributes.js +33 -40
- package/dist/lib/search-attributes.js.map +1 -1
- package/dist/lib/standalone-activity.d.ts +23 -0
- package/dist/lib/standalone-activity.d.ts.map +1 -0
- package/dist/lib/standalone-activity.js +48 -0
- package/dist/lib/standalone-activity.js.map +1 -0
- package/dist/lib/versioned-worker.d.ts +26 -0
- package/dist/lib/versioned-worker.d.ts.map +1 -0
- package/dist/lib/versioned-worker.js +60 -0
- package/dist/lib/versioned-worker.js.map +1 -0
- package/dist/lib/worker-deployment-version.d.ts +8 -0
- package/dist/lib/worker-deployment-version.d.ts.map +1 -0
- package/dist/lib/worker-deployment-version.js +45 -0
- package/dist/lib/worker-deployment-version.js.map +1 -0
- package/dist/lib/worker.d.ts +8 -7
- package/dist/lib/worker.d.ts.map +1 -1
- package/dist/lib/worker.js +55 -37
- package/dist/lib/worker.js.map +1 -1
- package/dist/lib/workflow-interceptors/fairness-guard.d.ts +4 -0
- package/dist/lib/workflow-interceptors/fairness-guard.d.ts.map +1 -0
- package/dist/lib/workflow-interceptors/fairness-guard.js +79 -0
- package/dist/lib/workflow-interceptors/fairness-guard.js.map +1 -0
- package/dist/lib/workflow-interceptors/fairness-propagation.d.ts +3 -0
- package/dist/lib/workflow-interceptors/fairness-propagation.d.ts.map +1 -0
- package/dist/lib/workflow-interceptors/fairness-propagation.js +6 -0
- package/dist/lib/workflow-interceptors/fairness-propagation.js.map +1 -0
- package/dist/lib/workflow-interceptors/org-fairness-required.d.ts +3 -0
- package/dist/lib/workflow-interceptors/org-fairness-required.d.ts.map +1 -0
- package/dist/lib/workflow-interceptors/org-fairness-required.js +6 -0
- package/dist/lib/workflow-interceptors/org-fairness-required.js.map +1 -0
- package/dist/lib/workflow-interceptors/org-search-attribute.d.ts +3 -0
- package/dist/lib/workflow-interceptors/org-search-attribute.d.ts.map +1 -0
- package/dist/lib/workflow-interceptors/org-search-attribute.js +49 -0
- package/dist/lib/workflow-interceptors/org-search-attribute.js.map +1 -0
- package/dist/lib/workflow-purity.d.ts +27 -0
- package/dist/lib/workflow-purity.d.ts.map +1 -0
- package/dist/lib/workflow-purity.js +115 -0
- package/dist/lib/workflow-purity.js.map +1 -0
- package/package.json +33 -10
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BiomeWorkerError = exports.BiomeWorkerErrorCode = void 0;
|
|
4
|
+
exports.defineBiomeWorker = defineBiomeWorker;
|
|
5
|
+
exports.resolveNexusTopology = resolveNexusTopology;
|
|
6
|
+
exports.composeBiomeWorkers = composeBiomeWorkers;
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const biome_1 = require("@xemahq/contracts/biome");
|
|
9
|
+
const deployment_1 = require("@xemahq/contracts/deployment");
|
|
10
|
+
const process_topology_1 = require("@xemahq/contracts/process-topology");
|
|
11
|
+
const workflow_1 = require("@xemahq/contracts/workflow");
|
|
12
|
+
const fairness_1 = require("./fairness");
|
|
13
|
+
const nexus_constants_1 = require("./nexus-constants");
|
|
14
|
+
const versioned_worker_1 = require("./versioned-worker");
|
|
15
|
+
const worker_1 = require("./worker");
|
|
16
|
+
const worker_deployment_version_1 = require("./worker-deployment-version");
|
|
17
|
+
var BiomeWorkerErrorCode;
|
|
18
|
+
(function (BiomeWorkerErrorCode) {
|
|
19
|
+
BiomeWorkerErrorCode["ProtocolNotWorkerV2"] = "protocol-not-worker-v2";
|
|
20
|
+
BiomeWorkerErrorCode["ImplementationMismatch"] = "implementation-mismatch";
|
|
21
|
+
BiomeWorkerErrorCode["NexusMismatch"] = "nexus-mismatch";
|
|
22
|
+
BiomeWorkerErrorCode["InvalidComponentKey"] = "invalid-component-key";
|
|
23
|
+
BiomeWorkerErrorCode["DuplicateComponent"] = "duplicate-component";
|
|
24
|
+
BiomeWorkerErrorCode["DuplicateTaskQueue"] = "duplicate-task-queue";
|
|
25
|
+
BiomeWorkerErrorCode["MixedTrustDomains"] = "mixed-trust-domains";
|
|
26
|
+
BiomeWorkerErrorCode["EmptyComposition"] = "empty-composition";
|
|
27
|
+
BiomeWorkerErrorCode["NexusLockMissing"] = "nexus-lock-missing";
|
|
28
|
+
BiomeWorkerErrorCode["NexusBindingAbsent"] = "nexus-binding-absent";
|
|
29
|
+
BiomeWorkerErrorCode["NexusBindingMismatch"] = "nexus-binding-mismatch";
|
|
30
|
+
})(BiomeWorkerErrorCode || (exports.BiomeWorkerErrorCode = BiomeWorkerErrorCode = {}));
|
|
31
|
+
class BiomeWorkerError extends Error {
|
|
32
|
+
code;
|
|
33
|
+
constructor(code, message) {
|
|
34
|
+
super(`[${code}] ${message}`);
|
|
35
|
+
this.code = code;
|
|
36
|
+
this.name = 'BiomeWorkerError';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.BiomeWorkerError = BiomeWorkerError;
|
|
40
|
+
const COMPONENT_KEY_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
41
|
+
const FAIRNESS_INTERCEPTOR_MODULE = {
|
|
42
|
+
[biome_1.BiomeWorkerTaskQueueFairness.Org]: (0, node_path_1.join)(__dirname, 'workflow-interceptors', 'org-fairness-required'),
|
|
43
|
+
[biome_1.BiomeWorkerTaskQueueFairness.None]: (0, node_path_1.join)(__dirname, 'workflow-interceptors', 'fairness-propagation'),
|
|
44
|
+
};
|
|
45
|
+
function servesAny(queues, kind) {
|
|
46
|
+
return queues.some((queue) => queue.serves.includes(kind));
|
|
47
|
+
}
|
|
48
|
+
function defineBiomeWorker(options) {
|
|
49
|
+
if (!COMPONENT_KEY_PATTERN.test(options.componentKey)) {
|
|
50
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.InvalidComponentKey, `component key ${JSON.stringify(options.componentKey)} must be kebab-case.`);
|
|
51
|
+
}
|
|
52
|
+
const where = `${options.biomeId}/${options.componentKey}`;
|
|
53
|
+
const parsed = biome_1.BiomeWorkerProtocolSchema.safeParse(options.protocol);
|
|
54
|
+
if (!parsed.success ||
|
|
55
|
+
parsed.data.kind !== biome_1.BiomeComponentProtocolKind.Worker ||
|
|
56
|
+
parsed.data.revision !== 'v2') {
|
|
57
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.ProtocolNotWorkerV2, `${where}: the protocol must be a worker protocol at revision v2` +
|
|
58
|
+
(parsed.success
|
|
59
|
+
? ` (got revision ${parsed.data.revision}).`
|
|
60
|
+
: `: ${parsed.error.message}`));
|
|
61
|
+
}
|
|
62
|
+
const protocol = parsed.data;
|
|
63
|
+
const declared = protocol.taskQueues;
|
|
64
|
+
for (const [kind, supplied, field] of [
|
|
65
|
+
[
|
|
66
|
+
biome_1.BiomeWorkerTaskQueueServes.Workflows,
|
|
67
|
+
options.workflowsPath,
|
|
68
|
+
'workflowsPath',
|
|
69
|
+
],
|
|
70
|
+
[biome_1.BiomeWorkerTaskQueueServes.Activities, options.activities, 'activities'],
|
|
71
|
+
]) {
|
|
72
|
+
const needed = servesAny(declared, kind);
|
|
73
|
+
if (needed !== (supplied !== undefined)) {
|
|
74
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.ImplementationMismatch, needed
|
|
75
|
+
? `${where}: a task queue serves '${kind}' but no ${field} was supplied.`
|
|
76
|
+
: `${where}: ${field} was supplied but no task queue serves '${kind}'.`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const provides = protocol.nexus?.provides ?? [];
|
|
80
|
+
const supplied = options.nexusServices ?? [];
|
|
81
|
+
const suppliedByKey = new Map();
|
|
82
|
+
for (const impl of supplied) {
|
|
83
|
+
const key = (0, nexus_constants_1.nexusServiceKey)(impl.service, impl.version);
|
|
84
|
+
if (suppliedByKey.has(key)) {
|
|
85
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.NexusMismatch, `${where}: Nexus service ${key} was supplied twice.`);
|
|
86
|
+
}
|
|
87
|
+
suppliedByKey.set(key, impl);
|
|
88
|
+
}
|
|
89
|
+
const declaredKeys = new Set(provides.map((p) => (0, nexus_constants_1.nexusServiceKey)(p.service, p.version)));
|
|
90
|
+
const undeclared = [...suppliedByKey.keys()].filter((k) => !declaredKeys.has(k));
|
|
91
|
+
const unimplemented = [...declaredKeys].filter((k) => !suppliedByKey.has(k));
|
|
92
|
+
if (undeclared.length > 0 || unimplemented.length > 0) {
|
|
93
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.NexusMismatch, `${where}: Nexus handlers must match nexus.provides exactly` +
|
|
94
|
+
(unimplemented.length > 0
|
|
95
|
+
? `; declared but not supplied: ${unimplemented.join(', ')}`
|
|
96
|
+
: '') +
|
|
97
|
+
(undeclared.length > 0
|
|
98
|
+
? `; supplied but not declared: ${undeclared.join(', ')}`
|
|
99
|
+
: '') +
|
|
100
|
+
'.');
|
|
101
|
+
}
|
|
102
|
+
for (const provided of provides) {
|
|
103
|
+
const impl = suppliedByKey.get((0, nexus_constants_1.nexusServiceKey)(provided.service, provided.version));
|
|
104
|
+
const declaredOps = new Map(provided.operations.map((o) => [o.name, o.mode]));
|
|
105
|
+
const drift = [
|
|
106
|
+
...[...declaredOps].filter(([name, mode]) => impl.operations.get(name) !== mode)
|
|
107
|
+
.map(([name, mode]) => `${name} (manifest ${mode}, contract ${impl.operations.get(name) ?? 'absent'})`),
|
|
108
|
+
...[...impl.operations.keys()].filter((name) => !declaredOps.has(name))
|
|
109
|
+
.map((name) => `${name} (contract only)`),
|
|
110
|
+
];
|
|
111
|
+
if (drift.length > 0) {
|
|
112
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.NexusMismatch, `${where}: Nexus service ${(0, nexus_constants_1.nexusServiceKey)(provided.service, provided.version)} operations ` +
|
|
113
|
+
`differ from nexus.provides: ${drift.join(', ')}.`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const queues = declared.map((queue) => {
|
|
117
|
+
const nexusServices = provides
|
|
118
|
+
.filter((p) => p.taskQueue === queue.name)
|
|
119
|
+
.map((p) => suppliedByKey.get((0, nexus_constants_1.nexusServiceKey)(p.service, p.version)));
|
|
120
|
+
if (queue.serves.includes(biome_1.BiomeWorkerTaskQueueServes.Nexus) &&
|
|
121
|
+
nexusServices.length === 0) {
|
|
122
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.NexusMismatch, `${where}: task queue ${queue.name} serves 'nexus' but no nexus.provides entry names it.`);
|
|
123
|
+
}
|
|
124
|
+
return Object.freeze({
|
|
125
|
+
name: queue.name,
|
|
126
|
+
taskQueue: (0, workflow_1.biomeTaskQueue)(options.biomeId, queue.name),
|
|
127
|
+
serves: Object.freeze([...queue.serves]),
|
|
128
|
+
fairness: queue.fairness,
|
|
129
|
+
nexusServices: Object.freeze(nexusServices),
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
return Object.freeze({
|
|
133
|
+
biomeId: options.biomeId,
|
|
134
|
+
componentKey: options.componentKey,
|
|
135
|
+
origin: options.origin,
|
|
136
|
+
queues: Object.freeze(queues),
|
|
137
|
+
nexusRequires: Object.freeze((protocol.nexus?.requires ?? []).map((r) => Object.freeze({
|
|
138
|
+
service: r.service,
|
|
139
|
+
version: r.version,
|
|
140
|
+
optional: r.optional === true,
|
|
141
|
+
}))),
|
|
142
|
+
...(options.workflowsPath !== undefined
|
|
143
|
+
? { workflowsPath: options.workflowsPath }
|
|
144
|
+
: {}),
|
|
145
|
+
...(options.activities !== undefined
|
|
146
|
+
? { activities: options.activities }
|
|
147
|
+
: {}),
|
|
148
|
+
workflowInterceptorModules: Object.freeze([
|
|
149
|
+
...(options.workflowInterceptorModules ?? []),
|
|
150
|
+
]),
|
|
151
|
+
activityInterceptors: Object.freeze([
|
|
152
|
+
...(options.activityInterceptors ?? []),
|
|
153
|
+
]),
|
|
154
|
+
...(options.payloadCodec !== undefined
|
|
155
|
+
? { payloadCodec: options.payloadCodec }
|
|
156
|
+
: {}),
|
|
157
|
+
...(options.sinks !== undefined ? { sinks: options.sinks } : {}),
|
|
158
|
+
tuning: Object.freeze({ ...(options.tuning ?? {}) }),
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
function resolveNexusTopology(options) {
|
|
162
|
+
const deploymentId = (0, deployment_1.parseDeploymentId)(options.deploymentId);
|
|
163
|
+
const usesNexus = options.definitions.some((d) => d.nexusRequires.length > 0 || d.queues.some((q) => q.nexusServices.length > 0));
|
|
164
|
+
const allowedCallers = new Map();
|
|
165
|
+
const endpoints = new Map();
|
|
166
|
+
if (!usesNexus) {
|
|
167
|
+
for (const def of options.definitions) {
|
|
168
|
+
endpoints.set(`${def.biomeId}/${def.componentKey}`, Object.freeze({}));
|
|
169
|
+
}
|
|
170
|
+
return { allowedCallers, endpoints };
|
|
171
|
+
}
|
|
172
|
+
const lock = options.lock;
|
|
173
|
+
if (lock === undefined) {
|
|
174
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.NexusLockMissing, 'a composed definition provides or requires Nexus, and no distribution lock was supplied: ' +
|
|
175
|
+
'the lock alone says which callers a provider admits and which endpoints a caller may name.');
|
|
176
|
+
}
|
|
177
|
+
const origins = new Map(lock.biomes.map((b) => [b.id, b.origin]));
|
|
178
|
+
const bindings = new Map((lock.nexusBindings ?? []).map((b) => [(0, nexus_constants_1.nexusServiceKey)(b.service, b.version), b]));
|
|
179
|
+
const namespaceOf = (biomeId) => {
|
|
180
|
+
const origin = origins.get(biomeId);
|
|
181
|
+
if (origin === undefined) {
|
|
182
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.NexusBindingMismatch, `the lock binds biome ${biomeId} as a Nexus caller and ships no biome by that id.`);
|
|
183
|
+
}
|
|
184
|
+
return (0, workflow_1.workflowNamespaceForTrustDomain)(deploymentId, (0, process_topology_1.resolveTrustDomain)(biomeId, origin, options.trustPolicy));
|
|
185
|
+
};
|
|
186
|
+
for (const def of options.definitions) {
|
|
187
|
+
const component = `${def.biomeId}/${def.componentKey}`;
|
|
188
|
+
for (const queue of def.queues) {
|
|
189
|
+
for (const impl of queue.nexusServices) {
|
|
190
|
+
const key = (0, nexus_constants_1.nexusServiceKey)(impl.service, impl.version);
|
|
191
|
+
const binding = bindings.get(key);
|
|
192
|
+
if (binding === undefined) {
|
|
193
|
+
allowedCallers.set(key, new Set());
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (binding.providerBiome !== def.biomeId ||
|
|
197
|
+
binding.providerComponent !== def.componentKey ||
|
|
198
|
+
binding.taskQueue !== queue.taskQueue) {
|
|
199
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.NexusBindingMismatch, `${component} provides ${key} on ${queue.taskQueue}, and the lock binds it to ` +
|
|
200
|
+
`${binding.providerBiome}/${binding.providerComponent} on ${binding.taskQueue}.`);
|
|
201
|
+
}
|
|
202
|
+
allowedCallers.set(key, new Set(binding.callers.map(namespaceOf)));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const map = {};
|
|
206
|
+
for (const req of def.nexusRequires) {
|
|
207
|
+
const key = (0, nexus_constants_1.nexusServiceKey)(req.service, req.version);
|
|
208
|
+
const binding = bindings.get(key);
|
|
209
|
+
if (binding === undefined || !binding.callers.includes(def.biomeId)) {
|
|
210
|
+
if (req.optional && binding === undefined) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.NexusBindingAbsent, `${component} requires Nexus service ${key}, and the lock ` +
|
|
214
|
+
(binding === undefined
|
|
215
|
+
? 'binds no provider for it.'
|
|
216
|
+
: `does not name biome ${def.biomeId} among its callers (${binding.callers.join(', ')}).`));
|
|
217
|
+
}
|
|
218
|
+
map[key] = (0, workflow_1.nexusEndpointName)(deploymentId, req.service, req.version);
|
|
219
|
+
}
|
|
220
|
+
endpoints.set(component, Object.freeze(map));
|
|
221
|
+
}
|
|
222
|
+
return { allowedCallers, endpoints };
|
|
223
|
+
}
|
|
224
|
+
async function composeBiomeWorkers(options) {
|
|
225
|
+
const { definitions } = options;
|
|
226
|
+
if (definitions.length === 0) {
|
|
227
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.EmptyComposition, 'composeBiomeWorkers needs at least one definition.');
|
|
228
|
+
}
|
|
229
|
+
const deploymentId = (0, deployment_1.parseDeploymentId)(options.deploymentId);
|
|
230
|
+
const version = (0, worker_deployment_version_1.assertWorkerDeploymentVersion)(options.version);
|
|
231
|
+
const components = new Set();
|
|
232
|
+
const taskQueues = new Set();
|
|
233
|
+
const domains = new Map();
|
|
234
|
+
for (const def of definitions) {
|
|
235
|
+
const component = `${def.biomeId}/${def.componentKey}`;
|
|
236
|
+
if (components.has(component)) {
|
|
237
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.DuplicateComponent, `${component} is composed twice.`);
|
|
238
|
+
}
|
|
239
|
+
components.add(component);
|
|
240
|
+
for (const queue of def.queues) {
|
|
241
|
+
if (taskQueues.has(queue.taskQueue)) {
|
|
242
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.DuplicateTaskQueue, `task queue ${queue.taskQueue} is polled by two composed definitions.`);
|
|
243
|
+
}
|
|
244
|
+
taskQueues.add(queue.taskQueue);
|
|
245
|
+
}
|
|
246
|
+
const domain = (0, process_topology_1.resolveTrustDomain)(def.biomeId, def.origin, options.trustPolicy);
|
|
247
|
+
domains.set(domain, [...(domains.get(domain) ?? []), component]);
|
|
248
|
+
}
|
|
249
|
+
if (domains.size !== 1) {
|
|
250
|
+
throw new BiomeWorkerError(BiomeWorkerErrorCode.MixedTrustDomains, 'one process is one trust domain, but the composed definitions resolve to ' +
|
|
251
|
+
[...domains].map(([d, c]) => `${d} (${c.join(', ')})`).join(' and ') +
|
|
252
|
+
'.');
|
|
253
|
+
}
|
|
254
|
+
const trustDomain = [...domains.keys()][0];
|
|
255
|
+
const namespace = (0, workflow_1.workflowNamespaceForTrustDomain)(deploymentId, trustDomain);
|
|
256
|
+
const nexus = resolveNexusTopology({
|
|
257
|
+
deploymentId,
|
|
258
|
+
definitions,
|
|
259
|
+
...(options.trustPolicy !== undefined ? { trustPolicy: options.trustPolicy } : {}),
|
|
260
|
+
...(options.lock !== undefined ? { lock: options.lock } : {}),
|
|
261
|
+
});
|
|
262
|
+
const bundles = new Map();
|
|
263
|
+
async function bundleFor(def, fairness) {
|
|
264
|
+
const key = `${def.biomeId}/${def.componentKey}#${fairness}`;
|
|
265
|
+
const cached = bundles.get(key);
|
|
266
|
+
if (cached !== undefined) {
|
|
267
|
+
return cached;
|
|
268
|
+
}
|
|
269
|
+
const bundle = await (0, worker_1.bundlePlatformWorkflows)(def.workflowsPath, {
|
|
270
|
+
workflowInterceptorModules: [
|
|
271
|
+
FAIRNESS_INTERCEPTOR_MODULE[fairness],
|
|
272
|
+
...def.workflowInterceptorModules,
|
|
273
|
+
],
|
|
274
|
+
nexusEndpoints: nexus.endpoints.get(`${def.biomeId}/${def.componentKey}`),
|
|
275
|
+
});
|
|
276
|
+
bundles.set(key, bundle);
|
|
277
|
+
return bundle;
|
|
278
|
+
}
|
|
279
|
+
const workers = [];
|
|
280
|
+
for (const def of definitions) {
|
|
281
|
+
for (const queue of def.queues) {
|
|
282
|
+
const servesWorkflows = queue.serves.includes(biome_1.BiomeWorkerTaskQueueServes.Workflows);
|
|
283
|
+
const servesActivities = queue.serves.includes(biome_1.BiomeWorkerTaskQueueServes.Activities);
|
|
284
|
+
const worker = await (0, versioned_worker_1.createVersionedWorker)({
|
|
285
|
+
connection: options.connection,
|
|
286
|
+
namespace,
|
|
287
|
+
taskQueue: queue.taskQueue,
|
|
288
|
+
version,
|
|
289
|
+
identity: (0, versioned_worker_1.platformWorkerIdentity)(`xema-biome-worker-${def.biomeId}-${def.componentKey}`, namespace, queue.taskQueue),
|
|
290
|
+
...(servesWorkflows
|
|
291
|
+
? { workflowBundle: await bundleFor(def, queue.fairness) }
|
|
292
|
+
: {}),
|
|
293
|
+
...(servesActivities ? { activities: def.activities } : {}),
|
|
294
|
+
...(queue.nexusServices.length > 0
|
|
295
|
+
? {
|
|
296
|
+
nexusServices: queue.nexusServices.map((n) => n.bind({
|
|
297
|
+
allowedCallerNamespaces: nexus.allowedCallers.get((0, nexus_constants_1.nexusServiceKey)(n.service, n.version)),
|
|
298
|
+
})),
|
|
299
|
+
}
|
|
300
|
+
: {}),
|
|
301
|
+
activityInterceptors: [
|
|
302
|
+
...(queue.fairness === biome_1.BiomeWorkerTaskQueueFairness.Org
|
|
303
|
+
? [fairness_1.orgFairnessActivityInterceptor]
|
|
304
|
+
: []),
|
|
305
|
+
...def.activityInterceptors,
|
|
306
|
+
],
|
|
307
|
+
...(def.payloadCodec !== undefined
|
|
308
|
+
? { payloadCodec: def.payloadCodec }
|
|
309
|
+
: {}),
|
|
310
|
+
...(def.sinks !== undefined ? { sinks: def.sinks } : {}),
|
|
311
|
+
...def.tuning,
|
|
312
|
+
});
|
|
313
|
+
workers.push(Object.freeze({
|
|
314
|
+
biomeId: def.biomeId,
|
|
315
|
+
componentKey: def.componentKey,
|
|
316
|
+
taskQueue: queue.taskQueue,
|
|
317
|
+
worker,
|
|
318
|
+
}));
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function shutdown() {
|
|
322
|
+
for (const { worker } of workers) {
|
|
323
|
+
if (worker.getState() === 'RUNNING') {
|
|
324
|
+
worker.shutdown();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
async function run() {
|
|
329
|
+
const runs = workers.map(({ worker }) => worker.run());
|
|
330
|
+
try {
|
|
331
|
+
await Promise.all(runs);
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
shutdown();
|
|
335
|
+
await Promise.allSettled(runs);
|
|
336
|
+
throw error;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return Object.freeze({
|
|
340
|
+
trustDomain,
|
|
341
|
+
namespace,
|
|
342
|
+
version,
|
|
343
|
+
workers: Object.freeze(workers),
|
|
344
|
+
run,
|
|
345
|
+
shutdown,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=biome-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"biome-worker.js","sourceRoot":"","sources":["../../src/lib/biome-worker.ts"],"names":[],"mappings":";;;AA+LA,8CA+JC;AAkDD,oDA2FC;AAyCD,kDAqKC;AAzrBD,yCAAiC;AAEjC,mDAOiC;AACjC,6DAAiE;AAEjE,yEAG4C;AAC5C,yDAIoC;AAEpC,yCAA4D;AAC5D,uDAAoD;AACpD,yDAK4B;AAC5B,qCAAmD;AACnD,2EAGqC;AAarC,IAAY,oBAuBX;AAvBD,WAAY,oBAAoB;IAE9B,sEAA8C,CAAA;IAE9C,0EAAkD,CAAA;IAElD,wDAAgC,CAAA;IAEhC,qEAA6C,CAAA;IAE7C,kEAA0C,CAAA;IAE1C,mEAA2C,CAAA;IAE3C,iEAAyC,CAAA;IAEzC,8DAAsC,CAAA;IAEtC,+DAAuC,CAAA;IAEvC,mEAA2C,CAAA;IAE3C,uEAA+C,CAAA;AACjD,CAAC,EAvBW,oBAAoB,oCAApB,oBAAoB,QAuB/B;AAED,MAAa,gBAAiB,SAAQ,KAAK;IAE9B;IADX,YACW,IAA0B,EACnC,OAAe;QAEf,KAAK,CAAC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QAHrB,SAAI,GAAJ,IAAI,CAAsB;QAInC,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AARD,4CAQC;AAqED,MAAM,qBAAqB,GAAG,mBAAmB,CAAC;AAOlD,MAAM,2BAA2B,GAE7B;IACF,CAAC,oCAA4B,CAAC,GAAG,CAAC,EAAE,IAAA,gBAAI,EACtC,SAAS,EACT,uBAAuB,EACvB,uBAAuB,CACxB;IACD,CAAC,oCAA4B,CAAC,IAAI,CAAC,EAAE,IAAA,gBAAI,EACvC,SAAS,EACT,uBAAuB,EACvB,sBAAsB,CACvB;CACF,CAAC;AAEF,SAAS,SAAS,CAChB,MAAuC,EACvC,IAAgC;IAEhC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7D,CAAC;AAeD,SAAgB,iBAAiB,CAC/B,OAAiC;IAEjC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,mBAAmB,EACxC,iBAAiB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,sBAAsB,CAC5E,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAC3D,MAAM,MAAM,GAAG,iCAAyB,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrE,IACE,CAAC,MAAM,CAAC,OAAO;QACf,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,kCAA0B,CAAC,MAAM;QACtD,MAAM,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,EAC7B,CAAC;QACD,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,mBAAmB,EACxC,GAAG,KAAK,yDAAyD;YAC/D,CAAC,MAAM,CAAC,OAAO;gBACb,CAAC,CAAC,kBAAkB,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI;gBAC5C,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CACnC,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC;IAC7B,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC;IAErC,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI;QACpC;YACE,kCAA0B,CAAC,SAAS;YACpC,OAAO,CAAC,aAAa;YACrB,eAAe;SAChB;QACD,CAAC,kCAA0B,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC;KACjE,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACzC,IAAI,MAAM,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,sBAAsB,EAC3C,MAAM;gBACJ,CAAC,CAAC,GAAG,KAAK,0BAA0B,IAAI,YAAY,KAAK,gBAAgB;gBACzE,CAAC,CAAC,GAAG,KAAK,KAAK,KAAK,2CAA2C,IAAI,IAAI,CAC1E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,EAAE,QAAQ,IAAI,EAAE,CAAC;IAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;IAC7C,MAAM,aAAa,GAAG,IAAI,GAAG,EAA0C,CAAC;IACxE,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAA,iCAAe,EAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACxD,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,aAAa,EAClC,GAAG,KAAK,mBAAmB,GAAG,sBAAsB,CACrD,CAAC;QACJ,CAAC;QACD,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,GAAG,CAC1B,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,iCAAe,EAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAC3D,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CACjD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAC5B,CAAC;IACF,MAAM,aAAa,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,aAAa,EAClC,GAAG,KAAK,oDAAoD;YAC1D,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC;gBACvB,CAAC,CAAC,gCAAgC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC5D,CAAC,CAAC,EAAE,CAAC;YACP,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;gBACpB,CAAC,CAAC,gCAAgC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACzD,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CACN,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAC5B,IAAA,iCAAe,EAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAClB,CAAC;QACpC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9E,MAAM,KAAK,GAAG;YACZ,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;iBAC7E,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,cAAc,IAAI,cAAc,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,QAAQ,GAAG,CAAC;YACzG,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;iBACpE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,kBAAkB,CAAC;SAC5C,CAAC;QACF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,aAAa,EAClC,GAAG,KAAK,mBAAmB,IAAA,iCAAe,EAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,cAAc;gBAC1F,+BAA+B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACrD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAuB,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACxD,MAAM,aAAa,GAAG,QAAQ;aAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,IAAI,CAAC;aACzC,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,aAAa,CAAC,GAAG,CACf,IAAA,iCAAe,EAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CACJ,CACtC,CAAC;QACJ,IACE,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,kCAA0B,CAAC,KAAK,CAAC;YACvD,aAAa,CAAC,MAAM,KAAK,CAAC,EAC1B,CAAC;YACD,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,aAAa,EAClC,GAAG,KAAK,gBAAgB,KAAK,CAAC,IAAI,uDAAuD,CAC1F,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,SAAS,EAAE,IAAA,yBAAc,EAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC;YACtD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;YACxC,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;SAC5C,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;QAC7B,aAAa,EAAE,MAAM,CAAC,MAAM,CAC1B,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACzC,MAAM,CAAC,MAAM,CAAC;YACZ,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ,KAAK,IAAI;SAC9B,CAAC,CACH,CACF;QACD,GAAG,CAAC,OAAO,CAAC,aAAa,KAAK,SAAS;YACrC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE;YAC1C,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS;YAClC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE;YACpC,CAAC,CAAC,EAAE,CAAC;QACP,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;YACxC,GAAG,CAAC,OAAO,CAAC,0BAA0B,IAAI,EAAE,CAAC;SAC9C,CAAC;QACF,oBAAoB,EAAE,MAAM,CAAC,MAAM,CAAC;YAClC,GAAG,CAAC,OAAO,CAAC,oBAAoB,IAAI,EAAE,CAAC;SACxC,CAAC;QACF,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS;YACpC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE;YACxC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;KACrD,CAAC,CAAC;AACL,CAAC;AAkDD,SAAgB,oBAAoB,CAAC,OAKpC;IACC,MAAM,YAAY,GAAG,IAAA,8BAAiB,EAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CACxC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CACtF,CAAC;IACF,MAAM,cAAc,GAAG,IAAI,GAAG,EAA+B,CAAC;IAC9D,MAAM,SAAS,GAAG,IAAI,GAAG,EAA4C,CAAC;IACtE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACtC,SAAS,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,YAAY,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QACzE,CAAC;QACD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC;IACvC,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,gBAAgB,EACrC,2FAA2F;YACzF,4FAA4F,CAC/F,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAA,iCAAe,EAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAClF,CAAC;IACF,MAAM,WAAW,GAAG,CAAC,OAAe,EAAU,EAAE;QAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,oBAAoB,EACzC,wBAAwB,OAAO,mDAAmD,CACnF,CAAC;QACJ,CAAC;QACD,OAAO,IAAA,0CAA+B,EACpC,YAAY,EACZ,IAAA,qCAAkB,EAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CACzD,CAAC;IACJ,CAAC,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACtC,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACvD,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;gBACvC,MAAM,GAAG,GAAG,IAAA,iCAAe,EAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBACxD,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAClC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;oBAG1B,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;oBACnC,SAAS;gBACX,CAAC;gBACD,IACE,OAAO,CAAC,aAAa,KAAK,GAAG,CAAC,OAAO;oBACrC,OAAO,CAAC,iBAAiB,KAAK,GAAG,CAAC,YAAY;oBAC9C,OAAO,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,EACrC,CAAC;oBACD,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,oBAAoB,EACzC,GAAG,SAAS,aAAa,GAAG,OAAO,KAAK,CAAC,SAAS,6BAA6B;wBAC7E,GAAG,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,iBAAiB,OAAO,OAAO,CAAC,SAAS,GAAG,CACnF,CAAC;gBACJ,CAAC;gBACD,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QACD,MAAM,GAAG,GAA2B,EAAE,CAAC;QACvC,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;YACpC,MAAM,GAAG,GAAG,IAAA,iCAAe,EAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YACtD,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpE,IAAI,GAAG,CAAC,QAAQ,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;oBAC1C,SAAS;gBACX,CAAC;gBACD,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,kBAAkB,EACvC,GAAG,SAAS,2BAA2B,GAAG,iBAAiB;oBACzD,CAAC,OAAO,KAAK,SAAS;wBACpB,CAAC,CAAC,2BAA2B;wBAC7B,CAAC,CAAC,uBAAuB,GAAG,CAAC,OAAO,uBAAuB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAC/F,CAAC;YACJ,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,GAAG,IAAA,4BAAiB,EAAC,YAAY,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACvE,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC;AACvC,CAAC;AAyCM,KAAK,UAAU,mBAAmB,CACvC,OAAmC;IAEnC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAChC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,gBAAgB,EACrC,oDAAoD,CACrD,CAAC;IACJ,CAAC;IACD,MAAM,YAAY,GAAG,IAAA,8BAAiB,EAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAA,yDAA6B,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/D,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC5C,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACvD,IAAI,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,kBAAkB,EACvC,GAAG,SAAS,qBAAqB,CAClC,CAAC;QACJ,CAAC;QACD,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1B,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YAC/B,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;gBACpC,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,kBAAkB,EACvC,cAAc,KAAK,CAAC,SAAS,yCAAyC,CACvE,CAAC;YACJ,CAAC;YACD,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAClC,CAAC;QACD,MAAM,MAAM,GAAG,IAAA,qCAAkB,EAC/B,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,MAAM,EACV,OAAO,CAAC,WAAW,CACpB,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,CAAC,iBAAiB,EACtC,2EAA2E;YACzE,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;YACpE,GAAG,CACN,CAAC;IACJ,CAAC;IACD,MAAM,WAAW,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAW,CAAC;IACrD,MAAM,SAAS,GAAG,IAAA,0CAA+B,EAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAC7E,MAAM,KAAK,GAAG,oBAAoB,CAAC;QACjC,YAAY;QACZ,WAAW;QACX,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9D,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAClD,KAAK,UAAU,SAAS,CACtB,GAA0B,EAC1B,QAAsC;QAEtC,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,YAAY,IAAI,QAAQ,EAAE,CAAC;QAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,IAAA,gCAAuB,EAAC,GAAG,CAAC,aAAuB,EAAE;YACxE,0BAA0B,EAAE;gBAC1B,2BAA2B,CAAC,QAAQ,CAAC;gBACrC,GAAG,GAAG,CAAC,0BAA0B;aAClC;YACD,cAAc,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CACjC,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,YAAY,EAAE,CACD;SACtC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,OAAO,GAA0B,EAAE,CAAC;IAC1C,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YAC/B,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAC3C,kCAA0B,CAAC,SAAS,CACrC,CAAC;YACF,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAC5C,kCAA0B,CAAC,UAAU,CACtC,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,IAAA,wCAAqB,EAAC;gBACzC,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,SAAS;gBACT,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,OAAO;gBACP,QAAQ,EAAE,IAAA,yCAAsB,EAC9B,qBAAqB,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,YAAY,EAAE,EACtD,SAAS,EACT,KAAK,CAAC,SAAS,CAChB;gBACD,GAAG,CAAC,eAAe;oBACjB,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE;oBAC1D,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrE,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC;oBAChC,CAAC,CAAC;wBACE,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3C,CAAC,CAAC,IAAI,CAAC;4BACL,uBAAuB,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAC/C,IAAA,iCAAe,EAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CACf;yBACzB,CAAC,CACH;qBACF;oBACH,CAAC,CAAC,EAAE,CAAC;gBACP,oBAAoB,EAAE;oBACpB,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,oCAA4B,CAAC,GAAG;wBACrD,CAAC,CAAC,CAAC,yCAA8B,CAAC;wBAClC,CAAC,CAAC,EAAE,CAAC;oBACP,GAAG,GAAG,CAAC,oBAAoB;iBAC5B;gBACD,GAAG,CAAC,GAAG,CAAC,YAAY,KAAK,SAAS;oBAChC,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,EAAE;oBACpC,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxD,GAAG,GAAG,CAAC,MAAM;aACd,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CACV,MAAM,CAAC,MAAM,CAAC;gBACZ,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,YAAY,EAAE,GAAG,CAAC,YAAY;gBAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,MAAM;aACP,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC;IAED,SAAS,QAAQ;QACf,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;YACjC,IAAI,MAAM,CAAC,QAAQ,EAAE,KAAK,SAAS,EAAE,CAAC;gBACpC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,UAAU,GAAG;QAChB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,EAAE,CAAC;YACX,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,WAAW;QACX,SAAS;QACT,OAAO;QACP,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;QAC/B,GAAG;QACH,QAAQ;KACT,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface BoundedRetryPolicy {
|
|
2
|
+
readonly attempts: number;
|
|
3
|
+
readonly initialDelayMs: number;
|
|
4
|
+
readonly maxDelayMs: number;
|
|
5
|
+
}
|
|
6
|
+
export declare const DEFAULT_BOUNDED_RETRY_POLICY: BoundedRetryPolicy;
|
|
7
|
+
export interface RetryClock {
|
|
8
|
+
now(): number;
|
|
9
|
+
setTimeout(callback: () => void, ms: number): unknown;
|
|
10
|
+
clearTimeout(handle: unknown): void;
|
|
11
|
+
}
|
|
12
|
+
export declare const SYSTEM_CLOCK: RetryClock;
|
|
13
|
+
export declare function backoffDelayMs(policy: BoundedRetryPolicy, failedAttempt: number): number;
|
|
14
|
+
export declare function sleep(clock: RetryClock, ms: number): Promise<void>;
|
|
15
|
+
export declare class BoundedRetryExhaustedError extends Error {
|
|
16
|
+
readonly operation: string;
|
|
17
|
+
readonly attempts: number;
|
|
18
|
+
constructor(operation: string, attempts: number, cause: unknown);
|
|
19
|
+
}
|
|
20
|
+
export declare function assertBoundedRetryPolicy(policy: BoundedRetryPolicy): void;
|
|
21
|
+
export declare function withBoundedRetry<T>(operationName: string, operation: () => Promise<T>, policy: BoundedRetryPolicy, clock: RetryClock, onAttemptFailed?: (attempt: number, error: unknown, nextDelayMs: number) => void): Promise<T>;
|
|
22
|
+
//# sourceMappingURL=bounded-retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-retry.d.ts","sourceRoot":"","sources":["../../src/lib/bounded-retry.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IAEjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAEhC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAGD,eAAO,MAAM,4BAA4B,EAAE,kBAI1C,CAAC;AAGF,MAAM,WAAW,UAAU;IACzB,GAAG,IAAI,MAAM,CAAC;IACd,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACtD,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CACrC;AAED,eAAO,MAAM,YAAY,EAAE,UAU1B,CAAC;AAEF,wBAAgB,cAAc,CAAC,MAAM,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAExF;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlE;AAGD,qBAAa,0BAA2B,SAAQ,KAAK;IAEjD,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM;gBADhB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EACzB,KAAK,EAAE,OAAO;CAUjB;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAOzE;AAOD,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,UAAU,EACjB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,GAC/E,OAAO,CAAC,CAAC,CAAC,CAeZ"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BoundedRetryExhaustedError = exports.SYSTEM_CLOCK = exports.DEFAULT_BOUNDED_RETRY_POLICY = void 0;
|
|
4
|
+
exports.backoffDelayMs = backoffDelayMs;
|
|
5
|
+
exports.sleep = sleep;
|
|
6
|
+
exports.assertBoundedRetryPolicy = assertBoundedRetryPolicy;
|
|
7
|
+
exports.withBoundedRetry = withBoundedRetry;
|
|
8
|
+
exports.DEFAULT_BOUNDED_RETRY_POLICY = {
|
|
9
|
+
attempts: 6,
|
|
10
|
+
initialDelayMs: 1_000,
|
|
11
|
+
maxDelayMs: 15_000,
|
|
12
|
+
};
|
|
13
|
+
exports.SYSTEM_CLOCK = {
|
|
14
|
+
now: () => Date.now(),
|
|
15
|
+
setTimeout: (callback, ms) => {
|
|
16
|
+
const handle = setTimeout(callback, ms);
|
|
17
|
+
handle.unref();
|
|
18
|
+
return handle;
|
|
19
|
+
},
|
|
20
|
+
clearTimeout: (handle) => clearTimeout(handle),
|
|
21
|
+
};
|
|
22
|
+
function backoffDelayMs(policy, failedAttempt) {
|
|
23
|
+
return Math.min(policy.maxDelayMs, policy.initialDelayMs * 2 ** (failedAttempt - 1));
|
|
24
|
+
}
|
|
25
|
+
function sleep(clock, ms) {
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
clock.setTimeout(resolve, ms);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
class BoundedRetryExhaustedError extends Error {
|
|
31
|
+
operation;
|
|
32
|
+
attempts;
|
|
33
|
+
constructor(operation, attempts, cause) {
|
|
34
|
+
super(`${operation} failed after ${attempts} attempt(s): ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
35
|
+
this.operation = operation;
|
|
36
|
+
this.attempts = attempts;
|
|
37
|
+
this.name = 'BoundedRetryExhaustedError';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.BoundedRetryExhaustedError = BoundedRetryExhaustedError;
|
|
41
|
+
function assertBoundedRetryPolicy(policy) {
|
|
42
|
+
if (!Number.isInteger(policy.attempts) || policy.attempts < 1) {
|
|
43
|
+
throw new Error(`Bounded retry attempts must be an integer >= 1 (got ${policy.attempts}).`);
|
|
44
|
+
}
|
|
45
|
+
if (policy.initialDelayMs < 0 || policy.maxDelayMs < policy.initialDelayMs) {
|
|
46
|
+
throw new Error('Bounded retry delays must satisfy 0 <= initialDelayMs <= maxDelayMs.');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function withBoundedRetry(operationName, operation, policy, clock, onAttemptFailed) {
|
|
50
|
+
assertBoundedRetryPolicy(policy);
|
|
51
|
+
let lastError;
|
|
52
|
+
for (let attempt = 1; attempt <= policy.attempts; attempt += 1) {
|
|
53
|
+
try {
|
|
54
|
+
return await operation();
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
lastError = error;
|
|
58
|
+
if (attempt === policy.attempts)
|
|
59
|
+
break;
|
|
60
|
+
const delay = backoffDelayMs(policy, attempt);
|
|
61
|
+
onAttemptFailed?.(attempt, error, delay);
|
|
62
|
+
await sleep(clock, delay);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
throw new BoundedRetryExhaustedError(operationName, policy.attempts, lastError);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=bounded-retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-retry.js","sourceRoot":"","sources":["../../src/lib/bounded-retry.ts"],"names":[],"mappings":";;;AAyCA,wCAEC;AAED,sBAIC;AAmBD,4DAOC;AAOD,4CAqBC;AAvFY,QAAA,4BAA4B,GAAuB;IAC9D,QAAQ,EAAE,CAAC;IACX,cAAc,EAAE,KAAK;IACrB,UAAU,EAAE,MAAM;CACnB,CAAC;AASW,QAAA,YAAY,GAAe;IACtC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;IACrB,UAAU,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAGxC,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAuC,CAAC;CAChF,CAAC;AAEF,SAAgB,cAAc,CAAC,MAA0B,EAAE,aAAqB;IAC9E,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,cAAc,GAAG,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,SAAgB,KAAK,CAAC,KAAiB,EAAE,EAAU;IACjD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC;AAGD,MAAa,0BAA2B,SAAQ,KAAK;IAExC;IACA;IAFX,YACW,SAAiB,EACjB,QAAgB,EACzB,KAAc;QAEd,KAAK,CACH,GAAG,SAAS,iBAAiB,QAAQ,gBACnC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,EACF,EAAE,KAAK,EAAE,CACV,CAAC;QATO,cAAS,GAAT,SAAS,CAAQ;QACjB,aAAQ,GAAR,QAAQ,CAAQ;QASzB,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAdD,gEAcC;AAED,SAAgB,wBAAwB,CAAC,MAA0B;IACjE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,uDAAuD,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,MAAM,CAAC,cAAc,GAAG,CAAC,IAAI,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;IAC1F,CAAC;AACH,CAAC;AAOM,KAAK,UAAU,gBAAgB,CACpC,aAAqB,EACrB,SAA2B,EAC3B,MAA0B,EAC1B,KAAiB,EACjB,eAAgF;IAEhF,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,SAAkB,CAAC;IACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QAC/D,IAAI,CAAC;YACH,OAAO,MAAM,SAAS,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,CAAC;YAClB,IAAI,OAAO,KAAK,MAAM,CAAC,QAAQ;gBAAE,MAAM;YACvC,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC9C,eAAe,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YACzC,MAAM,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,MAAM,IAAI,0BAA0B,CAAC,aAAa,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAClF,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type AccessTokenSource } from './access-token';
|
|
2
|
+
export interface ClientCredentialsOptions {
|
|
3
|
+
readonly tokenEndpoint: string;
|
|
4
|
+
readonly clientId: string;
|
|
5
|
+
readonly clientSecretFile: string;
|
|
6
|
+
readonly audience: string;
|
|
7
|
+
readonly requestTimeoutMs?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ClientCredentialsDeps {
|
|
10
|
+
readonly fetch?: typeof fetch;
|
|
11
|
+
readonly readSecretFile?: (path: string) => Promise<string>;
|
|
12
|
+
readonly now?: () => number;
|
|
13
|
+
}
|
|
14
|
+
export declare class ClientCredentialsTokenError extends Error {
|
|
15
|
+
readonly status: number | undefined;
|
|
16
|
+
constructor(message: string, options?: {
|
|
17
|
+
status?: number;
|
|
18
|
+
cause?: unknown;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export declare function createClientCredentialsTokenSource(options: ClientCredentialsOptions, deps?: ClientCredentialsDeps): AccessTokenSource;
|
|
22
|
+
export declare function validateClientCredentialsOptions(options: ClientCredentialsOptions): void;
|
|
23
|
+
//# sourceMappingURL=client-credentials-token-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-credentials-token-source.d.ts","sourceRoot":"","sources":["../../src/lib/client-credentials-token-source.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,gBAAgB,CAAC;AAYxB,MAAM,WAAW,wBAAwB;IAEvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAK1B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAOlC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAGD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IAC9B,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAKD,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;gBAExB,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAKhF;AAWD,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,wBAAwB,EACjC,IAAI,GAAE,qBAA0B,GAC/B,iBAAiB,CAsCnB;AAuDD,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,CAmBxF"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ClientCredentialsTokenError = void 0;
|
|
4
|
+
exports.createClientCredentialsTokenSource = createClientCredentialsTokenSource;
|
|
5
|
+
exports.validateClientCredentialsOptions = validateClientCredentialsOptions;
|
|
6
|
+
const promises_1 = require("node:fs/promises");
|
|
7
|
+
const access_token_1 = require("./access-token");
|
|
8
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 10_000;
|
|
9
|
+
class ClientCredentialsTokenError extends Error {
|
|
10
|
+
status;
|
|
11
|
+
constructor(message, options = {}) {
|
|
12
|
+
super(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
13
|
+
this.name = 'ClientCredentialsTokenError';
|
|
14
|
+
this.status = options.status;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.ClientCredentialsTokenError = ClientCredentialsTokenError;
|
|
18
|
+
function createClientCredentialsTokenSource(options, deps = {}) {
|
|
19
|
+
validateClientCredentialsOptions(options);
|
|
20
|
+
const doFetch = deps.fetch ?? fetch;
|
|
21
|
+
const readSecret = deps.readSecretFile ?? ((path) => (0, promises_1.readFile)(path, 'utf8'));
|
|
22
|
+
const now = deps.now ?? Date.now;
|
|
23
|
+
const timeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
24
|
+
return async () => {
|
|
25
|
+
const secret = (await readSecret(options.clientSecretFile)).trim();
|
|
26
|
+
if (secret.length === 0) {
|
|
27
|
+
throw new ClientCredentialsTokenError(`Temporal client secret file ${options.clientSecretFile} is empty.`);
|
|
28
|
+
}
|
|
29
|
+
const sentAt = now();
|
|
30
|
+
const response = await doFetch(options.tokenEndpoint, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
headers: {
|
|
33
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
34
|
+
Accept: 'application/json',
|
|
35
|
+
},
|
|
36
|
+
body: new URLSearchParams({
|
|
37
|
+
grant_type: 'client_credentials',
|
|
38
|
+
client_id: options.clientId,
|
|
39
|
+
client_secret: secret,
|
|
40
|
+
}).toString(),
|
|
41
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
42
|
+
});
|
|
43
|
+
const text = await response.text();
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw new ClientCredentialsTokenError(`Temporal token request for client ${options.clientId} was refused ` +
|
|
46
|
+
`(HTTP ${response.status}): ${text.slice(0, 300)}`, { status: response.status });
|
|
47
|
+
}
|
|
48
|
+
return parseTokenResponse(text, options, sentAt);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function parseTokenResponse(text, options, sentAt) {
|
|
52
|
+
let body;
|
|
53
|
+
try {
|
|
54
|
+
body = JSON.parse(text);
|
|
55
|
+
}
|
|
56
|
+
catch (cause) {
|
|
57
|
+
throw new ClientCredentialsTokenError(`Temporal token response for client ${options.clientId} is not JSON.`, { cause });
|
|
58
|
+
}
|
|
59
|
+
const record = (typeof body === 'object' && body !== null ? body : {});
|
|
60
|
+
const value = record['access_token'];
|
|
61
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
62
|
+
throw new ClientCredentialsTokenError(`Temporal token response for client ${options.clientId} carries no access_token.`);
|
|
63
|
+
}
|
|
64
|
+
const claims = (0, access_token_1.decodeAccessTokenClaims)(value);
|
|
65
|
+
if (!claims.aud.includes(options.audience)) {
|
|
66
|
+
throw new ClientCredentialsTokenError(`Temporal token for client ${options.clientId} does not carry the required ` +
|
|
67
|
+
`audience "${options.audience}" (aud=${JSON.stringify(claims.aud)}). ` +
|
|
68
|
+
'The frontend would refuse it; the issuer-side audience mapper is missing.');
|
|
69
|
+
}
|
|
70
|
+
const expiresIn = record['expires_in'];
|
|
71
|
+
let expiresAt;
|
|
72
|
+
if (typeof expiresIn === 'number' && expiresIn > 0) {
|
|
73
|
+
expiresAt = sentAt + expiresIn * 1000;
|
|
74
|
+
}
|
|
75
|
+
else if (claims.exp !== undefined) {
|
|
76
|
+
expiresAt = claims.exp * 1000;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
throw new ClientCredentialsTokenError(`Temporal token for client ${options.clientId} has neither expires_in nor exp; ` +
|
|
80
|
+
'its refresh cannot be scheduled.');
|
|
81
|
+
}
|
|
82
|
+
if (expiresAt <= sentAt) {
|
|
83
|
+
throw new ClientCredentialsTokenError(`Temporal token for client ${options.clientId} was already expired when issued.`);
|
|
84
|
+
}
|
|
85
|
+
return { value, expiresAt };
|
|
86
|
+
}
|
|
87
|
+
function validateClientCredentialsOptions(options) {
|
|
88
|
+
let url;
|
|
89
|
+
try {
|
|
90
|
+
url = new URL(options.tokenEndpoint);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
throw new Error(`Temporal token endpoint is not a URL: ${options.tokenEndpoint}`);
|
|
94
|
+
}
|
|
95
|
+
if (url.protocol !== 'https:' && url.protocol !== 'http:') {
|
|
96
|
+
throw new Error(`Temporal token endpoint must be http(s): ${options.tokenEndpoint}`);
|
|
97
|
+
}
|
|
98
|
+
for (const [name, value] of [
|
|
99
|
+
['clientId', options.clientId],
|
|
100
|
+
['clientSecretFile', options.clientSecretFile],
|
|
101
|
+
['audience', options.audience],
|
|
102
|
+
]) {
|
|
103
|
+
if (value.trim().length === 0) {
|
|
104
|
+
throw new Error(`Temporal client credentials: ${name} is required.`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=client-credentials-token-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-credentials-token-source.js","sourceRoot":"","sources":["../../src/lib/client-credentials-token-source.ts"],"names":[],"mappings":"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"}
|