velocious 1.0.626 → 1.0.628

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.
Files changed (81) hide show
  1. package/README.md +15 -3
  2. package/build/background-jobs/job-runner.js +9 -1
  3. package/build/background-jobs/local-dispatcher.js +23 -1
  4. package/build/background-jobs/main.js +6 -4
  5. package/build/background-jobs/perform-job.js +10 -1
  6. package/build/background-jobs/platform-job.js +62 -0
  7. package/build/background-jobs/runtime.js +6 -3
  8. package/build/background-jobs/types.js +8 -0
  9. package/build/background-jobs/worker.js +3 -1
  10. package/build/database/pool/async-tracked-multi-connection.js +46 -9
  11. package/build/database/pool/base.js +3 -0
  12. package/build/database/pool/checkout-timeout-error.js +16 -0
  13. package/build/http-client/websocket-client.js +52 -0
  14. package/build/http-server/client/index.js +6 -0
  15. package/build/http-server/client/websocket-session.js +30 -0
  16. package/build/http-server/index.js +202 -38
  17. package/build/http-server/worker-handler/index.js +15 -1
  18. package/build/http-server/worker-handler/worker-thread.js +8 -0
  19. package/build/src/background-jobs/job-runner.d.ts.map +1 -1
  20. package/build/src/background-jobs/job-runner.js +10 -2
  21. package/build/src/background-jobs/local-dispatcher.d.ts.map +1 -1
  22. package/build/src/background-jobs/local-dispatcher.js +24 -2
  23. package/build/src/background-jobs/main.d.ts.map +1 -1
  24. package/build/src/background-jobs/main.js +7 -5
  25. package/build/src/background-jobs/perform-job.d.ts +5 -1
  26. package/build/src/background-jobs/perform-job.d.ts.map +1 -1
  27. package/build/src/background-jobs/perform-job.js +11 -2
  28. package/build/src/background-jobs/platform-job.d.ts +34 -0
  29. package/build/src/background-jobs/platform-job.d.ts.map +1 -1
  30. package/build/src/background-jobs/platform-job.js +56 -1
  31. package/build/src/background-jobs/runtime.d.ts.map +1 -1
  32. package/build/src/background-jobs/runtime.js +7 -4
  33. package/build/src/background-jobs/types.d.ts +30 -0
  34. package/build/src/background-jobs/types.d.ts.map +1 -1
  35. package/build/src/background-jobs/types.js +9 -1
  36. package/build/src/background-jobs/worker.d.ts.map +1 -1
  37. package/build/src/background-jobs/worker.js +4 -2
  38. package/build/src/database/pool/async-tracked-multi-connection.d.ts +22 -2
  39. package/build/src/database/pool/async-tracked-multi-connection.d.ts.map +1 -1
  40. package/build/src/database/pool/async-tracked-multi-connection.js +44 -10
  41. package/build/src/database/pool/base.d.ts +15 -0
  42. package/build/src/database/pool/base.d.ts.map +1 -1
  43. package/build/src/database/pool/base.js +4 -1
  44. package/build/src/database/pool/checkout-timeout-error.d.ts +13 -0
  45. package/build/src/database/pool/checkout-timeout-error.d.ts.map +1 -0
  46. package/build/src/database/pool/checkout-timeout-error.js +15 -0
  47. package/build/src/http-client/websocket-client.d.ts +18 -0
  48. package/build/src/http-client/websocket-client.d.ts.map +1 -1
  49. package/build/src/http-client/websocket-client.js +48 -1
  50. package/build/src/http-server/client/index.d.ts.map +1 -1
  51. package/build/src/http-server/client/index.js +7 -1
  52. package/build/src/http-server/client/websocket-session.d.ts +6 -0
  53. package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
  54. package/build/src/http-server/client/websocket-session.js +27 -1
  55. package/build/src/http-server/index.d.ts +82 -10
  56. package/build/src/http-server/index.d.ts.map +1 -1
  57. package/build/src/http-server/index.js +186 -33
  58. package/build/src/http-server/worker-handler/index.d.ts +28 -1
  59. package/build/src/http-server/worker-handler/index.d.ts.map +1 -1
  60. package/build/src/http-server/worker-handler/index.js +23 -2
  61. package/build/src/http-server/worker-handler/worker-thread.d.ts.map +1 -1
  62. package/build/src/http-server/worker-handler/worker-thread.js +7 -1
  63. package/build/tsconfig.tsbuildinfo +1 -1
  64. package/package.json +1 -1
  65. package/src/background-jobs/job-runner.js +9 -1
  66. package/src/background-jobs/local-dispatcher.js +23 -1
  67. package/src/background-jobs/main.js +6 -4
  68. package/src/background-jobs/perform-job.js +10 -1
  69. package/src/background-jobs/platform-job.js +62 -0
  70. package/src/background-jobs/runtime.js +6 -3
  71. package/src/background-jobs/types.js +8 -0
  72. package/src/background-jobs/worker.js +3 -1
  73. package/src/database/pool/async-tracked-multi-connection.js +46 -9
  74. package/src/database/pool/base.js +3 -0
  75. package/src/database/pool/checkout-timeout-error.js +16 -0
  76. package/src/http-client/websocket-client.js +52 -0
  77. package/src/http-server/client/index.js +6 -0
  78. package/src/http-server/client/websocket-session.js +30 -0
  79. package/src/http-server/index.js +202 -38
  80. package/src/http-server/worker-handler/index.js +15 -1
  81. package/src/http-server/worker-handler/worker-thread.js +8 -0
@@ -6,6 +6,7 @@ import EventEmitter from "../utils/event-emitter.js"
6
6
  import InProcessHandler from "./worker-handler/in-process.js"
7
7
  import Logger from "../logger.js"
8
8
  import Net from "net"
9
+ import os from "node:os"
9
10
  import ServerClient from "./server-client.js"
10
11
  import WorkerHandler from "./worker-handler/index.js"
11
12
 
@@ -14,17 +15,18 @@ import WorkerHandler from "./worker-handler/index.js"
14
15
  * @typedef {{start: () => Promise<void>, stop: () => Promise<void>}} DevelopmentReloaderLike */
15
16
  /**
16
17
  * Defines this typedef.
17
- * @typedef {(args: {configuration: import("../configuration.js").default, workerCount: number}) => (WorkerHandler | InProcessHandler)} WorkerHandlerFactory */
18
+ * @typedef {(args: {configuration: import("../configuration.js").default, onWebsocketSessionOwned: (args: {sessionId: string, workerHandler: WorkerHandler}) => void, onWebsocketSessionReleased: (args: {sessionId: string, workerHandler: WorkerHandler}) => void, onWorkerStopped: (args: {workerHandler: WorkerHandler}) => void, workerCount: number}) => (WorkerHandler | InProcessHandler)} WorkerHandlerFactory */
18
19
 
19
20
  /**
20
21
  * Runs normalize worker count.
21
22
  * @param {object} args - Options object.
22
23
  * @param {number} [args.maxWorkers] - Backward-compatible worker count alias.
23
24
  * @param {number} [args.workers] - Configured worker count.
25
+ * @param {number} args.defaultWorkerCount - Process-available CPU count.
24
26
  * @returns {number} - Normalized worker count.
25
27
  */
26
- function normalizeWorkerCount({maxWorkers, workers}) {
27
- const workerCount = workers ?? maxWorkers ?? 1
28
+ function normalizeWorkerCount({defaultWorkerCount, maxWorkers, workers}) {
29
+ const workerCount = workers ?? maxWorkers ?? defaultWorkerCount
28
30
 
29
31
  if (!Number.isInteger(workerCount) || workerCount < 1) {
30
32
  throw new Error("HTTP server workers must be a positive integer")
@@ -33,6 +35,9 @@ function normalizeWorkerCount({maxWorkers, workers}) {
33
35
  return workerCount
34
36
  }
35
37
 
38
+ const MAX_INITIAL_REQUEST_HEADER_BYTES = 64 * 1024
39
+ const WEBSOCKET_SESSION_ROUTING_PARAMETER = "velociousSessionId"
40
+
36
41
  export default class VelociousHttpServer {
37
42
  clientCount = 0
38
43
  _starting = false
@@ -70,10 +75,8 @@ export default class VelociousHttpServer {
70
75
  * @type {Array<WorkerHandler | InProcessHandler>} */
71
76
  workerHandlers = []
72
77
  nextWorkerHandlerIndex = 0
73
- /**
74
- * Sticky worker handlers.
75
- * @type {Map<string, WorkerHandler | InProcessHandler>} */
76
- stickyWorkerHandlers = new Map()
78
+ /** Worker ownership for live or grace-paused resumable WebSocket sessions. */
79
+ websocketSessionOwners = new Map()
77
80
 
78
81
  /**
79
82
  * Runs constructor.
@@ -84,10 +87,11 @@ export default class VelociousHttpServer {
84
87
  * @param {number} [args.port] - Port.
85
88
  * @param {number} [args.maxWorkers] - Max workers.
86
89
  * @param {number} [args.workers] - Worker handlers to start.
90
+ * @param {() => number} [args.availableParallelism] - CPU availability owner seam.
87
91
  * @param {(args: {configuration: import("../configuration.js").default, onReload: (args: {changedPath: string}) => Promise<void>}) => {start: () => Promise<void>, stop: () => Promise<void>}} [args.developmentReloaderFactory] - Development reloader factory.
88
92
  * @param {WorkerHandlerFactory} [args.workerHandlerFactory] - Worker handler factory.
89
93
  */
90
- constructor({configuration, developmentReloaderFactory, host, inProcess, maxWorkers, port, workerHandlerFactory, workers}) {
94
+ constructor({availableParallelism = os.availableParallelism, configuration, developmentReloaderFactory, host, inProcess, maxWorkers, port, workerHandlerFactory, workers}) {
91
95
  this.configuration = configuration
92
96
  this.developmentReloaderFactory = developmentReloaderFactory
93
97
  this.workerHandlerFactory = workerHandlerFactory
@@ -95,7 +99,8 @@ export default class VelociousHttpServer {
95
99
  this.logger = new Logger(this)
96
100
  this.host = host ?? "0.0.0.0"
97
101
  this.port = port ?? 3006
98
- this.workers = normalizeWorkerCount({maxWorkers, workers})
102
+ this.workers = normalizeWorkerCount({defaultWorkerCount: availableParallelism(), maxWorkers, workers})
103
+ this.effectiveWorkers = this.inProcess && workers === undefined && maxWorkers === undefined ? 1 : this.workers
99
104
  }
100
105
 
101
106
  /**
@@ -167,7 +172,7 @@ export default class VelociousHttpServer {
167
172
  this.developmentReloader = startupState.developmentReloader
168
173
  this.netServer = startupState.netServer
169
174
  this.workerHandlers = startupState.workerHandlers
170
- this.stickyWorkerHandlers.clear()
175
+ this.websocketSessionOwners.clear()
171
176
  }
172
177
 
173
178
  /**
@@ -205,7 +210,7 @@ export default class VelociousHttpServer {
205
210
  * @returns {Promise<void>} - Resolves when complete.
206
211
  */
207
212
  async _ensureWorkers() {
208
- while (this.workerHandlers.length < this.workers) {
213
+ while (this.workerHandlers.length < this.effectiveWorkers) {
209
214
  await this.spawnWorker()
210
215
  }
211
216
  }
@@ -232,6 +237,7 @@ export default class VelociousHttpServer {
232
237
  activeSocketCount: this._activeSockets.size,
233
238
  clientCount: Object.keys(this.clients).length,
234
239
  configuredWorkerCount: this.workers,
240
+ effectiveWorkerCount: this.effectiveWorkers,
235
241
  inProcess: this.inProcess,
236
242
  workerCount: this.workerHandlers.length,
237
243
  workers: await Promise.all(this.workerHandlers.map((handler) => this.workerDebugSnapshot(handler)))
@@ -327,7 +333,7 @@ export default class VelociousHttpServer {
327
333
  const stopTasks = this.workerHandlers.map((handler) => handler.stop())
328
334
  await Promise.all(stopTasks)
329
335
  this.workerHandlers = []
330
- this.stickyWorkerHandlers.clear()
336
+ this.websocketSessionOwners.clear()
331
337
  }
332
338
 
333
339
  /**
@@ -367,9 +373,6 @@ export default class VelociousHttpServer {
367
373
  this.clientCount++
368
374
 
369
375
  try {
370
- // Paused WebSocket sessions are worker-local, so reconnects from
371
- // the same client address must return to the same worker.
372
- const workerHandler = this.workerHandlerToUse({stickyKey: socket.remoteAddress})
373
376
  const client = new ServerClient({
374
377
  clientCount,
375
378
  configuration: this.configuration,
@@ -377,16 +380,184 @@ export default class VelociousHttpServer {
377
380
  })
378
381
 
379
382
  client.events.on("close", this.onClientClose)
380
-
381
- this.logger.debug(`Gave client ${clientCount} to worker ${workerHandler.workerCount}`)
382
- workerHandler.addSocketConnection(client)
383
383
  this.clients[clientCount] = client
384
+ this.routeClientAfterInitialRoutingData(client)
384
385
  } catch (error) {
385
386
  this.logger.error(`Failed to initialize client ${clientCount} on new connection`, error)
386
387
  socket.destroy()
387
388
  }
388
389
  }
389
390
 
391
+ /**
392
+ * Buffers only the bounded initial request data needed to recognize a
393
+ * WebSocket resume routing hint, then replays it to the selected worker.
394
+ * @param {ServerClient} client - Unassigned socket client.
395
+ * @returns {void}
396
+ */
397
+ routeClientAfterInitialRoutingData(client) {
398
+ const {socket} = client
399
+ /** @type {Buffer[]} */
400
+ const chunks = []
401
+ let byteLength = 0
402
+ const cleanup = () => {
403
+ socket.off("data", onData)
404
+ socket.off("close", cleanup)
405
+ }
406
+ const onData = (/** @type {Buffer} */ chunk) => {
407
+ chunks.push(chunk)
408
+ byteLength += chunk.length
409
+ const initialRequest = Buffer.concat(chunks, byteLength)
410
+
411
+ if (this.initialRequestNeedsMoreRoutingData(initialRequest) && byteLength < MAX_INITIAL_REQUEST_HEADER_BYTES) return
412
+
413
+ cleanup()
414
+ this.assignClientToWorker(client, initialRequest)
415
+ }
416
+
417
+ socket.on("data", onData)
418
+ socket.once("close", cleanup)
419
+ }
420
+
421
+ /**
422
+ * Checks whether the buffered initial HTTP headers are complete.
423
+ * @param {Buffer} initialRequest - Buffered initial request bytes.
424
+ * @returns {boolean} - Whether a header terminator is present.
425
+ */
426
+ initialRequestHeadersComplete(initialRequest) {
427
+ return initialRequest.includes("\r\n\r\n") || initialRequest.includes("\n\n")
428
+ }
429
+
430
+ /**
431
+ * Checks whether a possible resumable WebSocket request still needs headers.
432
+ * Ordinary and malformed requests can reach the existing request parser as
433
+ * soon as their first line is complete.
434
+ * @param {Buffer} initialRequest - Buffered initial request bytes.
435
+ * @returns {boolean} - Whether more routing data is required.
436
+ */
437
+ initialRequestNeedsMoreRoutingData(initialRequest) {
438
+ if (this.initialRequestHeadersComplete(initialRequest)) return false
439
+
440
+ const lineEnd = initialRequest.indexOf("\n")
441
+
442
+ if (lineEnd === -1) return true
443
+
444
+ const requestLine = initialRequest.subarray(0, lineEnd).toString("latin1").replace(/\r$/, "")
445
+ const requestLineMatch = requestLine.match(/^GET ([^ ]+) HTTP\/[^ ]+$/)
446
+
447
+ if (!requestLineMatch) return false
448
+
449
+ try {
450
+ const requestUrl = new URL(requestLineMatch[1], "http://velocious.invalid")
451
+
452
+ return requestUrl.searchParams.has(WEBSOCKET_SESSION_ROUTING_PARAMETER)
453
+ } catch {
454
+ return false
455
+ }
456
+ }
457
+
458
+ /**
459
+ * Assigns a buffered client and replays the exact bytes into its worker.
460
+ * @param {ServerClient} client - Client awaiting assignment.
461
+ * @param {Buffer} initialRequest - Initial request bytes.
462
+ * @returns {void}
463
+ */
464
+ assignClientToWorker(client, initialRequest) {
465
+ if (client.socket.destroyed) return
466
+
467
+ try {
468
+ const workerHandler = this.workerHandlerForInitialRequest(initialRequest)
469
+
470
+ this.logger.debug(`Gave client ${client.clientCount} to worker ${workerHandler.workerCount}`)
471
+ workerHandler.addSocketConnection(client)
472
+ client.onSocketData(initialRequest)
473
+ } catch (error) {
474
+ this.logger.error(`Failed to assign client ${client.clientCount} to a worker`, error)
475
+ client.destroy(error instanceof Error ? error : new Error("Failed to assign HTTP client to worker", {cause: error}))
476
+ }
477
+ }
478
+
479
+ /**
480
+ * Selects the owner of a resumable WebSocket session or the next ordinary worker.
481
+ * @param {Buffer} initialRequest - Initial HTTP request headers.
482
+ * @returns {WorkerHandler | InProcessHandler} - Selected worker.
483
+ */
484
+ workerHandlerForInitialRequest(initialRequest) {
485
+ const sessionId = this.websocketResumeSessionId(initialRequest)
486
+
487
+ if (sessionId) {
488
+ const owner = this.websocketSessionOwners.get(sessionId)
489
+
490
+ if (owner && this.workerHandlers.includes(owner)) return owner
491
+ if (owner) this.websocketSessionOwners.delete(sessionId)
492
+ }
493
+
494
+ return this.workerHandlerToUse()
495
+ }
496
+
497
+ /**
498
+ * Reads the resumable WebSocket session routing hint from an upgrade request.
499
+ * @param {Buffer} initialRequest - Initial HTTP request headers.
500
+ * @returns {string | undefined} - Session identity, if present on a WebSocket upgrade.
501
+ */
502
+ websocketResumeSessionId(initialRequest) {
503
+ const headerEnd = initialRequest.indexOf("\r\n\r\n")
504
+ const fallbackHeaderEnd = headerEnd === -1 ? initialRequest.indexOf("\n\n") : headerEnd
505
+
506
+ if (fallbackHeaderEnd === -1) return
507
+
508
+ const lines = initialRequest.subarray(0, fallbackHeaderEnd).toString("latin1").split(/\r?\n/)
509
+ const [method, requestTarget] = lines[0]?.split(" ") || []
510
+
511
+ if (method !== "GET" || !requestTarget) return
512
+
513
+ /** @type {Map<string, string>} */
514
+ const headers = new Map()
515
+
516
+ for (const line of lines.slice(1)) {
517
+ const separatorIndex = line.indexOf(":")
518
+
519
+ if (separatorIndex === -1) continue
520
+
521
+ headers.set(line.slice(0, separatorIndex).trim().toLowerCase(), line.slice(separatorIndex + 1).trim().toLowerCase())
522
+ }
523
+
524
+ if (headers.get("upgrade") !== "websocket" || !headers.get("connection")?.split(",").map((value) => value.trim()).includes("upgrade")) return
525
+
526
+ const sessionId = new URL(requestTarget, "http://velocious.invalid").searchParams.get(WEBSOCKET_SESSION_ROUTING_PARAMETER)
527
+
528
+ return sessionId || undefined
529
+ }
530
+
531
+ /**
532
+ * Records the live worker owner for a resumable session.
533
+ * @param {{sessionId: string, workerHandler: WorkerHandler | InProcessHandler}} args - Ownership claim.
534
+ * @returns {void}
535
+ */
536
+ claimWebsocketSession({sessionId, workerHandler}) {
537
+ if (!this.workerHandlers.includes(workerHandler)) return
538
+ this.websocketSessionOwners.set(sessionId, workerHandler)
539
+ }
540
+
541
+ /**
542
+ * Releases a session only when the releasing worker still owns it.
543
+ * @param {{sessionId: string, workerHandler: WorkerHandler | InProcessHandler}} args - Ownership release.
544
+ * @returns {void}
545
+ */
546
+ releaseWebsocketSession({sessionId, workerHandler}) {
547
+ if (this.websocketSessionOwners.get(sessionId) === workerHandler) this.websocketSessionOwners.delete(sessionId)
548
+ }
549
+
550
+ /**
551
+ * Releases every session owned by a worker leaving service.
552
+ * @param {WorkerHandler | InProcessHandler} workerHandler - Worker leaving service.
553
+ * @returns {void}
554
+ */
555
+ releaseWebsocketSessionsForWorker(workerHandler) {
556
+ for (const [sessionId, owner] of this.websocketSessionOwners) {
557
+ if (owner === workerHandler) this.websocketSessionOwners.delete(sessionId)
558
+ }
559
+ }
560
+
390
561
  /**
391
562
  * On client close.
392
563
  * @param {ServerClient} client - Client instance.
@@ -425,7 +596,7 @@ export default class VelociousHttpServer {
425
596
  * @type {Array<WorkerHandler | InProcessHandler>} */
426
597
  const workerHandlers = []
427
598
 
428
- for (let index = 0; index < this.workers; index += 1) {
599
+ for (let index = 0; index < this.effectiveWorkers; index += 1) {
429
600
  workerHandlers.push(await this._buildWorkerHandler())
430
601
  }
431
602
 
@@ -443,9 +614,18 @@ export default class VelociousHttpServer {
443
614
 
444
615
  const Handler = this.inProcess ? InProcessHandler : WorkerHandler
445
616
  const workerHandler = this.workerHandlerFactory
446
- ? this.workerHandlerFactory({configuration: this.configuration, workerCount})
617
+ ? this.workerHandlerFactory({
618
+ configuration: this.configuration,
619
+ onWebsocketSessionOwned: ({sessionId, workerHandler}) => this.claimWebsocketSession({sessionId, workerHandler}),
620
+ onWebsocketSessionReleased: ({sessionId, workerHandler}) => this.releaseWebsocketSession({sessionId, workerHandler}),
621
+ onWorkerStopped: ({workerHandler}) => this.releaseWebsocketSessionsForWorker(workerHandler),
622
+ workerCount
623
+ })
447
624
  : new Handler({
448
625
  configuration: this.configuration,
626
+ onWebsocketSessionOwned: ({sessionId, workerHandler}) => this.claimWebsocketSession({sessionId, workerHandler}),
627
+ onWebsocketSessionReleased: ({sessionId, workerHandler}) => this.releaseWebsocketSession({sessionId, workerHandler}),
628
+ onWorkerStopped: ({workerHandler}) => this.releaseWebsocketSessionsForWorker(workerHandler),
449
629
  workerCount
450
630
  })
451
631
 
@@ -456,25 +636,9 @@ export default class VelociousHttpServer {
456
636
 
457
637
  /**
458
638
  * Runs worker handler to use.
459
- * @param {object} [args] - Options object.
460
- * @param {string} [args.stickyKey] - Stable key that must keep routing to the same worker.
461
639
  * @returns {WorkerHandler | InProcessHandler} - The worker handler to use.
462
640
  */
463
- workerHandlerToUse({stickyKey} = {}) {
464
- if (stickyKey) {
465
- const stickyWorkerHandler = this.stickyWorkerHandlers.get(stickyKey)
466
-
467
- if (stickyWorkerHandler && this.workerHandlers.includes(stickyWorkerHandler)) {
468
- return stickyWorkerHandler
469
- }
470
-
471
- const workerHandler = this._nextRoundRobinWorkerHandler()
472
-
473
- this.stickyWorkerHandlers.set(stickyKey, workerHandler)
474
-
475
- return workerHandler
476
- }
477
-
641
+ workerHandlerToUse() {
478
642
  return this._nextRoundRobinWorkerHandler()
479
643
  }
480
644
 
@@ -550,7 +714,7 @@ export default class VelociousHttpServer {
550
714
 
551
715
  this.workerHandlers = newWorkerHandlers
552
716
  this.nextWorkerHandlerIndex = 0
553
- this.stickyWorkerHandlers.clear()
717
+ for (const workerHandler of oldWorkerHandlers) this.releaseWebsocketSessionsForWorker(workerHandler)
554
718
 
555
719
  await Promise.all(oldWorkerHandlers.map((workerHandler) => workerHandler.stop()))
556
720
  } while (this._reloadWorkersForDevelopmentQueued && !this._stopping)
@@ -41,8 +41,11 @@ export default class VelociousHttpServerWorker {
41
41
  * @param {object} args - Options object.
42
42
  * @param {import("../../configuration.js").default} args.configuration - Configuration instance.
43
43
  * @param {number} args.workerCount - Worker count.
44
+ * @param {(args: {sessionId: string, workerHandler: VelociousHttpServerWorker}) => void} [args.onWebsocketSessionOwned] - Session ownership callback.
45
+ * @param {(args: {sessionId: string, workerHandler: VelociousHttpServerWorker}) => void} [args.onWebsocketSessionReleased] - Session ownership release callback.
46
+ * @param {(args: {workerHandler: VelociousHttpServerWorker}) => void} [args.onWorkerStopped] - Worker lifecycle callback.
44
47
  */
45
- constructor({configuration, workerCount}) {
48
+ constructor({configuration, onWebsocketSessionOwned, onWebsocketSessionReleased, onWorkerStopped, workerCount}) {
46
49
  this.configuration = configuration
47
50
 
48
51
  /**
@@ -52,6 +55,9 @@ export default class VelociousHttpServerWorker {
52
55
 
53
56
  this.logger = new Logger(this)
54
57
  this.workerCount = workerCount
58
+ this.onWebsocketSessionOwned = onWebsocketSessionOwned
59
+ this.onWebsocketSessionReleased = onWebsocketSessionReleased
60
+ this.onWorkerStopped = onWorkerStopped
55
61
  this.workerStarted = false
56
62
  this._stopping = false
57
63
  this._debugRequestId = 0
@@ -152,6 +158,7 @@ export default class VelociousHttpServerWorker {
152
158
  }
153
159
 
154
160
  this.unregisterFromEventsHostIfNeeded()
161
+ if (this.onWorkerStopped) this.onWorkerStopped({workerHandler: this})
155
162
  if (this._stopResolve) {
156
163
  this._stopResolve()
157
164
  }
@@ -190,6 +197,7 @@ export default class VelociousHttpServerWorker {
190
197
  * @param {number} [data.transferId] - File transfer id.
191
198
  * @param {boolean} [data.websocketFrame] - Whether output is a completed WebSocket frame.
192
199
  * @param {string} [data.channel] - Channel name.
200
+ * @param {string} [data.sessionId] - WebSocket session identity.
193
201
  * @param {number} [data.requestId] - Debug request id.
194
202
  * @param {Record<string, ReturnType<typeof JSON.parse>>} [data.snapshot] - Worker debug snapshot.
195
203
  * @param {ReturnType<typeof JSON.parse>} [data.payload] - Payload data.
@@ -306,6 +314,12 @@ export default class VelociousHttpServerWorker {
306
314
  channel,
307
315
  configuration: this.configuration
308
316
  })
317
+ } else if (command == "websocketSessionOwned") {
318
+ if (typeof data.sessionId !== "string") throw new Error("Worker websocket session id must be a string")
319
+ if (this.onWebsocketSessionOwned) this.onWebsocketSessionOwned({sessionId: data.sessionId, workerHandler: this})
320
+ } else if (command == "websocketSessionReleased") {
321
+ if (typeof data.sessionId !== "string") throw new Error("Worker websocket session id must be a string")
322
+ if (this.onWebsocketSessionReleased) this.onWebsocketSessionReleased({sessionId: data.sessionId, workerHandler: this})
309
323
  } else {
310
324
  throw new Error(`Unknown command: ${command}`)
311
325
  }
@@ -170,6 +170,14 @@ export default class VelociousHttpServerWorkerHandlerWorkerThread {
170
170
  this.parentPort.postMessage({command: "clientClose", clientCount, output})
171
171
  })
172
172
 
173
+ client.events.on("websocketSessionOwned", ({sessionId}) => {
174
+ this.parentPort.postMessage({command: "websocketSessionOwned", sessionId})
175
+ })
176
+
177
+ client.events.on("websocketSessionReleased", ({sessionId}) => {
178
+ this.parentPort.postMessage({command: "websocketSessionReleased", sessionId})
179
+ })
180
+
173
181
  this.clients[clientCount] = client
174
182
  }
175
183
 
@@ -1 +1 @@
1
- {"version":3,"file":"job-runner.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/job-runner.js"],"names":[],"mappings":"AASA,qBAAa,6BAA8B,SAAQ,KAAK;IACtD;;;OAGG;IACH,YAAY,KAAK,EAFN,KAEM,EAGhB;CACF;AA0DD;;;;;;;GAOG;AACH,wBAA8B,aAAa,CAAC,OAAO,EANxC,OAAO,YAAY,EAAE,oBAMmB,EAAE,EAAC,gBAAuB,EAAE,kBAAyB,EAAC,AALtG,CAGA,EAFA;IAA0B,gBAAgB,AAA1C,CACA,EADQ,OAAO,CACf;IAA0B,kBAAkB,AAA5C,CACA,EADQ,OAAO,CACf;CAE2G,GAFjG,OAAO,CAAC,WAAW,GAAG,aAAa,CAAC,CAsFhD"}
1
+ {"version":3,"file":"job-runner.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/job-runner.js"],"names":[],"mappings":"AASA,qBAAa,6BAA8B,SAAQ,KAAK;IACtD;;;OAGG;IACH,YAAY,KAAK,EAFN,KAEM,EAGhB;CACF;AA0DD;;;;;;;GAOG;AACH,wBAA8B,aAAa,CAAC,OAAO,EANxC,OAAO,YAAY,EAAE,oBAMmB,EAAE,EAAC,gBAAuB,EAAE,kBAAyB,EAAC,AALtG,CAGA,EAFA;IAA0B,gBAAgB,AAA1C,CACA,EADQ,OAAO,CACf;IAA0B,kBAAkB,AAA5C,CACA,EADQ,OAAO,CACf;CAE2G,GAFjG,OAAO,CAAC,WAAW,GAAG,aAAa,CAAC,CA8FhD"}
@@ -82,6 +82,14 @@ export default async function runJobPayload(payload, { closeConnections = true,
82
82
  await registry.load();
83
83
  const JobClass = registry.getJobByName(payload.jobName);
84
84
  const jobInstance = new JobClass();
85
+ const jobArgs = payload.args || [];
86
+ jobInstance._setBackgroundJobContext({
87
+ args: jobArgs,
88
+ jobClass: JobClass,
89
+ jobName: payload.jobName,
90
+ options: payload.options || {},
91
+ payload
92
+ });
85
93
  /**
86
94
  * Perform.
87
95
  * @type {(...args: Array<ReturnType<typeof JSON.parse>>) => Promise<void>} */
@@ -95,7 +103,7 @@ export default async function runJobPayload(payload, { closeConnections = true,
95
103
  try {
96
104
  try {
97
105
  await configuration.withConnections({ databaseIdentifiers: JobClass.databaseIdentifiers, name: `Background job runner: ${payload.jobName}` }, async () => {
98
- await perform.apply(jobInstance, payload.args || []);
106
+ await perform.apply(jobInstance, jobArgs);
99
107
  });
100
108
  }
101
109
  catch (error) {
@@ -155,4 +163,4 @@ export default async function runJobPayload(payload, { closeConnections = true,
155
163
  }
156
164
  }
157
165
  }
158
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iLXJ1bm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvam9iLXJ1bm5lci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxxQkFBcUIsTUFBTSw4QkFBOEIsQ0FBQTtBQUNoRSxPQUFPLHFCQUFxQixNQUFNLG1CQUFtQixDQUFBO0FBQ3JELE9BQU8sNEJBQTRCLE1BQU0sc0JBQXNCLENBQUE7QUFDL0QsT0FBTyw2QkFBNkIsTUFBTSx3QkFBd0IsQ0FBQTtBQUVsRSxNQUFNLHVCQUF1QixHQUFHLElBQUksQ0FBQTtBQUVwQyxNQUFNLE9BQU8sNkJBQThCLFNBQVEsS0FBSztJQUN0RDs7O09BR0c7SUFDSCxZQUFZLEtBQUs7UUFDZixLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFDLEtBQUssRUFBQyxDQUFDLENBQUE7UUFDN0IsSUFBSSxDQUFDLElBQUksR0FBRywrQkFBK0IsQ0FBQTtJQUM3QyxDQUFDO0NBQ0Y7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsc0JBQXNCLENBQUMsYUFBYSxFQUFFLEtBQUs7SUFDbEQsTUFBTSxXQUFXLEdBQUcsYUFBYSxDQUFDLGNBQWMsRUFBRSxDQUFBO0lBQ2xELE1BQU0sZUFBZSxHQUFHLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7SUFDakYsTUFBTSxPQUFPLEdBQUc7UUFDZCxPQUFPLEVBQUUsRUFBQyxRQUFRLEVBQUUsd0JBQXdCLEVBQUUsS0FBSyxFQUFFLGNBQWMsRUFBQztRQUNwRSxLQUFLLEVBQUUsZUFBZTtLQUN2QixDQUFBO0lBQ0QsTUFBTSxXQUFXLEdBQUcsV0FBVyxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUM7V0FDL0QsV0FBVyxDQUFDLGFBQWEs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QUFFLEtBQUs7aUJBQ3JCLENBQUMsQ0FBQTtZQUNKLENBQUM7WUFFRCxNQUFNLElBQUksNkJBQTZCLENBQUMsY0FBYyxDQUFDLENBQUE7UUFDekQsQ0FBQztRQUVELElBQUksT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2YsTUFBTSxRQUFRLENBQUMsZUFBZSxDQUFDO2dCQUM3QixLQUFLLEVBQUUsT0FBTyxDQUFDLEVBQUU7Z0JBQ2pCLE1BQU0sRUFBRSxXQUFXO2dCQUNuQixTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVM7Z0JBQzVCLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtnQkFDMUIsYUFBYSxFQUFFLE9BQU8sQ0FBQyxhQUFhO2dCQUNwQyxhQUFhLEVBQUUsS0FBSzthQUNyQixDQUFDLENBQUE7UUFDSixDQUFDO1FBQ0QsT0FBTyxXQUFXLENBQUE7SUFDcEIsQ0FBQztZQUFTLENBQUM7UUFDVCwwRUFBMEU7UUFDMUUsMERBQTBEO1FBQzFELElBQUksa0JBQWtCO1lBQUUsT0FBTyxDQUFDLEtBQUssR0FBRyxhQUFhLENBQUE7UUFDckQsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3JCLElBQUksQ0FBQztnQkFDSCxNQUFNLGFBQWEsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO1lBQ3hDLENBQUM7b0JBQVMsQ0FBQztnQkFDVCxNQUFNLGFBQWEsQ0FBQyx3QkFBd0IsRUFBRSxDQUFBO1lBQ2hELENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IGNvbmZpZ3VyYXRpb25SZXNvbHZlciBmcm9tIFwiLi4vY29uZmlndXJhdGlvbi1yZXNvbHZlci5qc1wiXG5pbXBvcnQgQmFja2dyb3VuZEpvYlJlZ2lzdHJ5IGZyb20gXCIuL2pvYi1yZWdpc3RyeS5qc1wiXG5pbXBvcnQgQmFja2dyb3VuZEpvYnNTdGF0dXNSZXBvcnRlciBmcm9tIFwiLi9zdGF0dXMtcmVwb3J0ZXIuanNcIlxuaW1wb3J0IEJhY2tncm91bmRKb2JSZXNjaGVkdWxlU2lnbmFsIGZyb20gXCIuL3Jlc2NoZWR1bGUtc2lnbmFsLmpzXCJcblxuY29uc3QgQkVBQ09OX1JFQURZX1RJTUVPVVRfTVMgPSA1MDAwXG5cbmV4cG9ydCBjbGFzcyBCYWNrZ3JvdW5kSm9iUGVyZm9ybWVkRmFpbHVyZSBleHRlbmRzIEVycm9yIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBwZXJmb3JtZWQtam9iIGZhaWx1cmUgYWZ0ZXIgaXRzIHRlcm1pbmFsIHJlcG9ydCBpcyBhY2tub3dsZWRnZWQuXG4gICAqIEBwYXJhbSB7RXJyb3J9IGNhdXNlIC0gQSBqb2IgcGVyZm9ybSBlcnJvciB3aG9zZSBmYWlsZWQgdGVybWluYWwgcmVwb3J0IHdhcyBhY2tub3dsZWRnZWQuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihjYXVzZSkge1xuICAgIHN1cGVyKGNhdXNlLm1lc3NhZ2UsIHtjYXVzZX0pXG4gICAgdGhpcy5uYW1lID0gXCJCYWNrZ3JvdW5kSm9iUGVyZm9ybWVkRmFpbHVyZVwiXG4gIH1cbn1cblxuLyoqXG4gKiBSdW5zIHJlcG9ydCBiZWFjb24gcmVhZHkgZXJyb3IuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24uanNcIikuZGVmYXVsdH0gY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24uXG4gKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSBlcnJvciAtIEJlYWNvbiByZWFkaW5lc3MgZXJyb3IuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gcmVwb3J0QmVhY29uUmVhZHlFcnJvcihjb25maWd1cmF0aW9uLCBlcnJvcikge1xuICBjb25zdCBlcnJvckV2ZW50cyA9IGNvbmZpZ3VyYXRpb24uZ2V0RXJyb3JFdmVudHMoKVxuICBjb25zdCBub3JtYWxpemVkRXJyb3IgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiBuZXcgRXJyb3IoU3RyaW5nKGVycm9yKSlcbiAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICBjb250ZXh0OiB7cGVlclR5cGU6IFwiYmFja2dyb3VuZC1qb2JzLXJ1bm5lclwiLCBzdGFnZTogXCJiZWFjb24tcmVhZHlcIn0sXG4gICAgZXJyb3I6IG5vcm1hbGl6ZWRFcnJvclxuICB9XG4gIGNvbnN0IGhhc0xpc3RlbmVyID0gZXJyb3JFdmVudHMubGlzdGVuZXJDb3VudChcImZyYW1ld29yay1lcnJvclwiKSA+IDBcbiAgICB8fCBlcnJvckV2ZW50cy5saXN0ZW5lckNvdW50KFwiYWxsLWVycm9yXCIpID4gMFxuXG4gIGVycm9yRXZlbnRzLmVtaXQoXCJmcmFtZXdvcmstZXJyb3JcIiwgcGF5bG9hZClcbiAgZXJyb3JFdmVudHMuZW1pdChcImFsbC1lcnJvclwiLCB7Li4ucGF5bG9hZCwgZXJyb3JUeXBlOiBcImZyYW1ld29yay1lcnJvclwifSlcblxuICBpZiAoIWhhc0xpc3RlbmVyKSB7XG4gICAgY29uc29sZS5lcnJvcihgW3ZlbG9jaW91cyBmcmFtZXdvcmstZXJyb3Igc3RhZ2U9YmVhY29uLXJlYWR5XSAke25vcm1hbGl6ZWRFcnJvci5tZXNzYWdlfWApXG4gIH1cbn1cblxuLyoqXG4gKiBSdW5zIGNvbm5lY3QgYmVhY29uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9IGNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uLlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNvbm5lY3RCZWFjb24oY29uZmlndXJhdGlvbikge1xuICBjb25zdCBiZWFjb25DbGllbnQgPSBhd2FpdCBjb25maWd1cmF0aW9uLmNvbm5lY3RCZWFjb24oe3BlZXJUeXBlOiBcImJhY2tncm91bmQtam9icy1ydW5uZXJcIn0pXG5cbiAgaWYgKCFiZWFjb25DbGllbnQpIHJldHVyblxuXG4gIHRyeSB7XG4gICAgYXdhaXQgYmVhY29uQ2xpZW50LndhaXRGb3JSZWFkeSh7dGltZW91dE1zOiBCRUFDT05fUkVBRFlfVElNRU9VVF9NU30pXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmVwb3J0QmVhY29uUmVhZHlFcnJvcihjb25maWd1cmF0aW9uLCBlcnJvcilcbiAgfVxufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSBwcm9jZXNzIHRpdGxlIHRvIHNob3cgd2hpbGUgYSBqb2IgcnVuczogdGhlIGpvYiBjbGFzcydzIGRlY2xhcmVkXG4gKiBgc3RhdGljIHByb2Nlc3NUaXRsZWAsIGVsc2UgYSBgdmVsb2Npb3VzIGpvYi1ydW5uZXI6IDxKb2JOYW1lPmAgZmFsbGJhY2suXG4gKiBAcGFyYW0ge3R5cGVvZiBpbXBvcnQoXCIuL2pvYi5qc1wiKS5kZWZhdWx0fSBKb2JDbGFzcyAtIFJlc29sdmVkIGpvYiBjbGFzcy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5CYWNrZ3JvdW5kSm9iUGF5bG9hZH0gcGF5bG9hZCAtIFBheWxvYWQuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIFByb2Nlc3MgdGl0bGUuXG4gKi9cbmZ1bmN0aW9uIHJ1bm5lclByb2Nlc3NUaXRsZShKb2JDbGFzcywgcGF5bG9hZCkge1xuICBjb25zdCBkZWNsYXJlZCA9IEpvYkNsYXNzLnByb2Nlc3NUaXRsZVxuXG4gIGlmICh0eXBlb2YgZGVjbGFyZWQgPT09IFwic3RyaW5nXCIgJiYgZGVjbGFyZWQubGVuZ3RoID4gMCkgcmV0dXJuIGRlY2xhcmVkXG5cbiAgcmV0dXJuIGB2ZWxvY2lvdXMgam9iLXJ1bm5lcjogJHtwYXlsb2FkLmpvYk5hbWV9YFxufVxuXG4vKipcbiAqIFJ1bnMgcnVuIGpvYiBwYXlsb2FkLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJhY2tncm91bmRKb2JQYXlsb2FkfSBwYXlsb2FkIC0gUGF5bG9hZC5cbiAqIEBwYXJhbSB7b2JqZWN0fSBbb3B0aW9uc10gLSBSdW5uZXIgb3B0aW9ucy5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMuY2xvc2VDb25uZWN0aW9uc10gLSBXaGV0aGVyIHRvIGdyYWNlZnVsbHkgY2xvc2UgZnJhbWV3b3JrIGNvbm5lY3Rpb25zIGFmdGVyIHRoZSBqb2IuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLm1hbmFnZVByb2Nlc3NUaXRsZV0gLSBXaGV0aGVyIHRvIHNldCB0aGUgcGVyLWpvYiBwcm9jZXNzIHRpdGxlIGFuZCByZXN0b3JlIGl0IGFmdGVyd2FyZHMuIE9mZiBmb3IgY29uY3VycmVudCBwb29sZWQgcnVubmVycywgd2hlcmUgaW50ZXJsZWF2ZWQgc25hcHNob3QvcmVzdG9yZSBvZiB0aGUgc2luZ2xlIHByb2Nlc3Mtd2lkZSBgcHJvY2Vzcy50aXRsZWAgd291bGQgY29ycnVwdCBpdDsgdGhlIHBvb2xlZCBjaGlsZCBvd25zIGFuIGFnZ3JlZ2F0ZSB0aXRsZSBpbnN0ZWFkLlxuICogQHJldHVybnMge1Byb21pc2U8XCJjb21wbGV0ZWRcIiB8IFwicmVzY2hlZHVsZWRcIj59IC0gQWNrbm93bGVkZ2VkIG91dGNvbWUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIHJ1bkpvYlBheWxvYWQocGF5bG9hZCwge2Nsb3NlQ29ubmVjdGlvbnMgPSB0cnVlLCBtYW5hZ2VQcm9jZXNzVGl0bGUgPSB0cnVlfSA9IHt9KSB7XG4gIGNvbnN0IGNvbmZpZ3VyYXRpb24gPSBhd2FpdCBjb25maWd1cmF0aW9uUmVzb2x2ZXIoKVxuICBjb25maWd1cmF0aW9uLnNldEN1cnJlbnQoKVxuICBhd2FpdCBjb25maWd1cmF0aW9uLmluaXRpYWxpemUoe3R5cGU6IFwiYmFja2dyb3VuZC1qb2JzLXJ1bm5lclwifSlcbiAgYXdhaXQgY29ubmVjdEJlYWNvbihjb25maWd1cmF0aW9uKVxuICBjb25zdCByZXBvcnRlciA9IG5ldyBCYWNrZ3JvdW5kSm9ic1N0YXR1c1JlcG9ydGVyKHtjb25maWd1cmF0aW9ufSlcblxuICBjb25zdCByZWdpc3RyeSA9IG5ldyBCYWNrZ3JvdW5kSm9iUmVnaXN0cnkoe2NvbmZpZ3VyYXRpb259KVxuICBhd2FpdCByZWdpc3RyeS5sb2FkKClcbiAgY29uc3QgSm9iQ2xhc3MgPSByZWdpc3RyeS5nZXRKb2JCeU5hbWUocGF5bG9hZC5qb2JOYW1lKVxuICBjb25zdCBqb2JJbnN0YW5jZSA9IG5ldyBKb2JDbGFzcygpXG4gIC8qKlxuICAgKiBQZXJmb3JtLlxuICAgKiBAdHlwZSB7KC4uLmFyZ3M6IEFycmF5PFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+PikgPT4gUHJvbWlzZTx2b2lkPn0gKi9cbiAgY29uc3QgcGVyZm9ybSA9IGpvYkluc3RhbmNlLnBlcmZvcm1cblxuICAvLyBOYW1lIHRoZSBwcm9jZXNzIGFmdGVyIHRoZSBqb2IgaXQgaXMgcnVubmluZyBzbyBgcHNgL2B0b3BgIHNob3cgd2hhdCBlYWNoXG4gIC8vIHJ1bm5lciBpcyBkb2luZzsgcmVzdG9yZWQgaW4gdGhlIGBmaW5hbGx5YCBiZWxvdyB3aGVuIHRoZSBqb2IgZmluaXNoZXMuXG4gIC8vIFNraXBwZWQgZm9yIGNvbmN1cnJlbnQgcG9vbGVkIHJ1bm5lcnMsIHdob3NlIGNoaWxkIG93bnMgYW4gYWdncmVnYXRlIHRpdGxlLlxuICBjb25zdCBwcmV2aW91c1RpdGxlID0gcHJvY2Vzcy50aXRsZVxuICBpZiAobWFuYWdlUHJvY2Vzc1RpdGxlKSBwcm9jZXNzLnRpdGxlID0gcnVubmVyUHJvY2Vzc1RpdGxlKEpvYkNsYXNzLCBwYXlsb2FkKVxuXG4gIHRyeSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGNvbmZpZ3VyYXRpb24ud2l0aENvbm5lY3Rpb25zKHtkYXRhYmFzZUlkZW50aWZpZXJzOiBKb2JDbGFzcy5kYXRhYmFzZUlkZW50aWZpZXJzLCBuYW1lOiBgQmFja2dyb3VuZCBqb2IgcnVubmVyOiAke3BheWxvYWQuam9iTmFtZX1gfSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCBwZXJmb3JtLmFwcGx5KGpvYkluc3RhbmNlLCBwYXlsb2FkLmFyZ3MgfHwgW10pXG4gICAgICB9KVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBCYWNrZ3JvdW5kSm9iUmVzY2hlZHVsZVNpZ25hbCkge1xuICAgICAgICBpZiAocGF5bG9hZC5pZCkge1xuICAgICAgICAgIGF3YWl0IHJlcG9ydGVyLnJlcG9ydFdpdGhSZXRyeSh7XG4gICAgICAgICAgICBqb2JJZDogcGF5bG9hZC5pZCxcbiAgICAgICAgICAgIHN0YXR1czogXCJyZXNjaGVkdWxlZFwiLFxuICAgICAgICAgICAgZGVsYXlNczogZXJyb3IuZGVsYXlNcyxcbiAgICAgICAgICAgIGhhbmRvZmZJZDogcGF5bG9hZC5oYW5kb2ZmSWQsXG4gICAgICAgICAgICB3b3JrZXJJZDogcGF5bG9hZC53b3JrZXJJZCxcbiAgICAgICAgICAgIGhhbmRlZE9mZkF0TXM6IHBheWxvYWQuaGFuZGVkT2ZmQXRNcyxcbiAgICAgICAgICAgIG1heER1cmF0aW9uTXM6IDMwMDAwLFxuICAgICAgICAgICAgcmV0cnlQZXJzaXN0RXJyb3JzOiB0cnVlXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBcInJlc2NoZWR1bGVkXCJcbiAgICAgIH1cblxuICAgICAgY29uc3QgcGVyZm9ybWVkRXJyb3IgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiBuZXcgRXJyb3IoU3RyaW5nKGVycm9yKSlcbiAgICAgIGlmIChwYXlsb2FkLmlkKSB7XG4gICAgICAgIGF3YWl0IHJlcG9ydGVyLnJlcG9ydFdpdGhSZXRyeSh7XG4gICAgICAgICAgam9iSWQ6IHBheWxvYWQuaWQsXG4gICAgICAgICAgc3RhdHVzOiBcImZhaWxlZFwiLFxuICAgICAgICAgIGVycm9yOiBwZXJmb3JtZWRFcnJvcixcbiAgICAgICAgICBoYW5kb2ZmSWQ6IHBheWxvYWQuaGFuZG9mZklkLFxuICAgICAgICAgIHdvcmtlcklkOiBwYXlsb2FkLndvcmtlcklkLFxuICAgICAgICAgIGhhbmRlZE9mZkF0TXM6IHBheWxvYWQuaGFuZGVkT2ZmQXRNcyxcbiAgICAgICAgICBtYXhEdXJhdGlvbk1zOiAzMDAwMFxuICAgICAgICB9KVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBuZXcgQmFja2dyb3VuZEpvYlBlcmZvcm1lZEZhaWx1cmUocGVyZm9ybWVkRXJyb3IpXG4gICAgfVxuXG4gICAgaWYgKHBheWxvYWQuaWQpIHtcbiAgICAgIGF3YWl0IHJlcG9ydGVyLnJlcG9ydFdpdGhSZXRyeSh7XG4gICAgICAgIGpvYklkOiBwYXlsb2FkLmlkLFxuICAgICAgICBzdGF0dXM6IFwiY29tcGxldGVkXCIsXG4gICAgICAgIGhhbmRvZmZJZDogcGF5bG9hZC5oYW5kb2ZmSWQsXG4gICAgICAgIHdvcmtlcklkOiBwYXlsb2FkLndvcmtlcklkLFxuICAgICAgICBoYW5kZWRPZmZBdE1zOiBwYXlsb2FkLmhhbmRlZE9mZkF0TXMsXG4gICAgICAgIG1heER1cmF0aW9uTXM6IDMwMDAwXG4gICAgICB9KVxuICAgIH1cbiAgICByZXR1cm4gXCJjb21wbGV0ZWRcIlxuICB9IGZpbmFsbHkge1xuICAgIC8vIFJlc3RvcmUgdGhlIHJ1bm5lcidzIGJhc2UgdGl0bGUgc28gYSBsaW5nZXJpbmcvaWRsZSBydW5uZXIgKG9yIGEgcmV1c2VkXG4gICAgLy8gb25lKSBkb2Vzbid0IG1pc3JlcG9ydCBhIGZpbmlzaGVkIGpvYiBhcyBzdGlsbCBydW5uaW5nLlxuICAgIGlmIChtYW5hZ2VQcm9jZXNzVGl0bGUpIHByb2Nlc3MudGl0bGUgPSBwcmV2aW91c1RpdGxlXG4gICAgaWYgKGNsb3NlQ29ubmVjdGlvbnMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGNvbmZpZ3VyYXRpb24uZGlzY29ubmVjdEJlYWNvbigpXG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBjb25maWd1cmF0aW9uLmNsb3NlRGF0YWJhc2VDb25uZWN0aW9ucygpXG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=
166
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iLXJ1bm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvam9iLXJ1bm5lci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxxQkFBcUIsTUFBTSw4QkFBOEIsQ0FBQTtBQUNoRSxPQUFPLHFCQUFxQixNQUFNLG1CQUFtQixDQUFBO0FBQ3JELE9BQU8sNEJBQTRCLE1BQU0sc0JBQXNCLENBQUE7QUFDL0QsT0FBTyw2QkFBNkIsTUFBTSx3QkFBd0IsQ0FBQTtBQUVsRSxNQUFNLHVCQUF1QixHQUFHLElBQUksQ0FBQTtBQUVwQyxNQUFNLE9BQU8sNkJBQThCLFNBQVEsS0FBSztJQUN0RDs7O09BR0c7SUFDSCxZQUFZLEtBQUs7UUFDZixLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFDLEtBQUssRUFBQyxDQUFDLENBQUE7UUFDN0IsSUFBSSxDQUFDLElBQUksR0FBRywrQkFBK0IsQ0FBQTtJQUM3QyxDQUFDO0NBQ0Y7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsc0JBQXNCLENBQUMsYUFBYSxFQUFFLEtBQUs7SUFDbEQsTUFBTSxXQUFXLEdBQUcsYUFBYSxDQUFDLGNBQWMsRUFBRSxDQUFBO0lBQ2xELE1BQU0sZUFBZSxHQUFHLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7SUFDakYsTUFBTSxPQUFPLEdBQUc7UUFDZCxPQUFPLEVBQUUsRUFBQyxRQUFRLEVBQUUsd0JBQXdCLEVBQUUsS0FBSyxFQUFFLGNBQWMsRUFBQztRQUNwRSxLQUFLLEVBQUUsZUFBZTtLQUN2QixDQUFBO0lBQ0QsTUFBTSxXQUFXLEdBQUcsV0FBVyxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUM7V0FDL0QsV0FBVyxDQUFDLGFBQWEs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dXJhdGlvblJlc29sdmVyIGZyb20gXCIuLi9jb25maWd1cmF0aW9uLXJlc29sdmVyLmpzXCJcbmltcG9ydCBCYWNrZ3JvdW5kSm9iUmVnaXN0cnkgZnJvbSBcIi4vam9iLXJlZ2lzdHJ5LmpzXCJcbmltcG9ydCBCYWNrZ3JvdW5kSm9ic1N0YXR1c1JlcG9ydGVyIGZyb20gXCIuL3N0YXR1cy1yZXBvcnRlci5qc1wiXG5pbXBvcnQgQmFja2dyb3VuZEpvYlJlc2NoZWR1bGVTaWduYWwgZnJvbSBcIi4vcmVzY2hlZHVsZS1zaWduYWwuanNcIlxuXG5jb25zdCBCRUFDT05fUkVBRFlfVElNRU9VVF9NUyA9IDUwMDBcblxuZXhwb3J0IGNsYXNzIEJhY2tncm91bmRKb2JQZXJmb3JtZWRGYWlsdXJlIGV4dGVuZHMgRXJyb3Ige1xuICAvKipcbiAgICogQ3JlYXRlcyBhIHBlcmZvcm1lZC1qb2IgZmFpbHVyZSBhZnRlciBpdHMgdGVybWluYWwgcmVwb3J0IGlzIGFja25vd2xlZGdlZC5cbiAgICogQHBhcmFtIHtFcnJvcn0gY2F1c2UgLSBBIGpvYiBwZXJmb3JtIGVycm9yIHdob3NlIGZhaWxlZCB0ZXJtaW5hbCByZXBvcnQgd2FzIGFja25vd2xlZGdlZC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGNhdXNlKSB7XG4gICAgc3VwZXIoY2F1c2UubWVzc2FnZSwge2NhdXNlfSlcbiAgICB0aGlzLm5hbWUgPSBcIkJhY2tncm91bmRKb2JQZXJmb3JtZWRGYWlsdXJlXCJcbiAgfVxufVxuXG4vKipcbiAqIFJ1bnMgcmVwb3J0IGJlYWNvbiByZWFkeSBlcnJvci5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBjb25maWd1cmF0aW9uIC0gQ29uZmlndXJhdGlvbi5cbiAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IGVycm9yIC0gQmVhY29uIHJlYWRpbmVzcyBlcnJvci5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiByZXBvcnRCZWFjb25SZWFkeUVycm9yKGNvbmZpZ3VyYXRpb24sIGVycm9yKSB7XG4gIGNvbnN0IGVycm9yRXZlbnRzID0gY29uZmlndXJhdGlvbi5nZXRFcnJvckV2ZW50cygpXG4gIGNvbnN0IG5vcm1hbGl6ZWRFcnJvciA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKVxuICBjb25zdCBwYXlsb2FkID0ge1xuICAgIGNvbnRleHQ6IHtwZWVyVHlwZTogXCJiYWNrZ3JvdW5kLWpvYnMtcnVubmVyXCIsIHN0YWdlOiBcImJlYWNvbi1yZWFkeVwifSxcbiAgICBlcnJvcjogbm9ybWFsaXplZEVycm9yXG4gIH1cbiAgY29uc3QgaGFzTGlzdGVuZXIgPSBlcnJvckV2ZW50cy5saXN0ZW5lckNvdW50KFwiZnJhbWV3b3JrLWVycm9yXCIpID4gMFxuICAgIHx8IGVycm9yRXZlbnRzLmxpc3RlbmVyQ291bnQoXCJhbGwtZXJyb3JcIikgPiAwXG5cbiAgZXJyb3JFdmVudHMuZW1pdChcImZyYW1ld29yay1lcnJvclwiLCBwYXlsb2FkKVxuICBlcnJvckV2ZW50cy5lbWl0KFwiYWxsLWVycm9yXCIsIHsuLi5wYXlsb2FkLCBlcnJvclR5cGU6IFwiZnJhbWV3b3JrLWVycm9yXCJ9KVxuXG4gIGlmICghaGFzTGlzdGVuZXIpIHtcbiAgICBjb25zb2xlLmVycm9yKGBbdmVsb2Npb3VzIGZyYW1ld29yay1lcnJvciBzdGFnZT1iZWFjb24tcmVhZHldICR7bm9ybWFsaXplZEVycm9yLm1lc3NhZ2V9YClcbiAgfVxufVxuXG4vKipcbiAqIFJ1bnMgY29ubmVjdCBiZWFjb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24uanNcIikuZGVmYXVsdH0gY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24uXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY29ubmVjdEJlYWNvbihjb25maWd1cmF0aW9uKSB7XG4gIGNvbnN0IGJlYWNvbkNsaWVudCA9IGF3YWl0IGNvbmZpZ3VyYXRpb24uY29ubmVjdEJlYWNvbih7cGVlclR5cGU6IFwiYmFja2dyb3VuZC1qb2JzLXJ1bm5lclwifSlcblxuICBpZiAoIWJlYWNvbkNsaWVudCkgcmV0dXJuXG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBiZWFjb25DbGllbnQud2FpdEZvclJlYWR5KHt0aW1lb3V0TXM6IEJFQUNPTl9SRUFEWV9USU1FT1VUX01TfSlcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICByZXBvcnRCZWFjb25SZWFkeUVycm9yKGNvbmZpZ3VyYXRpb24sIGVycm9yKVxuICB9XG59XG5cbi8qKlxuICogUmVzb2x2ZXMgdGhlIHByb2Nlc3MgdGl0bGUgdG8gc2hvdyB3aGlsZSBhIGpvYiBydW5zOiB0aGUgam9iIGNsYXNzJ3MgZGVjbGFyZWRcbiAqIGBzdGF0aWMgcHJvY2Vzc1RpdGxlYCwgZWxzZSBhIGB2ZWxvY2lvdXMgam9iLXJ1bm5lcjogPEpvYk5hbWU+YCBmYWxsYmFjay5cbiAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4vam9iLmpzXCIpLmRlZmF1bHR9IEpvYkNsYXNzIC0gUmVzb2x2ZWQgam9iIGNsYXNzLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJhY2tncm91bmRKb2JQYXlsb2FkfSBwYXlsb2FkIC0gUGF5bG9hZC5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IC0gUHJvY2VzcyB0aXRsZS5cbiAqL1xuZnVuY3Rpb24gcnVubmVyUHJvY2Vzc1RpdGxlKEpvYkNsYXNzLCBwYXlsb2FkKSB7XG4gIGNvbnN0IGRlY2xhcmVkID0gSm9iQ2xhc3MucHJvY2Vzc1RpdGxlXG5cbiAgaWYgKHR5cGVvZiBkZWNsYXJlZCA9PT0gXCJzdHJpbmdcIiAmJiBkZWNsYXJlZC5sZW5ndGggPiAwKSByZXR1cm4gZGVjbGFyZWRcblxuICByZXR1cm4gYHZlbG9jaW91cyBqb2ItcnVubmVyOiAke3BheWxvYWQuam9iTmFtZX1gXG59XG5cbi8qKlxuICogUnVucyBydW4gam9iIHBheWxvYWQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuQmFja2dyb3VuZEpvYlBheWxvYWR9IHBheWxvYWQgLSBQYXlsb2FkLlxuICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXSAtIFJ1bm5lciBvcHRpb25zLlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5jbG9zZUNvbm5lY3Rpb25zXSAtIFdoZXRoZXIgdG8gZ3JhY2VmdWxseSBjbG9zZSBmcmFtZXdvcmsgY29ubmVjdGlvbnMgYWZ0ZXIgdGhlIGpvYi5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMubWFuYWdlUHJvY2Vzc1RpdGxlXSAtIFdoZXRoZXIgdG8gc2V0IHRoZSBwZXItam9iIHByb2Nlc3MgdGl0bGUgYW5kIHJlc3RvcmUgaXQgYWZ0ZXJ3YXJkcy4gT2ZmIGZvciBjb25jdXJyZW50IHBvb2xlZCBydW5uZXJzLCB3aGVyZSBpbnRlcmxlYXZlZCBzbmFwc2hvdC9yZXN0b3JlIG9mIHRoZSBzaW5nbGUgcHJvY2Vzcy13aWRlIGBwcm9jZXNzLnRpdGxlYCB3b3VsZCBjb3JydXB0IGl0OyB0aGUgcG9vbGVkIGNoaWxkIG93bnMgYW4gYWdncmVnYXRlIHRpdGxlIGluc3RlYWQuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxcImNvbXBsZXRlZFwiIHwgXCJyZXNjaGVkdWxlZFwiPn0gLSBBY2tub3dsZWRnZWQgb3V0Y29tZS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gcnVuSm9iUGF5bG9hZChwYXlsb2FkLCB7Y2xvc2VDb25uZWN0aW9ucyA9IHRydWUsIG1hbmFnZVByb2Nlc3NUaXRsZSA9IHRydWV9ID0ge30pIHtcbiAgY29uc3QgY29uZmlndXJhdGlvbiA9IGF3YWl0IGNvbmZpZ3VyYXRpb25SZXNvbHZlcigpXG4gIGNvbmZpZ3VyYXRpb24uc2V0Q3VycmVudCgpXG4gIGF3YWl0IGNvbmZpZ3VyYXRpb24uaW5pdGlhbGl6ZSh7dHlwZTogXCJiYWNrZ3JvdW5kLWpvYnMtcnVubmVyXCJ9KVxuICBhd2FpdCBjb25uZWN0QmVhY29uKGNvbmZpZ3VyYXRpb24pXG4gIGNvbnN0IHJlcG9ydGVyID0gbmV3IEJhY2tncm91bmRKb2JzU3RhdHVzUmVwb3J0ZXIoe2NvbmZpZ3VyYXRpb259KVxuXG4gIGNvbnN0IHJlZ2lzdHJ5ID0gbmV3IEJhY2tncm91bmRKb2JSZWdpc3RyeSh7Y29uZmlndXJhdGlvbn0pXG4gIGF3YWl0IHJlZ2lzdHJ5LmxvYWQoKVxuICBjb25zdCBKb2JDbGFzcyA9IHJlZ2lzdHJ5LmdldEpvYkJ5TmFtZShwYXlsb2FkLmpvYk5hbWUpXG4gIGNvbnN0IGpvYkluc3RhbmNlID0gbmV3IEpvYkNsYXNzKClcbiAgY29uc3Qgam9iQXJncyA9IHBheWxvYWQuYXJncyB8fCBbXVxuICBqb2JJbnN0YW5jZS5fc2V0QmFja2dyb3VuZEpvYkNvbnRleHQoe1xuICAgIGFyZ3M6IGpvYkFyZ3MsXG4gICAgam9iQ2xhc3M6IEpvYkNsYXNzLFxuICAgIGpvYk5hbWU6IHBheWxvYWQuam9iTmFtZSxcbiAgICBvcHRpb25zOiBwYXlsb2FkLm9wdGlvbnMgfHwge30sXG4gICAgcGF5bG9hZFxuICB9KVxuICAvKipcbiAgICogUGVyZm9ybS5cbiAgICogQHR5cGUgeyguLi5hcmdzOiBBcnJheTxSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj4pID0+IFByb21pc2U8dm9pZD59ICovXG4gIGNvbnN0IHBlcmZvcm0gPSBqb2JJbnN0YW5jZS5wZXJmb3JtXG5cbiAgLy8gTmFtZSB0aGUgcHJvY2VzcyBhZnRlciB0aGUgam9iIGl0IGlzIHJ1bm5pbmcgc28gYHBzYC9gdG9wYCBzaG93IHdoYXQgZWFjaFxuICAvLyBydW5uZXIgaXMgZG9pbmc7IHJlc3RvcmVkIGluIHRoZSBgZmluYWxseWAgYmVsb3cgd2hlbiB0aGUgam9iIGZpbmlzaGVzLlxuICAvLyBTa2lwcGVkIGZvciBjb25jdXJyZW50IHBvb2xlZCBydW5uZXJzLCB3aG9zZSBjaGlsZCBvd25zIGFuIGFnZ3JlZ2F0ZSB0aXRsZS5cbiAgY29uc3QgcHJldmlvdXNUaXRsZSA9IHByb2Nlc3MudGl0bGVcbiAgaWYgKG1hbmFnZVByb2Nlc3NUaXRsZSkgcHJvY2Vzcy50aXRsZSA9IHJ1bm5lclByb2Nlc3NUaXRsZShKb2JDbGFzcywgcGF5bG9hZClcblxuICB0cnkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjb25maWd1cmF0aW9uLndpdGhDb25uZWN0aW9ucyh7ZGF0YWJhc2VJZGVudGlmaWVyczogSm9iQ2xhc3MuZGF0YWJhc2VJZGVudGlmaWVycywgbmFtZTogYEJhY2tncm91bmQgam9iIHJ1bm5lcjogJHtwYXlsb2FkLmpvYk5hbWV9YH0sIGFzeW5jICgpID0+IHtcbiAgICAgICAgYXdhaXQgcGVyZm9ybS5hcHBseShqb2JJbnN0YW5jZSwgam9iQXJncylcbiAgICAgIH0pXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEJhY2tncm91bmRKb2JSZXNjaGVkdWxlU2lnbmFsKSB7XG4gICAgICAgIGlmIChwYXlsb2FkLmlkKSB7XG4gICAgICAgICAgYXdhaXQgcmVwb3J0ZXIucmVwb3J0V2l0aFJldHJ5KHtcbiAgICAgICAgICAgIGpvYklkOiBwYXlsb2FkLmlkLFxuICAgICAgICAgICAgc3RhdHVzOiBcInJlc2NoZWR1bGVkXCIsXG4gICAgICAgICAgICBkZWxheU1zOiBlcnJvci5kZWxheU1zLFxuICAgICAgICAgICAgaGFuZG9mZklkOiBwYXlsb2FkLmhhbmRvZmZJZCxcbiAgICAgICAgICAgIHdvcmtlcklkOiBwYXlsb2FkLndvcmtlcklkLFxuICAgICAgICAgICAgaGFuZGVkT2ZmQXRNczogcGF5bG9hZC5oYW5kZWRPZmZBdE1zLFxuICAgICAgICAgICAgbWF4RHVyYXRpb25NczogMzAwMDAsXG4gICAgICAgICAgICByZXRyeVBlcnNpc3RFcnJvcnM6IHRydWVcbiAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFwicmVzY2hlZHVsZWRcIlxuICAgICAgfVxuXG4gICAgICBjb25zdCBwZXJmb3JtZWRFcnJvciA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKVxuICAgICAgaWYgKHBheWxvYWQuaWQpIHtcbiAgICAgICAgYXdhaXQgcmVwb3J0ZXIucmVwb3J0V2l0aFJldHJ5KHtcbiAgICAgICAgICBqb2JJZDogcGF5bG9hZC5pZCxcbiAgICAgICAgICBzdGF0dXM6IFwiZmFpbGVkXCIsXG4gICAgICAgICAgZXJyb3I6IHBlcmZvcm1lZEVycm9yLFxuICAgICAgICAgIGhhbmRvZmZJZDogcGF5bG9hZC5oYW5kb2ZmSWQsXG4gICAgICAgICAgd29ya2VySWQ6IHBheWxvYWQud29ya2VySWQsXG4gICAgICAgICAgaGFuZGVkT2ZmQXRNczogcGF5bG9hZC5oYW5kZWRPZmZBdE1zLFxuICAgICAgICAgIG1heER1cmF0aW9uTXM6IDMwMDAwXG4gICAgICAgIH0pXG4gICAgICB9XG5cbiAgICAgIHRocm93IG5ldyBCYWNrZ3JvdW5kSm9iUGVyZm9ybWVkRmFpbHVyZShwZXJmb3JtZWRFcnJvcilcbiAgICB9XG5cbiAgICBpZiAocGF5bG9hZC5pZCkge1xuICAgICAgYXdhaXQgcmVwb3J0ZXIucmVwb3J0V2l0aFJldHJ5KHtcbiAgICAgICAgam9iSWQ6IHBheWxvYWQuaWQsXG4gICAgICAgIHN0YXR1czogXCJjb21wbGV0ZWRcIixcbiAgICAgICAgaGFuZG9mZklkOiBwYXlsb2FkLmhhbmRvZmZJZCxcbiAgICAgICAgd29ya2VySWQ6IHBheWxvYWQud29ya2VySWQsXG4gICAgICAgIGhhbmRlZE9mZkF0TXM6IHBheWxvYWQuaGFuZGVkT2ZmQXRNcyxcbiAgICAgICAgbWF4RHVyYXRpb25NczogMzAwMDBcbiAgICAgIH0pXG4gICAgfVxuICAgIHJldHVybiBcImNvbXBsZXRlZFwiXG4gIH0gZmluYWxseSB7XG4gICAgLy8gUmVzdG9yZSB0aGUgcnVubmVyJ3MgYmFzZSB0aXRsZSBzbyBhIGxpbmdlcmluZy9pZGxlIHJ1bm5lciAob3IgYSByZXVzZWRcbiAgICAvLyBvbmUpIGRvZXNuJ3QgbWlzcmVwb3J0IGEgZmluaXNoZWQgam9iIGFzIHN0aWxsIHJ1bm5pbmcuXG4gICAgaWYgKG1hbmFnZVByb2Nlc3NUaXRsZSkgcHJvY2Vzcy50aXRsZSA9IHByZXZpb3VzVGl0bGVcbiAgICBpZiAoY2xvc2VDb25uZWN0aW9ucykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgY29uZmlndXJhdGlvbi5kaXNjb25uZWN0QmVhY29uKClcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IGNvbmZpZ3VyYXRpb24uY2xvc2VEYXRhYmFzZUNvbm5lY3Rpb25zKClcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdfQ==
@@ -1 +1 @@
1
- {"version":3,"file":"local-dispatcher.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/local-dispatcher.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local-dispatcher.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/local-dispatcher.js"],"names":[],"mappings":"AAKI,YAAiI,iCAAiC,GAAxJ;IAAC,IAAI,EAAE,WAAW,CAAA;CAAC,GAAG;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAA;CAAC,GAAG;IAAC,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAmC;AAGnK,YAAkB,wCAAwC,GAC1D;;;;IAA8C,eAAe,EAAlD,iCAAiC,CAC5C;;;;IAAsD,OAAO,EAAlD,OAAO,YAAY,EAAE,oBAAoB,CACpD;;;;IAAkD,GAAG,EAA1C,OAAO,YAAY,EAAE,gBAAgB,CAClD;CAAA,CAAA;AAKD,qEAAqE;AACrE,MAAM,CAAC,OAAO,OAAO,6BAA6B;IAUzC,KAAK;IACL,aAAa;IACb,QAAQ;IACR,KAAK;IACL,UAAU;IACV,QAAQ;IACb,mCAAmC;IAC9B,aAAa,EADP,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAE/B,mCAAmC;IAC9B,aAAa,EADP,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAE1B,QAAQ;IACR,WAAW;IAChB,iCAAiC;IAC5B,SAAS,EADH,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7B,oEAAoE;IAC/D,wBAAwB,EADlB,GAAG,CAAC,MAAM,EAAE,wCAAwC,CAAC;IAEhE,8BAA8B;IACzB,YAAY,EADN,GAAG,CAAC,MAAM,IAAI,CAAC;IAE1B,iEAAiE;IAC5D,eAAe,EADT,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,MAAM,GAAG,SAAS;IAE7D,iEAAiE;IAC5D,cAAc,EADR,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,MAAM,GAAG,SAAS;IA7B/D;;;;;;;OAOG;IACH,YAAY,EAAC,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAC,EALhD;QAAoD,aAAa,EAAzD,OAAO,qBAAqB,EAAE,OAAO,CAC7C;QAA4D,KAAK,EAAzD,OAAO,YAAY,EAAE,wBAAwB,CACrD;QAAwD,QAAQ,EAAxD,OAAO,yBAAyB,EAAE,OAAO,CACjD;QAAiD,KAAK,EAA9C,OAAO,kBAAkB,EAAE,OAAO,CAC5C;KACkD,EAuBlD;IAED;;;OAGG;IACG,KAAK,IAFE,OAAO,CAAC,IAAI,CAAC,CAmCzB;IAED;;;OAGG;IACH,IAAI,IAFS,IAAI,CAgChB;IAED;;;OAGG;IACG,MAAM,IAFC,OAAO,CAAC,IAAI,CAAC,CAqBzB;IAED;;;;OAIG;IACH,iBAAiB,CAAC,EAAC,OAAO,EAAE,GAAG,EAAC,EAHrB;QAAC,OAAO,EAAE,OAAO,YAAY,EAAE,oBAAoB,CAAC;QAAC,GAAG,EAAE,OAAO,YAAY,EAAE,gBAAgB,CAAA;KAG1E,GAFnB,IAAI,CAahB;IAED;;;;OAIG;IACG,QAAQ,CAAC,EAAC,OAAO,EAAE,GAAG,EAAC,EAHlB;QAAC,OAAO,EAAE,OAAO,YAAY,EAAE,oBAAoB,CAAC;QAAC,GAAG,EAAE,OAAO,YAAY,EAAE,gBAAgB,CAAA;KAG7E,GAFhB,OAAO,CAAC,IAAI,CAAC,CAmDzB;IAED;;;;OAIG;IACG,YAAY,CAAC,EAAC,eAAe,EAAE,OAAO,EAAE,GAAG,EAAC,EAHvC,wCAGuC,GAFrC,OAAO,CAAC,IAAI,CAAC,CAgBzB;IAED;;;;OAIG;IACG,6BAA6B,CAAC,EAAC,YAAoB,EAAC,AAHvD,CACA,EADQ;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAG6B,GAFlD,OAAO,CAAC,IAAI,CAAC,CAazB;IAED;;;OAGG;IACG,kBAAkB,IAFX,OAAO,CAAC,IAAI,CAAC,CAmBzB;IAED;;;OAGG;IACH,iBAAiB,IAFJ,IAAI,CAShB;IAED;;;OAGG;IACG,WAAW,IAFJ,OAAO,CAAC,IAAI,CAAC,CAMzB;IAED;;;OAGG;IACG,IAAI,IAFG,OAAO,CAAC,IAAI,CAAC,CAsBzB;IAED;;;OAGG;IACH,OAAO,IAFM,OAAO,CAEiC;IAErD;;;OAGG;IACH,kBAAkB,IAFL,MAAM,CAEiF;IAEpG;;;OAGG;IACH,sBAAsB,IAFT,MAAM,CAEyE;IAE5F;;;OAGG;IACH,OAAO,IAFM,OAAO,CAInB;IAED;;;OAGG;IACH,mBAAmB,IAFN,IAAI,CAShB;IAED;;;;OAIG;IACH,wBAAwB,CAAC,EAAC,KAAK,EAAE,GAAG,EAAC,EAH1B;QAAC,KAAK,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;QAAC,GAAG,EAAE,OAAO,YAAY,EAAE,gBAAgB,CAAA;KAGvD,GAFxB,IAAI,CAuBhB;IAED;;;;OAIG;IACH,2BAA2B,CAAC,EAAC,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAC,EAHvD,wCAAwC,GAAG;QAAC,KAAK,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAA;KAGzB,GAFrD,IAAI,CAchB;IAED;;;;;;;OAOG;IACH,qBAAqB,CAAC,EAAC,OAAY,EAAE,KAAK,EAAE,KAAK,EAAC,EAL/C;QAA6D,OAAO,AAApE,CACA,EADQ,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CACrD;QAA4C,KAAK,EAAzC,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CACrC;QAAqB,KAAK,EAAlB,MAAM,CACd;KAE+C,GAFrC,IAAI,CAShB;CACF"}