@spine-event-engine/server 2.0.0-snapshot.23 → 2.0.0-snapshot.24
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/REFERENCE.md +89 -23
- package/dist/bus/event-bus.d.ts +65 -100
- package/dist/bus/event-bus.d.ts.map +1 -1
- package/dist/bus/event-bus.js +46 -116
- package/dist/bus/event-bus.js.map +1 -1
- package/dist/bus/saved-dispatcher-binding.d.ts +1 -44
- package/dist/bus/saved-dispatcher-binding.d.ts.map +1 -1
- package/dist/bus/saved-dispatcher-binding.js +0 -8
- package/dist/bus/saved-dispatcher-binding.js.map +1 -1
- package/dist/context/bounded-context.d.ts +9 -10
- package/dist/context/bounded-context.d.ts.map +1 -1
- package/dist/context/bounded-context.js +64 -43
- package/dist/context/bounded-context.js.map +1 -1
- package/dist/context/entity-inbox.d.ts.map +1 -1
- package/dist/context/entity-inbox.js +21 -7
- package/dist/context/entity-inbox.js.map +1 -1
- package/dist/context/local-inbox-handoff.d.ts +1 -0
- package/dist/context/local-inbox-handoff.d.ts.map +1 -1
- package/dist/context/local-inbox-handoff.js +31 -1
- package/dist/context/local-inbox-handoff.js.map +1 -1
- package/dist/context/projection-handoff.d.ts.map +1 -1
- package/dist/context/projection-handoff.js +2 -0
- package/dist/context/projection-handoff.js.map +1 -1
- package/dist/delivery/delivery-monitor.d.ts +12 -9
- package/dist/delivery/delivery-monitor.d.ts.map +1 -1
- package/dist/delivery/delivery-monitor.js +15 -9
- package/dist/delivery/delivery-monitor.js.map +1 -1
- package/dist/delivery/delivery-ports.d.ts +6 -13
- package/dist/delivery/delivery-ports.d.ts.map +1 -1
- package/dist/delivery/delivery-run-control.d.ts +15 -0
- package/dist/delivery/delivery-run-control.d.ts.map +1 -1
- package/dist/delivery/delivery-run-control.js.map +1 -1
- package/dist/delivery/delivery-supervisor.d.ts +33 -5
- package/dist/delivery/delivery-supervisor.d.ts.map +1 -1
- package/dist/delivery/delivery-supervisor.js +150 -22
- package/dist/delivery/delivery-supervisor.js.map +1 -1
- package/dist/delivery/delivery.d.ts.map +1 -1
- package/dist/delivery/delivery.js +128 -54
- package/dist/delivery/delivery.js.map +1 -1
- package/dist/delivery/inbox-storage.d.ts +8 -11
- package/dist/delivery/inbox-storage.d.ts.map +1 -1
- package/dist/delivery/inbox-storage.js +33 -76
- package/dist/delivery/inbox-storage.js.map +1 -1
- package/dist/delivery/inbox.d.ts +9 -12
- package/dist/delivery/inbox.d.ts.map +1 -1
- package/dist/delivery/inbox.js +10 -13
- package/dist/delivery/inbox.js.map +1 -1
- package/dist/delivery/reception-observation.d.ts +56 -0
- package/dist/delivery/reception-observation.d.ts.map +1 -0
- package/dist/delivery/reception-observation.js +67 -0
- package/dist/delivery/reception-observation.js.map +1 -0
- package/dist/repository/repository.d.ts +3 -4
- package/dist/repository/repository.d.ts.map +1 -1
- package/dist/repository/repository.js +155 -166
- package/dist/repository/repository.js.map +1 -1
- package/dist/runtime/runtime.d.ts +11 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +13 -0
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/signal-metadata.d.ts.map +1 -1
- package/dist/runtime/signal-metadata.js +3 -10
- package/dist/runtime/signal-metadata.js.map +1 -1
- package/dist/runtime/signal-publisher.d.ts +11 -33
- package/dist/runtime/signal-publisher.d.ts.map +1 -1
- package/dist/runtime/signal-publisher.js +70 -55
- package/dist/runtime/signal-publisher.js.map +1 -1
- package/dist/runtime/standalone-handler-runtime.d.ts.map +1 -1
- package/dist/runtime/standalone-handler-runtime.js +1 -31
- package/dist/runtime/standalone-handler-runtime.js.map +1 -1
- package/dist/server/environment-delivery-worker.d.ts.map +1 -1
- package/dist/server/environment-delivery-worker.js +305 -5
- package/dist/server/environment-delivery-worker.js.map +1 -1
- package/dist/server/managed-server-application.d.ts +2 -2
- package/dist/server/managed-server-application.d.ts.map +1 -1
- package/dist/server/managed-server-application.js +467 -177
- package/dist/server/managed-server-application.js.map +1 -1
- package/dist/server/node-coordinator.d.ts +14 -0
- package/dist/server/node-coordinator.d.ts.map +1 -1
- package/dist/server/node-coordinator.js +266 -45
- package/dist/server/node-coordinator.js.map +1 -1
- package/dist/server/server-log.d.ts.map +1 -1
- package/dist/server/server-log.js +4 -0
- package/dist/server/server-log.js.map +1 -1
- package/dist/server/server.js +20 -7
- package/dist/server/server.js.map +1 -1
- package/dist/services/spine-services.d.ts.map +1 -1
- package/dist/services/spine-services.js +200 -72
- package/dist/services/spine-services.js.map +1 -1
- package/dist/stand/event-origin-filter.d.ts +16 -0
- package/dist/stand/event-origin-filter.d.ts.map +1 -0
- package/dist/stand/event-origin-filter.js +124 -0
- package/dist/stand/event-origin-filter.js.map +1 -0
- package/dist/stand/subscription-observer.d.ts.map +1 -1
- package/dist/stand/subscription-observer.js +7 -0
- package/dist/stand/subscription-observer.js.map +1 -1
- package/dist/stand/subscription-runtime.d.ts +18 -1
- package/dist/stand/subscription-runtime.d.ts.map +1 -1
- package/dist/stand/subscription-runtime.js +32 -4
- package/dist/stand/subscription-runtime.js.map +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +2 -2
- package/dist/testing/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +15 -15
|
@@ -19,6 +19,7 @@ import { CommandSchema, EventSchema } from "@spine-event-engine/proto";
|
|
|
19
19
|
import { deliveryRunWorkers, } from "../delivery/delivery-run-coordinator.js";
|
|
20
20
|
import { DeliveryBuilder, UniformAcrossAllShards } from "../delivery/delivery-builder.js";
|
|
21
21
|
import { Delivery, } from "../delivery/delivery.js";
|
|
22
|
+
import { receptionObservation } from "../delivery/reception-observation.js";
|
|
22
23
|
import { DeliverySupervisor, deliverySupervisorAccess, } from "../delivery/delivery-supervisor.js";
|
|
23
24
|
import { DeliveryWorker } from "../delivery/delivery-worker.js";
|
|
24
25
|
import { ShardIndex } from "../delivery/shard-index.js";
|
|
@@ -214,6 +215,12 @@ export class EnvironmentDeliveryWorker {
|
|
|
214
215
|
const failures = retired.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
215
216
|
EnvironmentDeliveryValues.throwFailures(failures, "Environment registration worker retirement failed.");
|
|
216
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* Finds the configured worker for an owner key.
|
|
220
|
+
*
|
|
221
|
+
* @param key The worker or group key.
|
|
222
|
+
* @returns The result of this delivery operation.
|
|
223
|
+
*/
|
|
217
224
|
#requiredWorker(key) {
|
|
218
225
|
const worker = this.#workers.get(key);
|
|
219
226
|
if (worker === undefined) {
|
|
@@ -221,6 +228,13 @@ export class EnvironmentDeliveryWorker {
|
|
|
221
228
|
}
|
|
222
229
|
return worker;
|
|
223
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Stops one configured owner worker and collects failures.
|
|
233
|
+
*
|
|
234
|
+
* @param key The worker or group key.
|
|
235
|
+
* @param worker The runtime delivery worker.
|
|
236
|
+
* @param failures The failures to propagate.
|
|
237
|
+
*/
|
|
224
238
|
#stopOwner(key, worker, failures) {
|
|
225
239
|
if (!this.#stoppedWorkers.has(key)) {
|
|
226
240
|
try {
|
|
@@ -239,14 +253,28 @@ export class EnvironmentDeliveryWorker {
|
|
|
239
253
|
}
|
|
240
254
|
}
|
|
241
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Coordinates supervisor groups for one environment generation.
|
|
258
|
+
*/
|
|
242
259
|
class RuntimeDeliverySupervisor {
|
|
243
260
|
#groups = new Map();
|
|
244
261
|
#ports;
|
|
245
262
|
#nodeId;
|
|
263
|
+
/**
|
|
264
|
+
* Creates the delivery component with its configured dependencies.
|
|
265
|
+
*
|
|
266
|
+
* @param ports The optional delivery ports.
|
|
267
|
+
* @param nodeId The worker node identity.
|
|
268
|
+
*/
|
|
246
269
|
constructor(ports, nodeId) {
|
|
247
270
|
this.#ports = ports;
|
|
248
271
|
this.#nodeId = nodeId;
|
|
249
272
|
}
|
|
273
|
+
/**
|
|
274
|
+
* Adds the configured delivery runtime or shards.
|
|
275
|
+
*
|
|
276
|
+
* @param runtime The configured context delivery runtime.
|
|
277
|
+
*/
|
|
250
278
|
add(runtime) {
|
|
251
279
|
const grouped = new Map();
|
|
252
280
|
for (const shard of EnvironmentDeliveryValues.uniqueShards(runtime.scopes)) {
|
|
@@ -267,10 +295,20 @@ class RuntimeDeliverySupervisor {
|
|
|
267
295
|
group.add(runtime.owner.key, runtime, shards);
|
|
268
296
|
}
|
|
269
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Removes an owner route from this runtime.
|
|
300
|
+
*
|
|
301
|
+
* @param ownerKey The configured owner key.
|
|
302
|
+
*/
|
|
270
303
|
remove(ownerKey) {
|
|
271
304
|
for (const group of this.#groups.values())
|
|
272
305
|
group.remove(ownerKey);
|
|
273
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* Starts the configured delivery worker or supervisor.
|
|
309
|
+
*
|
|
310
|
+
* @returns The result of this delivery operation.
|
|
311
|
+
*/
|
|
274
312
|
async start() {
|
|
275
313
|
if (!managedDeliveryActivated) {
|
|
276
314
|
waitingManagedSupervisors.add(() => {
|
|
@@ -282,16 +320,39 @@ class RuntimeDeliverySupervisor {
|
|
|
282
320
|
return;
|
|
283
321
|
await Promise.all(Array.from(this.#groups.values(), (group) => group.start()));
|
|
284
322
|
}
|
|
323
|
+
/**
|
|
324
|
+
* Notifies the selected delivery scope or shard.
|
|
325
|
+
*
|
|
326
|
+
* @param ownerKey The configured owner key.
|
|
327
|
+
* @param shard The shard to process.
|
|
328
|
+
*/
|
|
285
329
|
notify(ownerKey, shard) {
|
|
286
330
|
this.#groups.get(this.#groupKey(ownerKey, shard.ofTotal))?.notify(shard);
|
|
287
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* Marks the selected owners as unavailable for new route admission.
|
|
334
|
+
*
|
|
335
|
+
* @param ownerKeys The owner keys in this generation.
|
|
336
|
+
*/
|
|
288
337
|
fenceOwners(ownerKeys) {
|
|
289
338
|
for (const group of this.#groups.values())
|
|
290
339
|
group.fenceOwners(ownerKeys);
|
|
291
340
|
}
|
|
341
|
+
/**
|
|
342
|
+
* Waits for admitted work for the selected owners to settle.
|
|
343
|
+
*
|
|
344
|
+
* @param ownerKeys The owner keys in this generation.
|
|
345
|
+
* @returns The result of this delivery operation.
|
|
346
|
+
*/
|
|
292
347
|
async awaitOwnersSettled(ownerKeys) {
|
|
293
348
|
await Promise.all(Array.from(this.#groups.values(), (group) => group.awaitOwnersSettled(ownerKeys)));
|
|
294
349
|
}
|
|
350
|
+
/**
|
|
351
|
+
* Closes the selected owners after admitted work settles.
|
|
352
|
+
*
|
|
353
|
+
* @param ownerKeys The owner keys in this generation.
|
|
354
|
+
* @returns The result of this delivery operation.
|
|
355
|
+
*/
|
|
295
356
|
async retireOwners(ownerKeys) {
|
|
296
357
|
for (const [key, group] of this.#groups) {
|
|
297
358
|
await group.retireOwners(ownerKeys);
|
|
@@ -299,6 +360,9 @@ class RuntimeDeliverySupervisor {
|
|
|
299
360
|
this.#groups.delete(key);
|
|
300
361
|
}
|
|
301
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Stops admission and starts delivery shutdown.
|
|
365
|
+
*/
|
|
302
366
|
stop() {
|
|
303
367
|
const failures = [];
|
|
304
368
|
for (const group of this.#groups.values()) {
|
|
@@ -311,20 +375,40 @@ class RuntimeDeliverySupervisor {
|
|
|
311
375
|
}
|
|
312
376
|
EnvironmentDeliveryValues.throwFailures(failures, "Environment delivery supervisor stop failed.");
|
|
313
377
|
}
|
|
378
|
+
/**
|
|
379
|
+
* Waits for the active delivery work to settle.
|
|
380
|
+
*
|
|
381
|
+
* @returns The result of this delivery operation.
|
|
382
|
+
*/
|
|
314
383
|
async awaitSettled() {
|
|
315
384
|
const settled = await Promise.allSettled(Array.from(this.#groups.values(), (group) => group.awaitSettled()));
|
|
316
385
|
EnvironmentDeliveryValues.throwFailures(settled.flatMap((result) => (result.status === "rejected" ? [result.reason] : [])), "Environment delivery supervisor settlement failed.");
|
|
317
386
|
}
|
|
387
|
+
/**
|
|
388
|
+
* Closes this delivery worker after settling its work.
|
|
389
|
+
*
|
|
390
|
+
* @returns The result of this delivery operation.
|
|
391
|
+
*/
|
|
318
392
|
async retire() {
|
|
319
393
|
const settled = await Promise.allSettled(Array.from(this.#groups.values(), (group) => EnvironmentDeliveryValues.attempt(() => group.retire())));
|
|
320
394
|
EnvironmentDeliveryValues.throwFailures(settled.flatMap((result) => (result.status === "rejected" ? [result.reason] : [])), "Environment delivery supervisor retirement failed.");
|
|
321
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* Builds a stable supervisor-group key for one owner and shard total.
|
|
398
|
+
*
|
|
399
|
+
* @param ownerKey The configured owner key.
|
|
400
|
+
* @param shardCount The shard total for this supervisor group.
|
|
401
|
+
* @returns The result of this delivery operation.
|
|
402
|
+
*/
|
|
322
403
|
#groupKey(ownerKey, shardCount) {
|
|
323
404
|
return this.#ports?.source === undefined
|
|
324
405
|
? `${ownerKey}/${String(shardCount)}`
|
|
325
406
|
: `remote/${String(shardCount)}`;
|
|
326
407
|
}
|
|
327
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* Keeps admitted routes stable while one shard supervisor drains.
|
|
411
|
+
*/
|
|
328
412
|
class RuntimeDeliverySupervisorGroup {
|
|
329
413
|
#source;
|
|
330
414
|
#supervisor;
|
|
@@ -336,6 +420,11 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
336
420
|
#start;
|
|
337
421
|
#stopped = false;
|
|
338
422
|
#close;
|
|
423
|
+
/**
|
|
424
|
+
* Creates the delivery component with its configured dependencies.
|
|
425
|
+
*
|
|
426
|
+
* @param options The delivery or cancellation options.
|
|
427
|
+
*/
|
|
339
428
|
constructor(options) {
|
|
340
429
|
// `createSupervisorGroup()` rejects an empty shard collection before internal construction.
|
|
341
430
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
@@ -352,6 +441,9 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
352
441
|
onMessage: (message) => this.#route(message),
|
|
353
442
|
});
|
|
354
443
|
deliverySupervisorAccess.installAdmission(this.#supervisor, (message) => this.#accept(message));
|
|
444
|
+
deliverySupervisorAccess.installMessageSettled(this.#supervisor, (message) => {
|
|
445
|
+
this.#settleReservation(message);
|
|
446
|
+
});
|
|
355
447
|
deliverySupervisorAccess.installFinalization(this.#supervisor, (shard) => {
|
|
356
448
|
this.#releaseUndeliveredReservations(shard);
|
|
357
449
|
});
|
|
@@ -359,6 +451,13 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
359
451
|
deliverySupervisorAccess.installLogger(this.#supervisor, options.logger);
|
|
360
452
|
}
|
|
361
453
|
}
|
|
454
|
+
/**
|
|
455
|
+
* Adds the configured delivery runtime or shards.
|
|
456
|
+
*
|
|
457
|
+
* @param ownerKey The configured owner key.
|
|
458
|
+
* @param runtime The configured context delivery runtime.
|
|
459
|
+
* @param shards The shards assigned to this runtime.
|
|
460
|
+
*/
|
|
362
461
|
add(ownerKey, runtime, shards) {
|
|
363
462
|
if (this.#source instanceof LocalDeliverySource)
|
|
364
463
|
this.#source.add(shards);
|
|
@@ -378,13 +477,29 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
378
477
|
this.#routes.set(key, routes);
|
|
379
478
|
}
|
|
380
479
|
}
|
|
480
|
+
/**
|
|
481
|
+
* Checks whether this supervisor group has configured routes.
|
|
482
|
+
*
|
|
483
|
+
* @returns The result of this delivery operation.
|
|
484
|
+
*/
|
|
381
485
|
get empty() {
|
|
382
486
|
return this.#routes.size === 0;
|
|
383
487
|
}
|
|
488
|
+
/**
|
|
489
|
+
* Marks the selected owners as unavailable for new route admission.
|
|
490
|
+
*
|
|
491
|
+
* @param ownerKeys The owner keys in this generation.
|
|
492
|
+
*/
|
|
384
493
|
fenceOwners(ownerKeys) {
|
|
385
494
|
for (const ownerKey of ownerKeys)
|
|
386
495
|
this.#retiringOwners.add(ownerKey);
|
|
387
496
|
}
|
|
497
|
+
/**
|
|
498
|
+
* Waits for admitted work for the selected owners to settle.
|
|
499
|
+
*
|
|
500
|
+
* @param ownerKeys The owner keys in this generation.
|
|
501
|
+
* @returns The result of this delivery operation.
|
|
502
|
+
*/
|
|
388
503
|
async awaitOwnersSettled(ownerKeys) {
|
|
389
504
|
await Promise.all(Array.from(this.#reserved.values(), async (reservations) => Promise.all(Array.from(reservations.values())
|
|
390
505
|
.filter((reservation) => ownerKeys.includes(reservation.route.ownerKey))
|
|
@@ -395,6 +510,12 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
395
510
|
await Promise.allSettled(active);
|
|
396
511
|
}));
|
|
397
512
|
}
|
|
513
|
+
/**
|
|
514
|
+
* Closes the selected owners after admitted work settles.
|
|
515
|
+
*
|
|
516
|
+
* @param ownerKeys The owner keys in this generation.
|
|
517
|
+
* @returns The result of this delivery operation.
|
|
518
|
+
*/
|
|
398
519
|
async retireOwners(ownerKeys) {
|
|
399
520
|
this.fenceOwners(ownerKeys);
|
|
400
521
|
await this.awaitOwnersSettled(ownerKeys);
|
|
@@ -403,6 +524,11 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
403
524
|
if (this.empty)
|
|
404
525
|
await this.retire();
|
|
405
526
|
}
|
|
527
|
+
/**
|
|
528
|
+
* Removes an owner route from this runtime.
|
|
529
|
+
*
|
|
530
|
+
* @param ownerKey The configured owner key.
|
|
531
|
+
*/
|
|
406
532
|
remove(ownerKey) {
|
|
407
533
|
for (const [key, routes] of this.#routes) {
|
|
408
534
|
const retained = routes.filter((route) => route.ownerKey !== ownerKey);
|
|
@@ -412,6 +538,11 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
412
538
|
this.#routes.set(key, retained);
|
|
413
539
|
}
|
|
414
540
|
}
|
|
541
|
+
/**
|
|
542
|
+
* Starts the configured delivery worker or supervisor.
|
|
543
|
+
*
|
|
544
|
+
* @returns The result of this delivery operation.
|
|
545
|
+
*/
|
|
415
546
|
start() {
|
|
416
547
|
if (this.#stopped) {
|
|
417
548
|
return Promise.reject(new Error("Environment delivery supervisor is stopped."));
|
|
@@ -424,6 +555,11 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
424
555
|
}
|
|
425
556
|
return this.#start;
|
|
426
557
|
}
|
|
558
|
+
/**
|
|
559
|
+
* Notifies the selected delivery scope or shard.
|
|
560
|
+
*
|
|
561
|
+
* @param shard The shard to process.
|
|
562
|
+
*/
|
|
427
563
|
notify(shard) {
|
|
428
564
|
if (this.#stopped)
|
|
429
565
|
return;
|
|
@@ -434,6 +570,9 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
434
570
|
})
|
|
435
571
|
.catch(() => undefined);
|
|
436
572
|
}
|
|
573
|
+
/**
|
|
574
|
+
* Stops admission and starts delivery shutdown.
|
|
575
|
+
*/
|
|
437
576
|
stop() {
|
|
438
577
|
if (this.#stopped)
|
|
439
578
|
return;
|
|
@@ -442,28 +581,54 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
442
581
|
// spine-log-boundary: server.delivery_supervisor_close
|
|
443
582
|
void this.#close.catch(() => undefined);
|
|
444
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* Waits for the active delivery work to settle.
|
|
586
|
+
*
|
|
587
|
+
* @returns The result of this delivery operation.
|
|
588
|
+
*/
|
|
445
589
|
async awaitSettled() {
|
|
446
590
|
await this.#start;
|
|
447
591
|
await this.#close;
|
|
448
592
|
}
|
|
593
|
+
/**
|
|
594
|
+
* Closes this delivery worker after settling its work.
|
|
595
|
+
*
|
|
596
|
+
* @returns The result of this delivery operation.
|
|
597
|
+
*/
|
|
449
598
|
async retire() {
|
|
450
599
|
this.stop();
|
|
451
600
|
await this.awaitSettled();
|
|
452
601
|
}
|
|
602
|
+
/**
|
|
603
|
+
* Accepts an Inbox message and reserves its exact route.
|
|
604
|
+
*
|
|
605
|
+
* @param message The persisted Inbox message.
|
|
606
|
+
* @returns The result of this delivery operation.
|
|
607
|
+
*/
|
|
453
608
|
#accept(message) {
|
|
454
609
|
const route = this.#select(message);
|
|
455
610
|
if (route !== undefined) {
|
|
456
611
|
// `options.shards` initializes one private reservation map per supervised shard.
|
|
457
612
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
458
613
|
const reservations = this.#reserved.get(message.shard.key());
|
|
459
|
-
|
|
614
|
+
const key = _a.messageKey(message);
|
|
615
|
+
if (reservations.has(key))
|
|
616
|
+
return false;
|
|
617
|
+
reservations.set(key, {
|
|
460
618
|
route,
|
|
461
619
|
settled: Promise.withResolvers(),
|
|
462
620
|
});
|
|
463
621
|
}
|
|
464
622
|
return route !== undefined;
|
|
465
623
|
}
|
|
624
|
+
/**
|
|
625
|
+
* Routes an admitted Inbox message to its reserved endpoint.
|
|
626
|
+
*
|
|
627
|
+
* @param message The persisted Inbox message.
|
|
628
|
+
* @returns The result of this delivery operation.
|
|
629
|
+
*/
|
|
466
630
|
#route(message) {
|
|
631
|
+
receptionObservation.markManaged();
|
|
467
632
|
const key = _a.messageKey(message);
|
|
468
633
|
// `Delivery` invokes the callback only after this group's admission reserved its route.
|
|
469
634
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
@@ -481,10 +646,29 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
481
646
|
this.#active.delete(route.ownerKey);
|
|
482
647
|
});
|
|
483
648
|
active.add(replay);
|
|
649
|
+
return replay;
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Resolves and removes one reservation after its complete processing action.
|
|
653
|
+
*
|
|
654
|
+
* @param message The settled Inbox message.
|
|
655
|
+
*/
|
|
656
|
+
#settleReservation(message) {
|
|
657
|
+
// The constructor initializes a reservation map for every supervised shard.
|
|
658
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
659
|
+
const reservations = this.#reserved.get(message.shard.key());
|
|
660
|
+
const key = _a.messageKey(message);
|
|
661
|
+
const reservation = reservations.get(key);
|
|
662
|
+
if (reservation === undefined)
|
|
663
|
+
return;
|
|
484
664
|
reservations.delete(key);
|
|
485
665
|
reservation.settled.resolve(undefined);
|
|
486
|
-
return replay;
|
|
487
666
|
}
|
|
667
|
+
/**
|
|
668
|
+
* Clears route reservations when a shard run finishes.
|
|
669
|
+
*
|
|
670
|
+
* @param shard The shard to process.
|
|
671
|
+
*/
|
|
488
672
|
#releaseUndeliveredReservations(shard) {
|
|
489
673
|
// `options.shards` initializes one private reservation map per supervised shard.
|
|
490
674
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
@@ -494,12 +678,25 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
494
678
|
}
|
|
495
679
|
reservations.clear();
|
|
496
680
|
}
|
|
681
|
+
/**
|
|
682
|
+
* Finds the configured route for an Inbox message.
|
|
683
|
+
*
|
|
684
|
+
* @param message The persisted Inbox message.
|
|
685
|
+
* @returns The result of this delivery operation.
|
|
686
|
+
*/
|
|
497
687
|
#select(message) {
|
|
498
688
|
const key = _a.key(message);
|
|
499
689
|
const routes = this.#routes.get(key);
|
|
500
690
|
const route = _a.select(routes, message);
|
|
501
691
|
return route === undefined || this.#retiringOwners.has(route.ownerKey) ? undefined : route;
|
|
502
692
|
}
|
|
693
|
+
/**
|
|
694
|
+
* Finds the matching route for an Inbox message.
|
|
695
|
+
*
|
|
696
|
+
* @param routes The candidate routes.
|
|
697
|
+
* @param message The persisted Inbox message.
|
|
698
|
+
* @returns The result of this delivery operation.
|
|
699
|
+
*/
|
|
503
700
|
static select(routes, message) {
|
|
504
701
|
if (routes === undefined || routes.length === 0)
|
|
505
702
|
return undefined;
|
|
@@ -508,7 +705,7 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
508
705
|
}
|
|
509
706
|
/**
|
|
510
707
|
*
|
|
511
|
-
*
|
|
708
|
+
* Finds the tenant boundary key from the delivery label's matching envelope.
|
|
512
709
|
* `HANDLE_COMMAND` reads the Command actor tenant; Event labels read imported
|
|
513
710
|
* or past-message Event origin tenants.
|
|
514
711
|
*
|
|
@@ -539,30 +736,63 @@ class RuntimeDeliverySupervisorGroup {
|
|
|
539
736
|
}
|
|
540
737
|
return undefined;
|
|
541
738
|
}
|
|
739
|
+
/**
|
|
740
|
+
* Builds a route key for one configured endpoint.
|
|
741
|
+
*
|
|
742
|
+
* @param route The configured route.
|
|
743
|
+
* @returns The result of this delivery operation.
|
|
744
|
+
*/
|
|
542
745
|
static key(route) {
|
|
543
746
|
const targetTypeUrl = route.inboxId?.targetTypeUrl ?? route.targetTypeUrl;
|
|
544
747
|
if (targetTypeUrl === undefined)
|
|
545
748
|
throw new Error("Environment delivery route has no target type.");
|
|
546
749
|
return JSON.stringify([route.label, targetTypeUrl, route.shard.index, route.shard.ofTotal]);
|
|
547
750
|
}
|
|
751
|
+
/**
|
|
752
|
+
* Builds an exact route-reservation key for one Inbox message.
|
|
753
|
+
*
|
|
754
|
+
* @param message The persisted Inbox message.
|
|
755
|
+
* @returns The result of this delivery operation.
|
|
756
|
+
*/
|
|
548
757
|
static messageKey(message) {
|
|
549
|
-
return `${message.
|
|
758
|
+
return `${message.id.shard.key()}/${message.id.value}`;
|
|
550
759
|
}
|
|
551
760
|
}
|
|
552
761
|
_a = RuntimeDeliverySupervisorGroup;
|
|
762
|
+
/**
|
|
763
|
+
* Supplies local shard recovery observations to the supervisor.
|
|
764
|
+
*/
|
|
553
765
|
class LocalDeliverySource {
|
|
554
766
|
#shards = new Map();
|
|
555
767
|
#recoveryEnabled = false;
|
|
768
|
+
/**
|
|
769
|
+
* Creates the delivery component with its configured dependencies.
|
|
770
|
+
*
|
|
771
|
+
* @param shards The shards assigned to this runtime.
|
|
772
|
+
*/
|
|
556
773
|
constructor(shards) {
|
|
557
774
|
this.add(shards);
|
|
558
775
|
}
|
|
776
|
+
/**
|
|
777
|
+
* Adds the configured delivery runtime or shards.
|
|
778
|
+
*
|
|
779
|
+
* @param shards The shards assigned to this runtime.
|
|
780
|
+
*/
|
|
559
781
|
add(shards) {
|
|
560
782
|
for (const shard of shards)
|
|
561
783
|
this.#shards.set(shard.key(), shard);
|
|
562
784
|
}
|
|
785
|
+
/**
|
|
786
|
+
* Sets local shards as eligible for periodic recovery.
|
|
787
|
+
*/
|
|
563
788
|
enableRecovery() {
|
|
564
789
|
this.#recoveryEnabled = true;
|
|
565
790
|
}
|
|
791
|
+
/**
|
|
792
|
+
* Returns the locally recoverable shard snapshot.
|
|
793
|
+
*
|
|
794
|
+
* @returns The result of this delivery operation.
|
|
795
|
+
*/
|
|
566
796
|
shardSnapshot() {
|
|
567
797
|
return Promise.resolve(this.#recoveryEnabled
|
|
568
798
|
? Array.from(this.#shards.values(), (shard) => ({
|
|
@@ -572,18 +802,36 @@ class LocalDeliverySource {
|
|
|
572
802
|
}))
|
|
573
803
|
: []);
|
|
574
804
|
}
|
|
805
|
+
/**
|
|
806
|
+
* Observes shard changes until the operation is cancelled.
|
|
807
|
+
*
|
|
808
|
+
* @param options The delivery or cancellation options.
|
|
809
|
+
* @returns The result of this delivery operation.
|
|
810
|
+
*/
|
|
575
811
|
observeShardUpdates(options) {
|
|
576
812
|
return EnvironmentDeliveryValues.updatesUntilAborted(options?.signal);
|
|
577
813
|
}
|
|
814
|
+
/**
|
|
815
|
+
* Returns expired local ownership records.
|
|
816
|
+
*
|
|
817
|
+
* @returns The result of this delivery operation.
|
|
818
|
+
*/
|
|
578
819
|
releaseExpired() {
|
|
579
820
|
return Promise.resolve([]);
|
|
580
821
|
}
|
|
581
822
|
}
|
|
582
823
|
/**
|
|
824
|
+
* Groups private delivery-runtime assembly and failure operations.
|
|
583
825
|
*
|
|
584
|
-
* @internal
|
|
826
|
+
* @internal
|
|
585
827
|
*/
|
|
586
828
|
const EnvironmentDeliveryValues = Object.freeze({
|
|
829
|
+
/**
|
|
830
|
+
* Validates a delivery source before use.
|
|
831
|
+
*
|
|
832
|
+
* @param source The source to validate.
|
|
833
|
+
* @returns The validated delivery source.
|
|
834
|
+
*/
|
|
587
835
|
requireSource(source) {
|
|
588
836
|
if (source === null ||
|
|
589
837
|
typeof source !== "object" ||
|
|
@@ -594,6 +842,14 @@ const EnvironmentDeliveryValues = Object.freeze({
|
|
|
594
842
|
}
|
|
595
843
|
return source;
|
|
596
844
|
},
|
|
845
|
+
/**
|
|
846
|
+
* Creates the worker that drains one context runtime.
|
|
847
|
+
*
|
|
848
|
+
* @param runtime The context runtime to serve.
|
|
849
|
+
* @param ports Optional delivery ports.
|
|
850
|
+
* @param nodeId Optional node identity.
|
|
851
|
+
* @returns The configured worker.
|
|
852
|
+
*/
|
|
597
853
|
createWorker(runtime, ports, nodeId) {
|
|
598
854
|
const delivery = new Delivery({
|
|
599
855
|
context: runtime.context,
|
|
@@ -608,6 +864,15 @@ const EnvironmentDeliveryValues = Object.freeze({
|
|
|
608
864
|
});
|
|
609
865
|
return deliveryRunWorkers.worker(worker);
|
|
610
866
|
},
|
|
867
|
+
/**
|
|
868
|
+
* Creates a supervisor group for shards with one total.
|
|
869
|
+
*
|
|
870
|
+
* @param runtime The context runtime to serve.
|
|
871
|
+
* @param shards The assigned shards.
|
|
872
|
+
* @param ports Optional delivery ports.
|
|
873
|
+
* @param nodeId Optional node identity.
|
|
874
|
+
* @returns The configured supervisor group.
|
|
875
|
+
*/
|
|
611
876
|
createSupervisorGroup(runtime, shards, ports, nodeId) {
|
|
612
877
|
const first = shards[0];
|
|
613
878
|
if (first === undefined) {
|
|
@@ -627,8 +892,19 @@ const EnvironmentDeliveryValues = Object.freeze({
|
|
|
627
892
|
...(runtime.logger === undefined ? {} : { logger: runtime.logger }),
|
|
628
893
|
});
|
|
629
894
|
},
|
|
895
|
+
/**
|
|
896
|
+
* Creates an update stream that finishes on cancellation.
|
|
897
|
+
*
|
|
898
|
+
* @param signal The optional cancellation signal.
|
|
899
|
+
* @returns The cancellation-aware stream.
|
|
900
|
+
*/
|
|
630
901
|
updatesUntilAborted(signal) {
|
|
631
902
|
return {
|
|
903
|
+
/**
|
|
904
|
+
* Returns the cancellation-aware update iterator.
|
|
905
|
+
*
|
|
906
|
+
* @returns The result of this delivery operation.
|
|
907
|
+
*/
|
|
632
908
|
[Symbol.asyncIterator]() {
|
|
633
909
|
return {
|
|
634
910
|
next: () => new Promise((resolve) => {
|
|
@@ -644,6 +920,12 @@ const EnvironmentDeliveryValues = Object.freeze({
|
|
|
644
920
|
},
|
|
645
921
|
};
|
|
646
922
|
},
|
|
923
|
+
/**
|
|
924
|
+
* Finds the sole owner shared by the supplied scopes.
|
|
925
|
+
*
|
|
926
|
+
* @param scopes The exact delivery scopes.
|
|
927
|
+
* @returns Their shared owner.
|
|
928
|
+
*/
|
|
647
929
|
soleOwner(scopes) {
|
|
648
930
|
const first = scopes[0]?.owner;
|
|
649
931
|
if (first === undefined || scopes.some(({ owner }) => owner.key !== first.key)) {
|
|
@@ -651,6 +933,12 @@ const EnvironmentDeliveryValues = Object.freeze({
|
|
|
651
933
|
}
|
|
652
934
|
return first;
|
|
653
935
|
},
|
|
936
|
+
/**
|
|
937
|
+
* Collects distinct shards from the supplied scopes.
|
|
938
|
+
*
|
|
939
|
+
* @param scopes The exact delivery scopes.
|
|
940
|
+
* @returns Their distinct shards.
|
|
941
|
+
*/
|
|
654
942
|
uniqueShards(scopes) {
|
|
655
943
|
const shards = new Map();
|
|
656
944
|
for (const { ready } of scopes) {
|
|
@@ -658,6 +946,12 @@ const EnvironmentDeliveryValues = Object.freeze({
|
|
|
658
946
|
}
|
|
659
947
|
return Object.freeze([...shards.values()]);
|
|
660
948
|
},
|
|
949
|
+
/**
|
|
950
|
+
* Throws collected failures without losing their identity.
|
|
951
|
+
*
|
|
952
|
+
* @param failures The failures to propagate.
|
|
953
|
+
* @param message The aggregate message when several failures occurred.
|
|
954
|
+
*/
|
|
661
955
|
throwFailures(failures, message) {
|
|
662
956
|
if (failures.length === 1) {
|
|
663
957
|
throw failures[0];
|
|
@@ -666,6 +960,12 @@ const EnvironmentDeliveryValues = Object.freeze({
|
|
|
666
960
|
throw new AggregateError(failures, message);
|
|
667
961
|
}
|
|
668
962
|
},
|
|
963
|
+
/**
|
|
964
|
+
* Awaits one asynchronous cleanup action.
|
|
965
|
+
*
|
|
966
|
+
* @param action The action to await.
|
|
967
|
+
* @returns Completion of that action.
|
|
968
|
+
*/
|
|
669
969
|
async attempt(action) {
|
|
670
970
|
await action();
|
|
671
971
|
},
|