@blokjs/trigger-worker 0.2.1 → 0.4.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/dist/WorkerTrigger.d.ts +3 -3
- package/dist/WorkerTrigger.js +132 -21
- package/dist/adapters/BullMQAdapter.d.ts +1 -1
- package/dist/adapters/BullMQAdapter.js +5 -42
- package/dist/adapters/InMemoryAdapter.d.ts +1 -1
- package/dist/adapters/InMemoryAdapter.js +4 -8
- package/dist/adapters/NATSAdapter.d.ts +110 -0
- package/dist/adapters/NATSAdapter.js +394 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +8 -13
- package/package.json +9 -5
- package/src/WorkerTrigger.test.ts +44 -14
- package/src/WorkerTrigger.ts +147 -6
- package/src/adapters/NATSAdapter.ts +452 -0
- package/src/index.ts +1 -0
- package/template/.env.example +13 -0
- package/template/package.json +45 -0
- package/template/src/Nodes.ts +10 -0
- package/template/src/Workflows.ts +8 -0
- package/template/src/index.ts +41 -0
- package/template/src/runner/WorkerServer.ts +34 -0
- package/template/src/runner/types/Workflows.ts +7 -0
- package/template/src/workflows/jobs/process-job.ts +45 -0
- package/template/tsconfig.json +31 -0
- package/template/vitest.config.ts +39 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NATSAdapter - NATS JetStream worker adapter for WorkerTrigger
|
|
3
|
+
*
|
|
4
|
+
* Uses NATS JetStream for persistent background job processing with:
|
|
5
|
+
* - Pull-based consumers with configurable concurrency
|
|
6
|
+
* - Server-side retry config (max_deliver)
|
|
7
|
+
* - Ack wait for job timeouts
|
|
8
|
+
* - Priority via message headers
|
|
9
|
+
* - Delayed job scheduling
|
|
10
|
+
* - Queue statistics via consumer info
|
|
11
|
+
*
|
|
12
|
+
* Requires: npm install nats
|
|
13
|
+
*
|
|
14
|
+
* Environment variables:
|
|
15
|
+
* - NATS_SERVERS: Comma-separated NATS server URLs (default: localhost:4222)
|
|
16
|
+
* - NATS_TOKEN: Authentication token (optional)
|
|
17
|
+
* - NATS_USER: Username for auth (optional)
|
|
18
|
+
* - NATS_PASS: Password for auth (optional)
|
|
19
|
+
* - NATS_STREAM_NAME: JetStream stream name (default: blok-worker)
|
|
20
|
+
*/
|
|
21
|
+
import { v4 as uuid } from "uuid";
|
|
22
|
+
/**
|
|
23
|
+
* Tier 2 polish — compute the consumer-side hold time for a NATS message
|
|
24
|
+
* with an `x-delay` header. NATS JetStream stores `x-delay` as opaque
|
|
25
|
+
* metadata; the broker does NOT defer delivery on it. The consumer is
|
|
26
|
+
* responsible for honouring the delay between the message's first-publish
|
|
27
|
+
* timestamp and `createdMs + delay`.
|
|
28
|
+
*
|
|
29
|
+
* Returns the milliseconds to wait. Clamps to >= 0; returns 0 when the
|
|
30
|
+
* delay has already elapsed (the message was queued for longer than the
|
|
31
|
+
* delay) or when no delay was set.
|
|
32
|
+
*
|
|
33
|
+
* Exported for unit testability — the consumer message handler in
|
|
34
|
+
* `NATSWorkerAdapter.process()` mocks the NATS client extensively, so
|
|
35
|
+
* isolating the math here keeps the surface easy to verify.
|
|
36
|
+
*/
|
|
37
|
+
export function computeXDelayHoldMs(delay, createdMs, nowMs) {
|
|
38
|
+
if (!delay || delay <= 0)
|
|
39
|
+
return 0;
|
|
40
|
+
const dispatchAt = createdMs + delay;
|
|
41
|
+
return Math.max(0, dispatchAt - nowMs);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* NATSWorkerAdapter - NATS JetStream implementation of WorkerAdapter
|
|
45
|
+
*/
|
|
46
|
+
export class NATSWorkerAdapter {
|
|
47
|
+
provider = "nats";
|
|
48
|
+
// biome-ignore lint/suspicious/noExplicitAny: NATS types are dynamically imported (optional peer dependency)
|
|
49
|
+
nc = null;
|
|
50
|
+
// biome-ignore lint/suspicious/noExplicitAny: NATS types are dynamically imported
|
|
51
|
+
js = null;
|
|
52
|
+
// biome-ignore lint/suspicious/noExplicitAny: NATS types are dynamically imported
|
|
53
|
+
jsm = null;
|
|
54
|
+
connected = false;
|
|
55
|
+
config;
|
|
56
|
+
// biome-ignore lint/suspicious/noExplicitAny: NATS consumer instances
|
|
57
|
+
consumers = new Map();
|
|
58
|
+
// biome-ignore lint/suspicious/noExplicitAny: NATS consume iterators
|
|
59
|
+
consumeIterators = new Map();
|
|
60
|
+
constructor(config) {
|
|
61
|
+
this.config = {
|
|
62
|
+
servers: config?.servers || (process.env.NATS_SERVERS || "localhost:4222").split(","),
|
|
63
|
+
token: config?.token || process.env.NATS_TOKEN,
|
|
64
|
+
user: config?.user || process.env.NATS_USER,
|
|
65
|
+
pass: config?.pass || process.env.NATS_PASS,
|
|
66
|
+
streamName: config?.streamName || process.env.NATS_STREAM_NAME || "blok-worker",
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Connect to NATS and initialize JetStream
|
|
71
|
+
*/
|
|
72
|
+
async connect() {
|
|
73
|
+
if (this.connected)
|
|
74
|
+
return;
|
|
75
|
+
try {
|
|
76
|
+
const nats = await import("nats");
|
|
77
|
+
const connectOpts = {
|
|
78
|
+
servers: this.config.servers,
|
|
79
|
+
};
|
|
80
|
+
if (this.config.token)
|
|
81
|
+
connectOpts.token = this.config.token;
|
|
82
|
+
if (this.config.user)
|
|
83
|
+
connectOpts.user = this.config.user;
|
|
84
|
+
if (this.config.pass)
|
|
85
|
+
connectOpts.pass = this.config.pass;
|
|
86
|
+
this.nc = await nats.connect(connectOpts);
|
|
87
|
+
this.js = this.nc.jetstream();
|
|
88
|
+
this.jsm = await this.nc.jetstreamManager();
|
|
89
|
+
this.connected = true;
|
|
90
|
+
console.log(`[NATSWorkerAdapter] Connected to NATS: ${this.config.servers.join(", ")}`);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
throw new Error(`Failed to connect to NATS: ${error.message}. Make sure nats is installed: npm install nats`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Disconnect from NATS
|
|
98
|
+
*/
|
|
99
|
+
async disconnect() {
|
|
100
|
+
if (!this.connected)
|
|
101
|
+
return;
|
|
102
|
+
try {
|
|
103
|
+
// Stop all consume iterators
|
|
104
|
+
for (const [, iter] of this.consumeIterators) {
|
|
105
|
+
try {
|
|
106
|
+
iter.stop();
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Iterator may already be stopped
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
this.consumeIterators.clear();
|
|
113
|
+
this.consumers.clear();
|
|
114
|
+
await this.nc.drain();
|
|
115
|
+
this.connected = false;
|
|
116
|
+
console.log("[NATSWorkerAdapter] Disconnected from NATS");
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
console.error(`[NATSWorkerAdapter] Disconnect error: ${error.message}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Start processing jobs from a queue
|
|
124
|
+
*/
|
|
125
|
+
async process(config, handler) {
|
|
126
|
+
if (!this.connected) {
|
|
127
|
+
throw new Error("Not connected. Call connect() first.");
|
|
128
|
+
}
|
|
129
|
+
const nats = await import("nats");
|
|
130
|
+
const queue = config.queue;
|
|
131
|
+
const streamName = this.config.streamName || "blok-worker";
|
|
132
|
+
const subject = `worker.${queue}`;
|
|
133
|
+
const durableName = `blok-worker-${queue}`;
|
|
134
|
+
// Ensure stream exists with worker subjects
|
|
135
|
+
await this.ensureStream(streamName, [subject]);
|
|
136
|
+
// Create or update durable pull consumer with worker semantics
|
|
137
|
+
const ackWaitNs = ((config.timeout ?? 30000) + 5000) * 1_000_000; // timeout + 5s buffer, in nanoseconds
|
|
138
|
+
await this.jsm.consumers.add(streamName, {
|
|
139
|
+
durable_name: durableName,
|
|
140
|
+
ack_policy: nats.AckPolicy.Explicit,
|
|
141
|
+
max_deliver: (config.retries ?? 3) + 1, // +1 because first attempt counts
|
|
142
|
+
ack_wait: ackWaitNs,
|
|
143
|
+
filter_subjects: [subject],
|
|
144
|
+
});
|
|
145
|
+
// Get consumer handle
|
|
146
|
+
const consumer = await this.js.consumers.get(streamName, durableName);
|
|
147
|
+
this.consumers.set(queue, consumer);
|
|
148
|
+
// Start consuming
|
|
149
|
+
const iter = await consumer.consume();
|
|
150
|
+
this.consumeIterators.set(queue, iter);
|
|
151
|
+
// Process jobs in background
|
|
152
|
+
(async () => {
|
|
153
|
+
const semaphore = new Semaphore(config.concurrency ?? 1);
|
|
154
|
+
for await (const msg of iter) {
|
|
155
|
+
await semaphore.acquire();
|
|
156
|
+
// Process each job concurrently up to concurrency limit
|
|
157
|
+
(async () => {
|
|
158
|
+
try {
|
|
159
|
+
// Parse job data
|
|
160
|
+
let data;
|
|
161
|
+
try {
|
|
162
|
+
const codec = nats.JSONCodec();
|
|
163
|
+
data = codec.decode(msg.data);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
try {
|
|
167
|
+
const sc = nats.StringCodec();
|
|
168
|
+
data = JSON.parse(sc.decode(msg.data));
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
data = msg.data;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Extract headers
|
|
175
|
+
const headers = {};
|
|
176
|
+
if (msg.headers) {
|
|
177
|
+
for (const [key, values] of msg.headers) {
|
|
178
|
+
headers[key] = Array.isArray(values) ? values[0] : values;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Extract job metadata from headers
|
|
182
|
+
const jobId = headers["x-job-id"] || msg.headers?.get("Nats-Msg-Id") || uuid();
|
|
183
|
+
const priority = Number.parseInt(headers["x-priority"] || "0", 10);
|
|
184
|
+
const delay = Number.parseInt(headers["x-delay"] || "0", 10);
|
|
185
|
+
const timeout = Number.parseInt(headers["x-timeout"] || "0", 10);
|
|
186
|
+
// Get redelivery count (attempts)
|
|
187
|
+
const info = msg.info;
|
|
188
|
+
const attempts = info.redeliveryCount ?? 0;
|
|
189
|
+
const maxRetries = config.retries ?? 3;
|
|
190
|
+
// Create WorkerJob
|
|
191
|
+
const workerJob = {
|
|
192
|
+
id: jobId,
|
|
193
|
+
data,
|
|
194
|
+
headers,
|
|
195
|
+
queue,
|
|
196
|
+
priority,
|
|
197
|
+
attempts,
|
|
198
|
+
maxRetries,
|
|
199
|
+
createdAt: new Date(info.timestampNanos ? Number(info.timestampNanos / BigInt(1_000_000)) : Date.now()),
|
|
200
|
+
delay: delay || undefined,
|
|
201
|
+
timeout: timeout || config.timeout || undefined,
|
|
202
|
+
raw: msg,
|
|
203
|
+
complete: async () => {
|
|
204
|
+
msg.ack();
|
|
205
|
+
},
|
|
206
|
+
fail: async (error, requeue) => {
|
|
207
|
+
if (requeue) {
|
|
208
|
+
// nak() tells the server to redeliver
|
|
209
|
+
msg.nak();
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
// term() terminates delivery — no more retries
|
|
213
|
+
msg.term();
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
// Tier 2 polish — enforce `x-delay` header on the consumer side.
|
|
218
|
+
// NATS JetStream stores `x-delay` as opaque metadata; the broker
|
|
219
|
+
// does NOT defer delivery on it. We implement consumer-side
|
|
220
|
+
// holding here. createdMs is the message's first-publish timestamp;
|
|
221
|
+
// hold until createdMs + delay. Single-process semantics — for
|
|
222
|
+
// long deferrals, prefer trigger-level `delay` (DeferredRunScheduler).
|
|
223
|
+
const createdMs = info.timestampNanos ? Number(info.timestampNanos / BigInt(1_000_000)) : Date.now();
|
|
224
|
+
const waitMs = computeXDelayHoldMs(delay, createdMs, Date.now());
|
|
225
|
+
if (waitMs > 0) {
|
|
226
|
+
await new Promise((resolve) => setTimeout(resolve, waitMs));
|
|
227
|
+
}
|
|
228
|
+
await handler(workerJob);
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
console.error(`[NATSWorkerAdapter] Error processing job from ${queue}: ${error.message}`);
|
|
232
|
+
try {
|
|
233
|
+
msg.nak();
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Already acked/nacked
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
semaphore.release();
|
|
241
|
+
}
|
|
242
|
+
})();
|
|
243
|
+
}
|
|
244
|
+
})();
|
|
245
|
+
console.log(`[NATSWorkerAdapter] Processing queue: ${queue} (concurrency=${config.concurrency ?? 1}, retries=${config.retries ?? 3})`);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Add a job to a worker queue
|
|
249
|
+
*/
|
|
250
|
+
async addJob(queue, data, opts) {
|
|
251
|
+
if (!this.connected) {
|
|
252
|
+
throw new Error("Not connected. Call connect() first.");
|
|
253
|
+
}
|
|
254
|
+
const nats = await import("nats");
|
|
255
|
+
const subject = `worker.${queue}`;
|
|
256
|
+
const streamName = this.config.streamName || "blok-worker";
|
|
257
|
+
// Ensure stream has this subject
|
|
258
|
+
await this.ensureStream(streamName, [subject]);
|
|
259
|
+
// Build headers with job metadata
|
|
260
|
+
const hdrs = nats.headers();
|
|
261
|
+
const jobId = opts?.jobId || uuid();
|
|
262
|
+
hdrs.set("x-job-id", jobId);
|
|
263
|
+
hdrs.set("Nats-Msg-Id", jobId); // Deduplication
|
|
264
|
+
if (opts?.priority)
|
|
265
|
+
hdrs.set("x-priority", String(opts.priority));
|
|
266
|
+
if (opts?.delay)
|
|
267
|
+
hdrs.set("x-delay", String(opts.delay));
|
|
268
|
+
if (opts?.timeout)
|
|
269
|
+
hdrs.set("x-timeout", String(opts.timeout));
|
|
270
|
+
// Encode and publish
|
|
271
|
+
const codec = nats.JSONCodec();
|
|
272
|
+
await this.js.publish(subject, codec.encode(data), { headers: hdrs });
|
|
273
|
+
return jobId;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Stop processing a specific queue
|
|
277
|
+
*/
|
|
278
|
+
async stopProcessing(queue) {
|
|
279
|
+
const iter = this.consumeIterators.get(queue);
|
|
280
|
+
if (iter) {
|
|
281
|
+
try {
|
|
282
|
+
iter.stop();
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
// Already stopped
|
|
286
|
+
}
|
|
287
|
+
this.consumeIterators.delete(queue);
|
|
288
|
+
}
|
|
289
|
+
this.consumers.delete(queue);
|
|
290
|
+
console.log(`[NATSWorkerAdapter] Stopped processing queue: ${queue}`);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Check if connected
|
|
294
|
+
*/
|
|
295
|
+
isConnected() {
|
|
296
|
+
return this.connected;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Health check
|
|
300
|
+
*/
|
|
301
|
+
async healthCheck() {
|
|
302
|
+
if (!this.connected || !this.nc)
|
|
303
|
+
return false;
|
|
304
|
+
try {
|
|
305
|
+
const info = this.nc.info;
|
|
306
|
+
return info !== undefined;
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Get queue statistics from JetStream consumer info
|
|
314
|
+
*/
|
|
315
|
+
async getQueueStats(queue) {
|
|
316
|
+
if (!this.connected) {
|
|
317
|
+
return { waiting: 0, active: 0, completed: 0, failed: 0, delayed: 0 };
|
|
318
|
+
}
|
|
319
|
+
try {
|
|
320
|
+
const streamName = this.config.streamName || "blok-worker";
|
|
321
|
+
const durableName = `blok-worker-${queue}`;
|
|
322
|
+
const info = await this.jsm.consumers.info(streamName, durableName);
|
|
323
|
+
return {
|
|
324
|
+
waiting: info.num_pending ?? 0,
|
|
325
|
+
active: info.num_ack_pending ?? 0,
|
|
326
|
+
completed: info.delivered?.consumer_seq ?? 0,
|
|
327
|
+
failed: info.num_redelivered ?? 0,
|
|
328
|
+
delayed: 0, // NATS doesn't have a native delayed count
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
return { waiting: 0, active: 0, completed: 0, failed: 0, delayed: 0 };
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Ensure a JetStream stream exists with the given subjects
|
|
337
|
+
*/
|
|
338
|
+
async ensureStream(name, subjects) {
|
|
339
|
+
try {
|
|
340
|
+
const info = await this.jsm.streams.info(name);
|
|
341
|
+
// Merge new subjects with existing
|
|
342
|
+
const existingSubjects = info.config.subjects || [];
|
|
343
|
+
const allSubjects = [...new Set([...existingSubjects, ...subjects])];
|
|
344
|
+
if (allSubjects.length !== existingSubjects.length) {
|
|
345
|
+
await this.jsm.streams.update(name, {
|
|
346
|
+
...info.config,
|
|
347
|
+
subjects: allSubjects,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
catch {
|
|
352
|
+
// Stream doesn't exist, create it
|
|
353
|
+
await this.jsm.streams.add({
|
|
354
|
+
name,
|
|
355
|
+
subjects,
|
|
356
|
+
// biome-ignore lint/suspicious/noExplicitAny: nats JetStream retention policy enum
|
|
357
|
+
retention: "workqueue",
|
|
358
|
+
max_deliver: 4, // default: 3 retries + 1 initial attempt
|
|
359
|
+
// biome-ignore lint/suspicious/noExplicitAny: nats JetStream storage type enum
|
|
360
|
+
storage: "file",
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Simple semaphore for concurrency control
|
|
367
|
+
*/
|
|
368
|
+
class Semaphore {
|
|
369
|
+
permits;
|
|
370
|
+
waiting = [];
|
|
371
|
+
constructor(permits) {
|
|
372
|
+
this.permits = permits;
|
|
373
|
+
}
|
|
374
|
+
async acquire() {
|
|
375
|
+
if (this.permits > 0) {
|
|
376
|
+
this.permits--;
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
return new Promise((resolve) => {
|
|
380
|
+
this.waiting.push(resolve);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
release() {
|
|
384
|
+
const next = this.waiting.shift();
|
|
385
|
+
if (next) {
|
|
386
|
+
next();
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
this.permits++;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
export default NATSWorkerAdapter;
|
|
394
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTkFUU0FkYXB0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWRhcHRlcnMvTkFUU0FkYXB0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFHSCxPQUFPLEVBQUUsRUFBRSxJQUFJLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUdsQzs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxLQUFhLEVBQUUsU0FBaUIsRUFBRSxLQUFhO0lBQ2xGLElBQUksQ0FBQyxLQUFLLElBQUksS0FBSyxJQUFJLENBQUM7UUFBRSxPQUFPLENBQUMsQ0FBQztJQUNuQyxNQUFNLFVBQVUsR0FBRyxTQUFTLEdBQUcsS0FBSyxDQUFDO0lBQ3JDLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsVUFBVSxHQUFHLEtBQUssQ0FBQyxDQUFDO0FBQ3hDLENBQUM7QUFrQkQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8saUJBQWlCO0lBQ3BCLFFBQVEsR0FBRyxNQUFlLENBQUM7SUFFcEMsNkdBQTZHO0lBQ3JHLEVBQUUsR0FBUSxJQUFJLENBQUM7SUFDdkIsa0ZBQWtGO0lBQzFFLEVBQUUsR0FBUSxJQUFJLENBQUM7SUFDdkIsa0ZBQWtGO0lBQzFFLEdBQUcsR0FBUSxJQUFJLENBQUM7SUFDaEIsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNsQixNQUFNLENBQW1CO0lBQ2pDLHNFQUFzRTtJQUM5RCxTQUFTLEdBQXFCLElBQUksR0FBRyxFQUFFLENBQUM7SUFDaEQscUVBQXFFO0lBQzdELGdCQUFnQixHQUFxQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBRXZELFlBQVksTUFBa0M7UUFDN0MsSUFBSSxDQUFDLE1BQU0sR0FBRztZQUNiLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLElBQUksZ0JBQWdC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RUFBRTtZQUNwQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM1QixDQUFDLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRCxPQUFPO1FBQ04sTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNsQyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ1YsSUFBSSxFQUFFLENBQUM7UUFDUixDQUFDO2FBQU0sQ0FBQztZQUNQLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNoQixDQUFDO0lBQ0YsQ0FBQztDQUNEO0FBRUQsZUFBZSxpQkFBaUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTkFUU0FkYXB0ZXIgLSBOQVRTIEpldFN0cmVhbSB3b3JrZXIgYWRhcHRlciBmb3IgV29ya2VyVHJpZ2dlclxuICpcbiAqIFVzZXMgTkFUUyBKZXRTdHJlYW0gZm9yIHBlcnNpc3RlbnQgYmFja2dyb3VuZCBqb2IgcHJvY2Vzc2luZyB3aXRoOlxuICogLSBQdWxsLWJhc2VkIGNvbnN1bWVycyB3aXRoIGNvbmZpZ3VyYWJsZSBjb25jdXJyZW5jeVxuICogLSBTZXJ2ZXItc2lkZSByZXRyeSBjb25maWcgKG1heF9kZWxpdmVyKVxuICogLSBBY2sgd2FpdCBmb3Igam9iIHRpbWVvdXRzXG4gKiAtIFByaW9yaXR5IHZpYSBtZXNzYWdlIGhlYWRlcnNcbiAqIC0gRGVsYXllZCBqb2Igc2NoZWR1bGluZ1xuICogLSBRdWV1ZSBzdGF0aXN0aWNzIHZpYSBjb25zdW1lciBpbmZvXG4gKlxuICogUmVxdWlyZXM6IG5wbSBpbnN0YWxsIG5hdHNcbiAqXG4gKiBFbnZpcm9ubWVudCB2YXJpYWJsZXM6XG4gKiAtIE5BVFNfU0VSVkVSUzogQ29tbWEtc2VwYXJhdGVkIE5BVFMgc2VydmVyIFVSTHMgKGRlZmF1bHQ6IGxvY2FsaG9zdDo0MjIyKVxuICogLSBOQVRTX1RPS0VOOiBBdXRoZW50aWNhdGlvbiB0b2tlbiAob3B0aW9uYWwpXG4gKiAtIE5BVFNfVVNFUjogVXNlcm5hbWUgZm9yIGF1dGggKG9wdGlvbmFsKVxuICogLSBOQVRTX1BBU1M6IFBhc3N3b3JkIGZvciBhdXRoIChvcHRpb25hbClcbiAqIC0gTkFUU19TVFJFQU1fTkFNRTogSmV0U3RyZWFtIHN0cmVhbSBuYW1lIChkZWZhdWx0OiBibG9rLXdvcmtlcilcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFdvcmtlclRyaWdnZXJPcHRzIH0gZnJvbSBcIkBibG9ranMvaGVscGVyXCI7XG5pbXBvcnQgeyB2NCBhcyB1dWlkIH0gZnJvbSBcInV1aWRcIjtcbmltcG9ydCB0eXBlIHsgV29ya2VyQWRhcHRlciwgV29ya2VySm9iLCBXb3JrZXJRdWV1ZVN0YXRzIH0gZnJvbSBcIi4uL1dvcmtlclRyaWdnZXJcIjtcblxuLyoqXG4gKiBUaWVyIDIgcG9saXNoIOKAlCBjb21wdXRlIHRoZSBjb25zdW1lci1zaWRlIGhvbGQgdGltZSBmb3IgYSBOQVRTIG1lc3NhZ2VcbiAqIHdpdGggYW4gYHgtZGVsYXlgIGhlYWRlci4gTkFUUyBKZXRTdHJlYW0gc3RvcmVzIGB4LWRlbGF5YCBhcyBvcGFxdWVcbiAqIG1ldGFkYXRhOyB0aGUgYnJva2VyIGRvZXMgTk9UIGRlZmVyIGRlbGl2ZXJ5IG9uIGl0LiBUaGUgY29uc3VtZXIgaXNcbiAqIHJlc3BvbnNpYmxlIGZvciBob25vdXJpbmcgdGhlIGRlbGF5IGJldHdlZW4gdGhlIG1lc3NhZ2UncyBmaXJzdC1wdWJsaXNoXG4gKiB0aW1lc3RhbXAgYW5kIGBjcmVhdGVkTXMgKyBkZWxheWAuXG4gKlxuICogUmV0dXJucyB0aGUgbWlsbGlzZWNvbmRzIHRvIHdhaXQuIENsYW1wcyB0byA+PSAwOyByZXR1cm5zIDAgd2hlbiB0aGVcbiAqIGRlbGF5IGhhcyBhbHJlYWR5IGVsYXBzZWQgKHRoZSBtZXNzYWdlIHdhcyBxdWV1ZWQgZm9yIGxvbmdlciB0aGFuIHRoZVxuICogZGVsYXkpIG9yIHdoZW4gbm8gZGVsYXkgd2FzIHNldC5cbiAqXG4gKiBFeHBvcnRlZCBmb3IgdW5pdCB0ZXN0YWJpbGl0eSDigJQgdGhlIGNvbnN1bWVyIG1lc3NhZ2UgaGFuZGxlciBpblxuICogYE5BVFNXb3JrZXJBZGFwdGVyLnByb2Nlc3MoKWAgbW9ja3MgdGhlIE5BVFMgY2xpZW50IGV4dGVuc2l2ZWx5LCBzb1xuICogaXNvbGF0aW5nIHRoZSBtYXRoIGhlcmUga2VlcHMgdGhlIHN1cmZhY2UgZWFzeSB0byB2ZXJpZnkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlWERlbGF5SG9sZE1zKGRlbGF5OiBudW1iZXIsIGNyZWF0ZWRNczogbnVtYmVyLCBub3dNczogbnVtYmVyKTogbnVtYmVyIHtcblx0aWYgKCFkZWxheSB8fCBkZWxheSA8PSAwKSByZXR1cm4gMDtcblx0Y29uc3QgZGlzcGF0Y2hBdCA9IGNyZWF0ZWRNcyArIGRlbGF5O1xuXHRyZXR1cm4gTWF0aC5tYXgoMCwgZGlzcGF0Y2hBdCAtIG5vd01zKTtcbn1cblxuLyoqXG4gKiBOQVRTIHdvcmtlciBhZGFwdGVyIGNvbmZpZ3VyYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBOQVRTV29ya2VyQ29uZmlnIHtcblx0LyoqIE5BVFMgc2VydmVyIFVSTHMgKi9cblx0c2VydmVyczogc3RyaW5nW107XG5cdC8qKiBBdXRoZW50aWNhdGlvbiB0b2tlbiAqL1xuXHR0b2tlbj86IHN0cmluZztcblx0LyoqIFVzZXJuYW1lICovXG5cdHVzZXI/OiBzdHJpbmc7XG5cdC8qKiBQYXNzd29yZCAqL1xuXHRwYXNzPzogc3RyaW5nO1xuXHQvKiogSmV0U3RyZWFtIHN0cmVhbSBuYW1lIChkZWZhdWx0OiBcImJsb2std29ya2VyXCIpICovXG5cdHN0cmVhbU5hbWU/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogTkFUU1dvcmtlckFkYXB0ZXIgLSBOQVRTIEpldFN0cmVhbSBpbXBsZW1lbnRhdGlvbiBvZiBXb3JrZXJBZGFwdGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBOQVRTV29ya2VyQWRhcHRlciBpbXBsZW1lbnRzIFdvcmtlckFkYXB0ZXIge1xuXHRyZWFkb25seSBwcm92aWRlciA9IFwibmF0c1wiIGFzIGNvbnN0O1xuXG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogTkFUUyB0eXBlcyBhcmUgZHluYW1pY2FsbHkgaW1wb3J0ZWQgKG9wdGlvbmFsIHBlZXIgZGVwZW5kZW5jeSlcblx0cHJpdmF0ZSBuYzogYW55ID0gbnVsbDtcblx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBOQVRTIHR5cGVzIGFyZSBkeW5hbWljYWxseSBpbXBvcnRlZFxuXHRwcml2YXRlIGpzOiBhbnkgPSBudWxsO1xuXHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IE5BVFMgdHlwZXMgYXJlIGR5bmFtaWNhbGx5IGltcG9ydGVkXG5cdHByaXZhdGUganNtOiBhbnkgPSBudWxsO1xuXHRwcml2YXRlIGNvbm5lY3RlZCA9IGZhbHNlO1xuXHRwcml2YXRlIGNvbmZpZzogTkFUU1dvcmtlckNvbmZpZztcblx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBOQVRTIGNvbnN1bWVyIGluc3RhbmNlc1xuXHRwcml2YXRlIGNvbnN1bWVyczogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcblx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBOQVRTIGNvbnN1bWUgaXRlcmF0b3JzXG5cdHByaXZhdGUgY29uc3VtZUl0ZXJhdG9yczogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcblxuXHRjb25zdHJ1Y3Rvcihjb25maWc/OiBQYXJ0aWFsPE5BVFNXb3JrZXJDb25maWc+KSB7XG5cdFx0dGhpcy5jb25maWcgPSB7XG5cdFx0XHRzZXJ2ZXJzOiBjb25maWc/LnNlcnZlcnMgfHwgKHByb2Nlc3MuZW52Lk5BVFNfU0VSVkVSUyB8fCBcImxvY2FsaG9zdDo0MjIyXCIpLnNwbGl0KFwiLFwiKSxcblx0XHRcdHRva2VuOiBjb25maWc/LnRva2VuIHx8IHByb2Nlc3MuZW52Lk5BVFNfVE9LRU4sXG5cdFx0XHR1c2VyOiBjb25maWc/LnVzZXIgfHwgcHJvY2Vzcy5lbnYuTkFUU19VU0VSLFxuXHRcdFx0cGFzczogY29uZmlnPy5wYXNzIHx8IHByb2Nlc3MuZW52Lk5BVFNfUEFTUyxcblx0XHRcdHN0cmVhbU5hbWU6IGNvbmZpZz8uc3RyZWFtTmFtZSB8fCBwcm9jZXNzLmVudi5OQVRTX1NUUkVBTV9OQU1FIHx8IFwiYmxvay13b3JrZXJcIixcblx0XHR9O1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbm5lY3QgdG8gTkFUUyBhbmQgaW5pdGlhbGl6ZSBKZXRTdHJlYW1cblx0ICovXG5cdGFzeW5jIGNvbm5lY3QoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0aWYgKHRoaXMuY29ubmVjdGVkKSByZXR1cm47XG5cblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgbmF0cyA9IGF3YWl0IGltcG9ydChcIm5hdHNcIik7XG5cblx0XHRcdGNvbnN0IGNvbm5lY3RPcHRzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcblx0XHRcdFx0c2VydmVyczogdGhpcy5jb25maWcuc2VydmVycyxcblx0XHRcdH07XG5cblx0XHRcdGlmICh0aGlzLmNvbmZpZy50b2tlbikgY29ubmVjdE9wdHMudG9rZW4gPSB0aGlzLmNvbmZpZy50b2tlbjtcblx0XHRcdGlmICh0aGlzLmNvbmZpZy51c2VyKSBjb25uZWN0T3B0cy51c2VyID0gdGhpcy5jb25maWcudXNlcjtcblx0XHRcdGlmICh0aGlzLmNvbmZpZy5wYXNzKSBjb25uZWN0T3B0cy5wYXNzID0gdGhpcy5jb25maWcucGFzcztcblxuXHRcdFx0dGhpcy5uYyA9IGF3YWl0IG5hdHMuY29ubmVjdChjb25uZWN0T3B0cyk7XG5cdFx0XHR0aGlzLmpzID0gdGhpcy5uYy5qZXRzdHJlYW0oKTtcblx0XHRcdHRoaXMuanNtID0gYXdhaXQgdGhpcy5uYy5qZXRzdHJlYW1NYW5hZ2VyKCk7XG5cblx0XHRcdHRoaXMuY29ubmVjdGVkID0gdHJ1ZTtcblx0XHRcdGNvbnNvbGUubG9nKGBbTkFUU1dvcmtlckFkYXB0ZXJdIENvbm5lY3RlZCB0byBOQVRTOiAke3RoaXMuY29uZmlnLnNlcnZlcnMuam9pbihcIiwgXCIpfWApO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRcdGBGYWlsZWQgdG8gY29ubmVjdCB0byBOQVRTOiAkeyhlcnJvciBhcyBFcnJvcikubWVzc2FnZX0uIE1ha2Ugc3VyZSBuYXRzIGlzIGluc3RhbGxlZDogbnBtIGluc3RhbGwgbmF0c2AsXG5cdFx0XHQpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNjb25uZWN0IGZyb20gTkFUU1xuXHQgKi9cblx0YXN5bmMgZGlzY29ubmVjdCgpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRpZiAoIXRoaXMuY29ubmVjdGVkKSByZXR1cm47XG5cblx0XHR0cnkge1xuXHRcdFx0Ly8gU3RvcCBhbGwgY29uc3VtZSBpdGVyYXRvcnNcblx0XHRcdGZvciAoY29uc3QgWywgaXRlcl0gb2YgdGhpcy5jb25zdW1lSXRlcmF0b3JzKSB7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0aXRlci5zdG9wKCk7XG5cdFx0XHRcdH0gY2F0Y2gge1xuXHRcdFx0XHRcdC8vIEl0ZXJhdG9yIG1heSBhbHJlYWR5IGJlIHN0b3BwZWRcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0dGhpcy5jb25zdW1lSXRlcmF0b3JzLmNsZWFyKCk7XG5cdFx0XHR0aGlzLmNvbnN1bWVycy5jbGVhcigpO1xuXG5cdFx0XHRhd2FpdCB0aGlzLm5jLmRyYWluKCk7XG5cdFx0XHR0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuXHRcdFx0Y29uc29sZS5sb2coXCJbTkFUU1dvcmtlckFkYXB0ZXJdIERpc2Nvbm5lY3RlZCBmcm9tIE5BVFNcIik7XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoYFtOQVRTV29ya2VyQWRhcHRlcl0gRGlzY29ubmVjdCBlcnJvcjogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXJ0IHByb2Nlc3Npbmcgam9icyBmcm9tIGEgcXVldWVcblx0ICovXG5cdGFzeW5jIHByb2Nlc3MoY29uZmlnOiBXb3JrZXJUcmlnZ2VyT3B0cywgaGFuZGxlcjogKGpvYjogV29ya2VySm9iKSA9PiBQcm9taXNlPHZvaWQ+KTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0aWYgKCF0aGlzLmNvbm5lY3RlZCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiTm90IGNvbm5lY3RlZC4gQ2FsbCBjb25uZWN0KCkgZmlyc3QuXCIpO1xuXHRcdH1cblxuXHRcdGNvbnN0IG5hdHMgPSBhd2FpdCBpbXBvcnQoXCJuYXRzXCIpO1xuXHRcdGNvbnN0IHF1ZXVlID0gY29uZmlnLnF1ZXVlO1xuXHRcdGNvbnN0IHN0cmVhbU5hbWUgPSB0aGlzLmNvbmZpZy5zdHJlYW1OYW1lIHx8IFwiYmxvay13b3JrZXJcIjtcblx0XHRjb25zdCBzdWJqZWN0ID0gYHdvcmtlci4ke3F1ZXVlfWA7XG5cdFx0Y29uc3QgZHVyYWJsZU5hbWUgPSBgYmxvay13b3JrZXItJHtxdWV1ZX1gO1xuXG5cdFx0Ly8gRW5zdXJlIHN0cmVhbSBleGlzdHMgd2l0aCB3b3JrZXIgc3ViamVjdHNcblx0XHRhd2FpdCB0aGlzLmVuc3VyZVN0cmVhbShzdHJlYW1OYW1lLCBbc3ViamVjdF0pO1xuXG5cdFx0Ly8gQ3JlYXRlIG9yIHVwZGF0ZSBkdXJhYmxlIHB1bGwgY29uc3VtZXIgd2l0aCB3b3JrZXIgc2VtYW50aWNzXG5cdFx0Y29uc3QgYWNrV2FpdE5zID0gKChjb25maWcudGltZW91dCA/PyAzMDAwMCkgKyA1MDAwKSAqIDFfMDAwXzAwMDsgLy8gdGltZW91dCArIDVzIGJ1ZmZlciwgaW4gbmFub3NlY29uZHNcblx0XHRhd2FpdCB0aGlzLmpzbS5jb25zdW1lcnMuYWRkKHN0cmVhbU5hbWUsIHtcblx0XHRcdGR1cmFibGVfbmFtZTogZHVyYWJsZU5hbWUsXG5cdFx0XHRhY2tfcG9saWN5OiBuYXRzLkFja1BvbGljeS5FeHBsaWNpdCxcblx0XHRcdG1heF9kZWxpdmVyOiAoY29uZmlnLnJldHJpZXMgPz8gMykgKyAxLCAvLyArMSBiZWNhdXNlIGZpcnN0IGF0dGVtcHQgY291bnRzXG5cdFx0XHRhY2tfd2FpdDogYWNrV2FpdE5zLFxuXHRcdFx0ZmlsdGVyX3N1YmplY3RzOiBbc3ViamVjdF0sXG5cdFx0fSk7XG5cblx0XHQvLyBHZXQgY29uc3VtZXIgaGFuZGxlXG5cdFx0Y29uc3QgY29uc3VtZXIgPSBhd2FpdCB0aGlzLmpzLmNvbnN1bWVycy5nZXQoc3RyZWFtTmFtZSwgZHVyYWJsZU5hbWUpO1xuXHRcdHRoaXMuY29uc3VtZXJzLnNldChxdWV1ZSwgY29uc3VtZXIpO1xuXG5cdFx0Ly8gU3RhcnQgY29uc3VtaW5nXG5cdFx0Y29uc3QgaXRlciA9IGF3YWl0IGNvbnN1bWVyLmNvbnN1bWUoKTtcblx0XHR0aGlzLmNvbnN1bWVJdGVyYXRvcnMuc2V0KHF1ZXVlLCBpdGVyKTtcblxuXHRcdC8vIFByb2Nlc3Mgam9icyBpbiBiYWNrZ3JvdW5kXG5cdFx0KGFzeW5jICgpID0+IHtcblx0XHRcdGNvbnN0IHNlbWFwaG9yZSA9IG5ldyBTZW1hcGhvcmUoY29uZmlnLmNvbmN1cnJlbmN5ID8/IDEpO1xuXG5cdFx0XHRmb3IgYXdhaXQgKGNvbnN0IG1zZyBvZiBpdGVyKSB7XG5cdFx0XHRcdGF3YWl0IHNlbWFwaG9yZS5hY3F1aXJlKCk7XG5cblx0XHRcdFx0Ly8gUHJvY2VzcyBlYWNoIGpvYiBjb25jdXJyZW50bHkgdXAgdG8gY29uY3VycmVuY3kgbGltaXRcblx0XHRcdFx0KGFzeW5jICgpID0+IHtcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0Ly8gUGFyc2Ugam9iIGRhdGFcblx0XHRcdFx0XHRcdGxldCBkYXRhOiB1bmtub3duO1xuXHRcdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdFx0Y29uc3QgY29kZWMgPSBuYXRzLkpTT05Db2RlYygpO1xuXHRcdFx0XHRcdFx0XHRkYXRhID0gY29kZWMuZGVjb2RlKG1zZy5kYXRhKTtcblx0XHRcdFx0XHRcdH0gY2F0Y2gge1xuXHRcdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRcdGNvbnN0IHNjID0gbmF0cy5TdHJpbmdDb2RlYygpO1xuXHRcdFx0XHRcdFx0XHRcdGRhdGEgPSBKU09OLnBhcnNlKHNjLmRlY29kZShtc2cuZGF0YSkpO1xuXHRcdFx0XHRcdFx0XHR9IGNhdGNoIHtcblx0XHRcdFx0XHRcdFx0XHRkYXRhID0gbXNnLmRhdGE7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0Ly8gRXh0cmFjdCBoZWFkZXJzXG5cdFx0XHRcdFx0XHRjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cdFx0XHRcdFx0XHRpZiAobXNnLmhlYWRlcnMpIHtcblx0XHRcdFx0XHRcdFx0Zm9yIChjb25zdCBba2V5LCB2YWx1ZXNdIG9mIG1zZy5oZWFkZXJzKSB7XG5cdFx0XHRcdFx0XHRcdFx0aGVhZGVyc1trZXldID0gQXJyYXkuaXNBcnJheSh2YWx1ZXMpID8gdmFsdWVzWzBdIDogdmFsdWVzO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdC8vIEV4dHJhY3Qgam9iIG1ldGFkYXRhIGZyb20gaGVhZGVyc1xuXHRcdFx0XHRcdFx0Y29uc3Qgam9iSWQgPSBoZWFkZXJzW1wieC1qb2ItaWRcIl0gfHwgbXNnLmhlYWRlcnM/LmdldChcIk5hdHMtTXNnLUlkXCIpIHx8IHV1aWQoKTtcblx0XHRcdFx0XHRcdGNvbnN0IHByaW9yaXR5ID0gTnVtYmVyLnBhcnNlSW50KGhlYWRlcnNbXCJ4LXByaW9yaXR5XCJdIHx8IFwiMFwiLCAxMCk7XG5cdFx0XHRcdFx0XHRjb25zdCBkZWxheSA9IE51bWJlci5wYXJzZUludChoZWFkZXJzW1wieC1kZWxheVwiXSB8fCBcIjBcIiwgMTApO1xuXHRcdFx0XHRcdFx0Y29uc3QgdGltZW91dCA9IE51bWJlci5wYXJzZUludChoZWFkZXJzW1wieC10aW1lb3V0XCJdIHx8IFwiMFwiLCAxMCk7XG5cblx0XHRcdFx0XHRcdC8vIEdldCByZWRlbGl2ZXJ5IGNvdW50IChhdHRlbXB0cylcblx0XHRcdFx0XHRcdGNvbnN0IGluZm8gPSBtc2cuaW5mbztcblx0XHRcdFx0XHRcdGNvbnN0IGF0dGVtcHRzID0gaW5mby5yZWRlbGl2ZXJ5Q291bnQgPz8gMDtcblx0XHRcdFx0XHRcdGNvbnN0IG1heFJldHJpZXMgPSBjb25maWcucmV0cmllcyA/PyAzO1xuXG5cdFx0XHRcdFx0XHQvLyBDcmVhdGUgV29ya2VySm9iXG5cdFx0XHRcdFx0XHRjb25zdCB3b3JrZXJKb2I6IFdvcmtlckpvYiA9IHtcblx0XHRcdFx0XHRcdFx0aWQ6IGpvYklkLFxuXHRcdFx0XHRcdFx0XHRkYXRhLFxuXHRcdFx0XHRcdFx0XHRoZWFkZXJzLFxuXHRcdFx0XHRcdFx0XHRxdWV1ZSxcblx0XHRcdFx0XHRcdFx0cHJpb3JpdHksXG5cdFx0XHRcdFx0XHRcdGF0dGVtcHRzLFxuXHRcdFx0XHRcdFx0XHRtYXhSZXRyaWVzLFxuXHRcdFx0XHRcdFx0XHRjcmVhdGVkQXQ6IG5ldyBEYXRlKGluZm8udGltZXN0YW1wTmFub3MgPyBOdW1iZXIoaW5mby50aW1lc3RhbXBOYW5vcyAvIEJpZ0ludCgxXzAwMF8wMDApKSA6IERhdGUubm93KCkpLFxuXHRcdFx0XHRcdFx0XHRkZWxheTogZGVsYXkgfHwgdW5kZWZpbmVkLFxuXHRcdFx0XHRcdFx0XHR0aW1lb3V0OiB0aW1lb3V0IHx8IGNvbmZpZy50aW1lb3V0IHx8IHVuZGVmaW5lZCxcblx0XHRcdFx0XHRcdFx0cmF3OiBtc2csXG5cdFx0XHRcdFx0XHRcdGNvbXBsZXRlOiBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0bXNnLmFjaygpO1xuXHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0XHRmYWlsOiBhc3luYyAoZXJyb3I6IEVycm9yLCByZXF1ZXVlPzogYm9vbGVhbikgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdGlmIChyZXF1ZXVlKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBuYWsoKSB0ZWxscyB0aGUgc2VydmVyIHRvIHJlZGVsaXZlclxuXHRcdFx0XHRcdFx0XHRcdFx0bXNnLm5haygpO1xuXHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyB0ZXJtKCkgdGVybWluYXRlcyBkZWxpdmVyeSDigJQgbm8gbW9yZSByZXRyaWVzXG5cdFx0XHRcdFx0XHRcdFx0XHRtc2cudGVybSgpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRcdC8vIFRpZXIgMiBwb2xpc2gg4oCUIGVuZm9yY2UgYHgtZGVsYXlgIGhlYWRlciBvbiB0aGUgY29uc3VtZXIgc2lkZS5cblx0XHRcdFx0XHRcdC8vIE5BVFMgSmV0U3RyZWFtIHN0b3JlcyBgeC1kZWxheWAgYXMgb3BhcXVlIG1ldGFkYXRhOyB0aGUgYnJva2VyXG5cdFx0XHRcdFx0XHQvLyBkb2VzIE5PVCBkZWZlciBkZWxpdmVyeSBvbiBpdC4gV2UgaW1wbGVtZW50IGNvbnN1bWVyLXNpZGVcblx0XHRcdFx0XHRcdC8vIGhvbGRpbmcgaGVyZS4gY3JlYXRlZE1zIGlzIHRoZSBtZXNzYWdlJ3MgZmlyc3QtcHVibGlzaCB0aW1lc3RhbXA7XG5cdFx0XHRcdFx0XHQvLyBob2xkIHVudGlsIGNyZWF0ZWRNcyArIGRlbGF5LiBTaW5nbGUtcHJvY2VzcyBzZW1hbnRpY3Mg4oCUIGZvclxuXHRcdFx0XHRcdFx0Ly8gbG9uZyBkZWZlcnJhbHMsIHByZWZlciB0cmlnZ2VyLWxldmVsIGBkZWxheWAgKERlZmVycmVkUnVuU2NoZWR1bGVyKS5cblx0XHRcdFx0XHRcdGNvbnN0IGNyZWF0ZWRNcyA9IGluZm8udGltZXN0YW1wTmFub3MgPyBOdW1iZXIoaW5mby50aW1lc3RhbXBOYW5vcyAvIEJpZ0ludCgxXzAwMF8wMDApKSA6IERhdGUubm93KCk7XG5cdFx0XHRcdFx0XHRjb25zdCB3YWl0TXMgPSBjb21wdXRlWERlbGF5SG9sZE1zKGRlbGF5LCBjcmVhdGVkTXMsIERhdGUubm93KCkpO1xuXHRcdFx0XHRcdFx0aWYgKHdhaXRNcyA+IDApIHtcblx0XHRcdFx0XHRcdFx0YXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgd2FpdE1zKSk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdGF3YWl0IGhhbmRsZXIod29ya2VySm9iKTtcblx0XHRcdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRcdFx0Y29uc29sZS5lcnJvcihgW05BVFNXb3JrZXJBZGFwdGVyXSBFcnJvciBwcm9jZXNzaW5nIGpvYiBmcm9tICR7cXVldWV9OiAkeyhlcnJvciBhcyBFcnJvcikubWVzc2FnZX1gKTtcblx0XHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRcdG1zZy5uYWsoKTtcblx0XHRcdFx0XHRcdH0gY2F0Y2gge1xuXHRcdFx0XHRcdFx0XHQvLyBBbHJlYWR5IGFja2VkL25hY2tlZFxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdFx0XHRzZW1hcGhvcmUucmVsZWFzZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSkoKTtcblx0XHRcdH1cblx0XHR9KSgpO1xuXG5cdFx0Y29uc29sZS5sb2coXG5cdFx0XHRgW05BVFNXb3JrZXJBZGFwdGVyXSBQcm9jZXNzaW5nIHF1ZXVlOiAke3F1ZXVlfSAoY29uY3VycmVuY3k9JHtjb25maWcuY29uY3VycmVuY3kgPz8gMX0sIHJldHJpZXM9JHtjb25maWcucmV0cmllcyA/PyAzfSlgLFxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkIGEgam9iIHRvIGEgd29ya2VyIHF1ZXVlXG5cdCAqL1xuXHRhc3luYyBhZGRKb2IoXG5cdFx0cXVldWU6IHN0cmluZyxcblx0XHRkYXRhOiB1bmtub3duLFxuXHRcdG9wdHM/OiB7XG5cdFx0XHRwcmlvcml0eT86IG51bWJlcjtcblx0XHRcdGRlbGF5PzogbnVtYmVyO1xuXHRcdFx0cmV0cmllcz86IG51bWJlcjtcblx0XHRcdHRpbWVvdXQ/OiBudW1iZXI7XG5cdFx0XHRqb2JJZD86IHN0cmluZztcblx0XHR9LFxuXHQpOiBQcm9taXNlPHN0cmluZz4ge1xuXHRcdGlmICghdGhpcy5jb25uZWN0ZWQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIk5vdCBjb25uZWN0ZWQuIENhbGwgY29ubmVjdCgpIGZpcnN0LlwiKTtcblx0XHR9XG5cblx0XHRjb25zdCBuYXRzID0gYXdhaXQgaW1wb3J0KFwibmF0c1wiKTtcblx0XHRjb25zdCBzdWJqZWN0ID0gYHdvcmtlci4ke3F1ZXVlfWA7XG5cdFx0Y29uc3Qgc3RyZWFtTmFtZSA9IHRoaXMuY29uZmlnLnN0cmVhbU5hbWUgfHwgXCJibG9rLXdvcmtlclwiO1xuXG5cdFx0Ly8gRW5zdXJlIHN0cmVhbSBoYXMgdGhpcyBzdWJqZWN0XG5cdFx0YXdhaXQgdGhpcy5lbnN1cmVTdHJlYW0oc3RyZWFtTmFtZSwgW3N1YmplY3RdKTtcblxuXHRcdC8vIEJ1aWxkIGhlYWRlcnMgd2l0aCBqb2IgbWV0YWRhdGFcblx0XHRjb25zdCBoZHJzID0gbmF0cy5oZWFkZXJzKCk7XG5cdFx0Y29uc3Qgam9iSWQgPSBvcHRzPy5qb2JJZCB8fCB1dWlkKCk7XG5cdFx0aGRycy5zZXQoXCJ4LWpvYi1pZFwiLCBqb2JJZCk7XG5cdFx0aGRycy5zZXQoXCJOYXRzLU1zZy1JZFwiLCBqb2JJZCk7IC8vIERlZHVwbGljYXRpb25cblx0XHRpZiAob3B0cz8ucHJpb3JpdHkpIGhkcnMuc2V0KFwieC1wcmlvcml0eVwiLCBTdHJpbmcob3B0cy5wcmlvcml0eSkpO1xuXHRcdGlmIChvcHRzPy5kZWxheSkgaGRycy5zZXQoXCJ4LWRlbGF5XCIsIFN0cmluZyhvcHRzLmRlbGF5KSk7XG5cdFx0aWYgKG9wdHM/LnRpbWVvdXQpIGhkcnMuc2V0KFwieC10aW1lb3V0XCIsIFN0cmluZyhvcHRzLnRpbWVvdXQpKTtcblxuXHRcdC8vIEVuY29kZSBhbmQgcHVibGlzaFxuXHRcdGNvbnN0IGNvZGVjID0gbmF0cy5KU09OQ29kZWMoKTtcblx0XHRhd2FpdCB0aGlzLmpzLnB1Ymxpc2goc3ViamVjdCwgY29kZWMuZW5jb2RlKGRhdGEpLCB7IGhlYWRlcnM6IGhkcnMgfSk7XG5cblx0XHRyZXR1cm4gam9iSWQ7XG5cdH1cblxuXHQvKipcblx0ICogU3RvcCBwcm9jZXNzaW5nIGEgc3BlY2lmaWMgcXVldWVcblx0ICovXG5cdGFzeW5jIHN0b3BQcm9jZXNzaW5nKHF1ZXVlOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRjb25zdCBpdGVyID0gdGhpcy5jb25zdW1lSXRlcmF0b3JzLmdldChxdWV1ZSk7XG5cdFx0aWYgKGl0ZXIpIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGl0ZXIuc3RvcCgpO1xuXHRcdFx0fSBjYXRjaCB7XG5cdFx0XHRcdC8vIEFscmVhZHkgc3RvcHBlZFxuXHRcdFx0fVxuXHRcdFx0dGhpcy5jb25zdW1lSXRlcmF0b3JzLmRlbGV0ZShxdWV1ZSk7XG5cdFx0fVxuXHRcdHRoaXMuY29uc3VtZXJzLmRlbGV0ZShxdWV1ZSk7XG5cdFx0Y29uc29sZS5sb2coYFtOQVRTV29ya2VyQWRhcHRlcl0gU3RvcHBlZCBwcm9jZXNzaW5nIHF1ZXVlOiAke3F1ZXVlfWApO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrIGlmIGNvbm5lY3RlZFxuXHQgKi9cblx0aXNDb25uZWN0ZWQoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMuY29ubmVjdGVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIEhlYWx0aCBjaGVja1xuXHQgKi9cblx0YXN5bmMgaGVhbHRoQ2hlY2soKTogUHJvbWlzZTxib29sZWFuPiB7XG5cdFx0aWYgKCF0aGlzLmNvbm5lY3RlZCB8fCAhdGhpcy5uYykgcmV0dXJuIGZhbHNlO1xuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBpbmZvID0gdGhpcy5uYy5pbmZvO1xuXHRcdFx0cmV0dXJuIGluZm8gIT09IHVuZGVmaW5lZDtcblx0XHR9IGNhdGNoIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0IHF1ZXVlIHN0YXRpc3RpY3MgZnJvbSBKZXRTdHJlYW0gY29uc3VtZXIgaW5mb1xuXHQgKi9cblx0YXN5bmMgZ2V0UXVldWVTdGF0cyhxdWV1ZTogc3RyaW5nKTogUHJvbWlzZTxXb3JrZXJRdWV1ZVN0YXRzPiB7XG5cdFx0aWYgKCF0aGlzLmNvbm5lY3RlZCkge1xuXHRcdFx0cmV0dXJuIHsgd2FpdGluZzogMCwgYWN0aXZlOiAwLCBjb21wbGV0ZWQ6IDAsIGZhaWxlZDogMCwgZGVsYXllZDogMCB9O1xuXHRcdH1cblxuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBzdHJlYW1OYW1lID0gdGhpcy5jb25maWcuc3RyZWFtTmFtZSB8fCBcImJsb2std29ya2VyXCI7XG5cdFx0XHRjb25zdCBkdXJhYmxlTmFtZSA9IGBibG9rLXdvcmtlci0ke3F1ZXVlfWA7XG5cblx0XHRcdGNvbnN0IGluZm8gPSBhd2FpdCB0aGlzLmpzbS5jb25zdW1lcnMuaW5mbyhzdHJlYW1OYW1lLCBkdXJhYmxlTmFtZSk7XG5cblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdHdhaXRpbmc6IGluZm8ubnVtX3BlbmRpbmcgPz8gMCxcblx0XHRcdFx0YWN0aXZlOiBpbmZvLm51bV9hY2tfcGVuZGluZyA/PyAwLFxuXHRcdFx0XHRjb21wbGV0ZWQ6IGluZm8uZGVsaXZlcmVkPy5jb25zdW1lcl9zZXEgPz8gMCxcblx0XHRcdFx0ZmFpbGVkOiBpbmZvLm51bV9yZWRlbGl2ZXJlZCA/PyAwLFxuXHRcdFx0XHRkZWxheWVkOiAwLCAvLyBOQVRTIGRvZXNuJ3QgaGF2ZSBhIG5hdGl2ZSBkZWxheWVkIGNvdW50XG5cdFx0XHR9O1xuXHRcdH0gY2F0Y2gge1xuXHRcdFx0cmV0dXJuIHsgd2FpdGluZzogMCwgYWN0aXZlOiAwLCBjb21wbGV0ZWQ6IDAsIGZhaWxlZDogMCwgZGVsYXllZDogMCB9O1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBFbnN1cmUgYSBKZXRTdHJlYW0gc3RyZWFtIGV4aXN0cyB3aXRoIHRoZSBnaXZlbiBzdWJqZWN0c1xuXHQgKi9cblx0cHJpdmF0ZSBhc3luYyBlbnN1cmVTdHJlYW0obmFtZTogc3RyaW5nLCBzdWJqZWN0czogc3RyaW5nW10pOiBQcm9taXNlPHZvaWQ+IHtcblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgaW5mbyA9IGF3YWl0IHRoaXMuanNtLnN0cmVhbXMuaW5mbyhuYW1lKTtcblxuXHRcdFx0Ly8gTWVyZ2UgbmV3IHN1YmplY3RzIHdpdGggZXhpc3Rpbmdcblx0XHRcdGNvbnN0IGV4aXN0aW5nU3ViamVjdHMgPSBpbmZvLmNvbmZpZy5zdWJqZWN0cyB8fCBbXTtcblx0XHRcdGNvbnN0IGFsbFN1YmplY3RzID0gWy4uLm5ldyBTZXQoWy4uLmV4aXN0aW5nU3ViamVjdHMsIC4uLnN1YmplY3RzXSldO1xuXG5cdFx0XHRpZiAoYWxsU3ViamVjdHMubGVuZ3RoICE9PSBleGlzdGluZ1N1YmplY3RzLmxlbmd0aCkge1xuXHRcdFx0XHRhd2FpdCB0aGlzLmpzbS5zdHJlYW1zLnVwZGF0ZShuYW1lLCB7XG5cdFx0XHRcdFx0Li4uaW5mby5jb25maWcsXG5cdFx0XHRcdFx0c3ViamVjdHM6IGFsbFN1YmplY3RzLFxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9IGNhdGNoIHtcblx0XHRcdC8vIFN0cmVhbSBkb2Vzbid0IGV4aXN0LCBjcmVhdGUgaXRcblx0XHRcdGF3YWl0IHRoaXMuanNtLnN0cmVhbXMuYWRkKHtcblx0XHRcdFx0bmFtZSxcblx0XHRcdFx0c3ViamVjdHMsXG5cdFx0XHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogbmF0cyBKZXRTdHJlYW0gcmV0ZW50aW9uIHBvbGljeSBlbnVtXG5cdFx0XHRcdHJldGVudGlvbjogXCJ3b3JrcXVldWVcIiBhcyBhbnksXG5cdFx0XHRcdG1heF9kZWxpdmVyOiA0LCAvLyBkZWZhdWx0OiAzIHJldHJpZXMgKyAxIGluaXRpYWwgYXR0ZW1wdFxuXHRcdFx0XHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IG5hdHMgSmV0U3RyZWFtIHN0b3JhZ2UgdHlwZSBlbnVtXG5cdFx0XHRcdHN0b3JhZ2U6IFwiZmlsZVwiIGFzIGFueSxcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIFNpbXBsZSBzZW1hcGhvcmUgZm9yIGNvbmN1cnJlbmN5IGNvbnRyb2xcbiAqL1xuY2xhc3MgU2VtYXBob3JlIHtcblx0cHJpdmF0ZSBwZXJtaXRzOiBudW1iZXI7XG5cdHByaXZhdGUgd2FpdGluZzogQXJyYXk8KCkgPT4gdm9pZD4gPSBbXTtcblxuXHRjb25zdHJ1Y3RvcihwZXJtaXRzOiBudW1iZXIpIHtcblx0XHR0aGlzLnBlcm1pdHMgPSBwZXJtaXRzO1xuXHR9XG5cblx0YXN5bmMgYWNxdWlyZSgpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRpZiAodGhpcy5wZXJtaXRzID4gMCkge1xuXHRcdFx0dGhpcy5wZXJtaXRzLS07XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuXHRcdFx0dGhpcy53YWl0aW5nLnB1c2gocmVzb2x2ZSk7XG5cdFx0fSk7XG5cdH1cblxuXHRyZWxlYXNlKCk6IHZvaWQge1xuXHRcdGNvbnN0IG5leHQgPSB0aGlzLndhaXRpbmcuc2hpZnQoKTtcblx0XHRpZiAobmV4dCkge1xuXHRcdFx0bmV4dCgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnBlcm1pdHMrKztcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTkFUU1dvcmtlckFkYXB0ZXI7XG4iXX0=
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @
|
|
2
|
+
* @blokjs/trigger-worker
|
|
3
3
|
*
|
|
4
4
|
* Worker-based trigger for Blok workflows.
|
|
5
5
|
* Supports background job processing with:
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*
|
|
17
17
|
* @example BullMQ
|
|
18
18
|
* ```typescript
|
|
19
|
-
* import { WorkerTrigger, BullMQAdapter } from "@
|
|
19
|
+
* import { WorkerTrigger, BullMQAdapter } from "@blokjs/trigger-worker";
|
|
20
20
|
*
|
|
21
21
|
* class MyWorkerTrigger extends WorkerTrigger {
|
|
22
22
|
* protected adapter = new BullMQAdapter({
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
*
|
|
42
42
|
* @example InMemory (development)
|
|
43
43
|
* ```typescript
|
|
44
|
-
* import { WorkerTrigger, InMemoryAdapter } from "@
|
|
44
|
+
* import { WorkerTrigger, InMemoryAdapter } from "@blokjs/trigger-worker";
|
|
45
45
|
*
|
|
46
46
|
* class DevWorkerTrigger extends WorkerTrigger {
|
|
47
47
|
* protected adapter = new InMemoryAdapter();
|
|
@@ -53,4 +53,5 @@
|
|
|
53
53
|
export { WorkerTrigger, type WorkerAdapter, type WorkerJob, type WorkerQueueStats, } from "./WorkerTrigger";
|
|
54
54
|
export { BullMQAdapter, type BullMQConfig } from "./adapters/BullMQAdapter";
|
|
55
55
|
export { InMemoryAdapter } from "./adapters/InMemoryAdapter";
|
|
56
|
-
export type
|
|
56
|
+
export { NATSWorkerAdapter, type NATSWorkerConfig } from "./adapters/NATSAdapter";
|
|
57
|
+
export type { WorkerTriggerOpts } from "@blokjs/helper";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
|
-
* @
|
|
2
|
+
* @blokjs/trigger-worker
|
|
4
3
|
*
|
|
5
4
|
* Worker-based trigger for Blok workflows.
|
|
6
5
|
* Supports background job processing with:
|
|
@@ -17,7 +16,7 @@
|
|
|
17
16
|
*
|
|
18
17
|
* @example BullMQ
|
|
19
18
|
* ```typescript
|
|
20
|
-
* import { WorkerTrigger, BullMQAdapter } from "@
|
|
19
|
+
* import { WorkerTrigger, BullMQAdapter } from "@blokjs/trigger-worker";
|
|
21
20
|
*
|
|
22
21
|
* class MyWorkerTrigger extends WorkerTrigger {
|
|
23
22
|
* protected adapter = new BullMQAdapter({
|
|
@@ -42,7 +41,7 @@
|
|
|
42
41
|
*
|
|
43
42
|
* @example InMemory (development)
|
|
44
43
|
* ```typescript
|
|
45
|
-
* import { WorkerTrigger, InMemoryAdapter } from "@
|
|
44
|
+
* import { WorkerTrigger, InMemoryAdapter } from "@blokjs/trigger-worker";
|
|
46
45
|
*
|
|
47
46
|
* class DevWorkerTrigger extends WorkerTrigger {
|
|
48
47
|
* protected adapter = new InMemoryAdapter();
|
|
@@ -51,14 +50,10 @@
|
|
|
51
50
|
* }
|
|
52
51
|
* ```
|
|
53
52
|
*/
|
|
54
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
-
exports.InMemoryAdapter = exports.BullMQAdapter = exports.WorkerTrigger = void 0;
|
|
56
53
|
// Core exports
|
|
57
|
-
|
|
58
|
-
Object.defineProperty(exports, "WorkerTrigger", { enumerable: true, get: function () { return WorkerTrigger_1.WorkerTrigger; } });
|
|
54
|
+
export { WorkerTrigger, } from "./WorkerTrigger";
|
|
59
55
|
// Adapters
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtREc7OztBQUVILGVBQWU7QUFDZixpREFLeUI7QUFKeEIsOEdBQUEsYUFBYSxPQUFBO0FBTWQsV0FBVztBQUNYLDBEQUE0RTtBQUFuRSw4R0FBQSxhQUFhLE9BQUE7QUFDdEIsOERBQTZEO0FBQXBELGtIQUFBLGVBQWUsT0FBQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGJsb2svdHJpZ2dlci13b3JrZXJcbiAqXG4gKiBXb3JrZXItYmFzZWQgdHJpZ2dlciBmb3IgQmxvayB3b3JrZmxvd3MuXG4gKiBTdXBwb3J0cyBiYWNrZ3JvdW5kIGpvYiBwcm9jZXNzaW5nIHdpdGg6XG4gKiAtIENvbmZpZ3VyYWJsZSBjb25jdXJyZW5jeSBwZXIgcXVldWVcbiAqIC0gQXV0b21hdGljIHJldHJpZXMgd2l0aCBleHBvbmVudGlhbCBiYWNrb2ZmXG4gKiAtIEpvYiB0aW1lb3V0c1xuICogLSBQcmlvcml0eS1iYXNlZCBqb2Igb3JkZXJpbmdcbiAqIC0gRGVsYXllZCBqb2Igc2NoZWR1bGluZ1xuICogLSBRdWV1ZSBzdGF0aXN0aWNzIGFuZCBtb25pdG9yaW5nXG4gKlxuICogQWRhcHRlcnM6XG4gKiAtIEJ1bGxNUSAoUmVkaXMtYmFja2VkLCBwcm9kdWN0aW9uKVxuICogLSBJbk1lbW9yeSAoZGV2ZWxvcG1lbnQvdGVzdGluZylcbiAqXG4gKiBAZXhhbXBsZSBCdWxsTVFcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IFdvcmtlclRyaWdnZXIsIEJ1bGxNUUFkYXB0ZXIgfSBmcm9tIFwiQGJsb2svdHJpZ2dlci13b3JrZXJcIjtcbiAqXG4gKiBjbGFzcyBNeVdvcmtlclRyaWdnZXIgZXh0ZW5kcyBXb3JrZXJUcmlnZ2VyIHtcbiAqICAgcHJvdGVjdGVkIGFkYXB0ZXIgPSBuZXcgQnVsbE1RQWRhcHRlcih7XG4gKiAgICAgaG9zdDogXCJsb2NhbGhvc3RcIixcbiAqICAgICBwb3J0OiA2Mzc5LFxuICogICB9KTtcbiAqXG4gKiAgIHByb3RlY3RlZCBub2RlcyA9IG15Tm9kZXM7XG4gKiAgIHByb3RlY3RlZCB3b3JrZmxvd3MgPSBteVdvcmtmbG93cztcbiAqIH1cbiAqXG4gKiBjb25zdCB0cmlnZ2VyID0gbmV3IE15V29ya2VyVHJpZ2dlcigpO1xuICogYXdhaXQgdHJpZ2dlci5saXN0ZW4oKTtcbiAqXG4gKiAvLyBEaXNwYXRjaCBhIGpvYlxuICogYXdhaXQgdHJpZ2dlci5kaXNwYXRjaChcImJhY2tncm91bmQtam9ic1wiLCB7IHVzZXJJZDogXCIxMjNcIiB9LCB7XG4gKiAgIHByaW9yaXR5OiAxMCxcbiAqICAgcmV0cmllczogMyxcbiAqICAgZGVsYXk6IDUwMDAsIC8vIGRlbGF5IDUgc2Vjb25kc1xuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZSBJbk1lbW9yeSAoZGV2ZWxvcG1lbnQpXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBXb3JrZXJUcmlnZ2VyLCBJbk1lbW9yeUFkYXB0ZXIgfSBmcm9tIFwiQGJsb2svdHJpZ2dlci13b3JrZXJcIjtcbiAqXG4gKiBjbGFzcyBEZXZXb3JrZXJUcmlnZ2VyIGV4dGVuZHMgV29ya2VyVHJpZ2dlciB7XG4gKiAgIHByb3RlY3RlZCBhZGFwdGVyID0gbmV3IEluTWVtb3J5QWRhcHRlcigpO1xuICogICBwcm90ZWN0ZWQgbm9kZXMgPSBteU5vZGVzO1xuICogICBwcm90ZWN0ZWQgd29ya2Zsb3dzID0gbXlXb3JrZmxvd3M7XG4gKiB9XG4gKiBgYGBcbiAqL1xuXG4vLyBDb3JlIGV4cG9ydHNcbmV4cG9ydCB7XG5cdFdvcmtlclRyaWdnZXIsXG5cdHR5cGUgV29ya2VyQWRhcHRlcixcblx0dHlwZSBXb3JrZXJKb2IsXG5cdHR5cGUgV29ya2VyUXVldWVTdGF0cyxcbn0gZnJvbSBcIi4vV29ya2VyVHJpZ2dlclwiO1xuXG4vLyBBZGFwdGVyc1xuZXhwb3J0IHsgQnVsbE1RQWRhcHRlciwgdHlwZSBCdWxsTVFDb25maWcgfSBmcm9tIFwiLi9hZGFwdGVycy9CdWxsTVFBZGFwdGVyXCI7XG5leHBvcnQgeyBJbk1lbW9yeUFkYXB0ZXIgfSBmcm9tIFwiLi9hZGFwdGVycy9Jbk1lbW9yeUFkYXB0ZXJcIjtcblxuLy8gUmUtZXhwb3J0IHR5cGVzIGZyb20gaGVscGVyIGZvciBjb252ZW5pZW5jZVxuZXhwb3J0IHR5cGUgeyBXb3JrZXJUcmlnZ2VyT3B0cyB9IGZyb20gXCJAYmxvay9oZWxwZXJcIjtcbiJdfQ==
|
|
56
|
+
export { BullMQAdapter } from "./adapters/BullMQAdapter";
|
|
57
|
+
export { InMemoryAdapter } from "./adapters/InMemoryAdapter";
|
|
58
|
+
export { NATSWorkerAdapter } from "./adapters/NATSAdapter";
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1ERztBQUVILGVBQWU7QUFDZixPQUFPLEVBQ04sYUFBYSxHQUliLE1BQU0saUJBQWlCLENBQUM7QUFFekIsV0FBVztBQUNYLE9BQU8sRUFBRSxhQUFhLEVBQXFCLE1BQU0sMEJBQTBCLENBQUM7QUFDNUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzdELE9BQU8sRUFBRSxpQkFBaUIsRUFBeUIsTUFBTSx3QkFBd0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGJsb2tqcy90cmlnZ2VyLXdvcmtlclxuICpcbiAqIFdvcmtlci1iYXNlZCB0cmlnZ2VyIGZvciBCbG9rIHdvcmtmbG93cy5cbiAqIFN1cHBvcnRzIGJhY2tncm91bmQgam9iIHByb2Nlc3Npbmcgd2l0aDpcbiAqIC0gQ29uZmlndXJhYmxlIGNvbmN1cnJlbmN5IHBlciBxdWV1ZVxuICogLSBBdXRvbWF0aWMgcmV0cmllcyB3aXRoIGV4cG9uZW50aWFsIGJhY2tvZmZcbiAqIC0gSm9iIHRpbWVvdXRzXG4gKiAtIFByaW9yaXR5LWJhc2VkIGpvYiBvcmRlcmluZ1xuICogLSBEZWxheWVkIGpvYiBzY2hlZHVsaW5nXG4gKiAtIFF1ZXVlIHN0YXRpc3RpY3MgYW5kIG1vbml0b3JpbmdcbiAqXG4gKiBBZGFwdGVyczpcbiAqIC0gQnVsbE1RIChSZWRpcy1iYWNrZWQsIHByb2R1Y3Rpb24pXG4gKiAtIEluTWVtb3J5IChkZXZlbG9wbWVudC90ZXN0aW5nKVxuICpcbiAqIEBleGFtcGxlIEJ1bGxNUVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgV29ya2VyVHJpZ2dlciwgQnVsbE1RQWRhcHRlciB9IGZyb20gXCJAYmxva2pzL3RyaWdnZXItd29ya2VyXCI7XG4gKlxuICogY2xhc3MgTXlXb3JrZXJUcmlnZ2VyIGV4dGVuZHMgV29ya2VyVHJpZ2dlciB7XG4gKiAgIHByb3RlY3RlZCBhZGFwdGVyID0gbmV3IEJ1bGxNUUFkYXB0ZXIoe1xuICogICAgIGhvc3Q6IFwibG9jYWxob3N0XCIsXG4gKiAgICAgcG9ydDogNjM3OSxcbiAqICAgfSk7XG4gKlxuICogICBwcm90ZWN0ZWQgbm9kZXMgPSBteU5vZGVzO1xuICogICBwcm90ZWN0ZWQgd29ya2Zsb3dzID0gbXlXb3JrZmxvd3M7XG4gKiB9XG4gKlxuICogY29uc3QgdHJpZ2dlciA9IG5ldyBNeVdvcmtlclRyaWdnZXIoKTtcbiAqIGF3YWl0IHRyaWdnZXIubGlzdGVuKCk7XG4gKlxuICogLy8gRGlzcGF0Y2ggYSBqb2JcbiAqIGF3YWl0IHRyaWdnZXIuZGlzcGF0Y2goXCJiYWNrZ3JvdW5kLWpvYnNcIiwgeyB1c2VySWQ6IFwiMTIzXCIgfSwge1xuICogICBwcmlvcml0eTogMTAsXG4gKiAgIHJldHJpZXM6IDMsXG4gKiAgIGRlbGF5OiA1MDAwLCAvLyBkZWxheSA1IHNlY29uZHNcbiAqIH0pO1xuICogYGBgXG4gKlxuICogQGV4YW1wbGUgSW5NZW1vcnkgKGRldmVsb3BtZW50KVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgV29ya2VyVHJpZ2dlciwgSW5NZW1vcnlBZGFwdGVyIH0gZnJvbSBcIkBibG9ranMvdHJpZ2dlci13b3JrZXJcIjtcbiAqXG4gKiBjbGFzcyBEZXZXb3JrZXJUcmlnZ2VyIGV4dGVuZHMgV29ya2VyVHJpZ2dlciB7XG4gKiAgIHByb3RlY3RlZCBhZGFwdGVyID0gbmV3IEluTWVtb3J5QWRhcHRlcigpO1xuICogICBwcm90ZWN0ZWQgbm9kZXMgPSBteU5vZGVzO1xuICogICBwcm90ZWN0ZWQgd29ya2Zsb3dzID0gbXlXb3JrZmxvd3M7XG4gKiB9XG4gKiBgYGBcbiAqL1xuXG4vLyBDb3JlIGV4cG9ydHNcbmV4cG9ydCB7XG5cdFdvcmtlclRyaWdnZXIsXG5cdHR5cGUgV29ya2VyQWRhcHRlcixcblx0dHlwZSBXb3JrZXJKb2IsXG5cdHR5cGUgV29ya2VyUXVldWVTdGF0cyxcbn0gZnJvbSBcIi4vV29ya2VyVHJpZ2dlclwiO1xuXG4vLyBBZGFwdGVyc1xuZXhwb3J0IHsgQnVsbE1RQWRhcHRlciwgdHlwZSBCdWxsTVFDb25maWcgfSBmcm9tIFwiLi9hZGFwdGVycy9CdWxsTVFBZGFwdGVyXCI7XG5leHBvcnQgeyBJbk1lbW9yeUFkYXB0ZXIgfSBmcm9tIFwiLi9hZGFwdGVycy9Jbk1lbW9yeUFkYXB0ZXJcIjtcbmV4cG9ydCB7IE5BVFNXb3JrZXJBZGFwdGVyLCB0eXBlIE5BVFNXb3JrZXJDb25maWcgfSBmcm9tIFwiLi9hZGFwdGVycy9OQVRTQWRhcHRlclwiO1xuXG4vLyBSZS1leHBvcnQgdHlwZXMgZnJvbSBoZWxwZXIgZm9yIGNvbnZlbmllbmNlXG5leHBvcnQgdHlwZSB7IFdvcmtlclRyaWdnZXJPcHRzIH0gZnJvbSBcIkBibG9ranMvaGVscGVyXCI7XG4iXX0=
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blokjs/trigger-worker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Worker-based trigger for Blok workflows - supports background job processing with concurrency, retries, and scheduling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
"author": "Deskree Technologies Inc.",
|
|
15
15
|
"license": "Apache-2.0",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@blokjs/helper": "^0.
|
|
18
|
-
"@blokjs/runner": "^0.
|
|
19
|
-
"@blokjs/shared": "^0.
|
|
17
|
+
"@blokjs/helper": "^0.4.0",
|
|
18
|
+
"@blokjs/runner": "^0.4.0",
|
|
19
|
+
"@blokjs/shared": "^0.4.0",
|
|
20
20
|
"@opentelemetry/api": "^1.9.0",
|
|
21
21
|
"uuid": "^11.1.0"
|
|
22
22
|
},
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"bullmq": "^5.67.2",
|
|
31
|
-
"ioredis": "^5.9.2"
|
|
31
|
+
"ioredis": "^5.9.2",
|
|
32
|
+
"nats": ""
|
|
32
33
|
},
|
|
33
34
|
"peerDependenciesMeta": {
|
|
34
35
|
"bullmq": {
|
|
@@ -36,6 +37,9 @@
|
|
|
36
37
|
},
|
|
37
38
|
"ioredis": {
|
|
38
39
|
"optional": true
|
|
40
|
+
},
|
|
41
|
+
"nats": {
|
|
42
|
+
"optional": true
|
|
39
43
|
}
|
|
40
44
|
},
|
|
41
45
|
"private": false,
|