@cadenza.io/service 2.17.2 → 2.17.4
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/browser/index.js +165 -63
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +165 -63
- package/dist/browser/index.mjs.map +1 -1
- package/dist/index.d.mts +29 -2
- package/dist/index.d.ts +29 -2
- package/dist/index.js +170 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +170 -72
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.js
CHANGED
|
@@ -460,7 +460,14 @@ function selectTransportForRole(transports, role, protocol) {
|
|
|
460
460
|
const filtered = transports.filter(
|
|
461
461
|
(transport) => !transport.deleted && transport.role === role && (!protocol || transportSupportsProtocol(transport, protocol))
|
|
462
462
|
);
|
|
463
|
-
return filtered
|
|
463
|
+
return filtered.sort((left, right) => {
|
|
464
|
+
const leftIsBootstrap = left.uuid.endsWith("-bootstrap") ? 1 : 0;
|
|
465
|
+
const rightIsBootstrap = right.uuid.endsWith("-bootstrap") ? 1 : 0;
|
|
466
|
+
if (leftIsBootstrap !== rightIsBootstrap) {
|
|
467
|
+
return leftIsBootstrap - rightIsBootstrap;
|
|
468
|
+
}
|
|
469
|
+
return left.origin.localeCompare(right.origin);
|
|
470
|
+
})[0];
|
|
464
471
|
}
|
|
465
472
|
function buildTransportClientKey(transport) {
|
|
466
473
|
return transport.uuid;
|
|
@@ -1478,20 +1485,25 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1478
1485
|
this.getBalancedInstance = CadenzaService.createMetaTask(
|
|
1479
1486
|
"Get balanced instance",
|
|
1480
1487
|
(context, emit) => {
|
|
1481
|
-
const {
|
|
1488
|
+
const {
|
|
1489
|
+
__serviceName,
|
|
1490
|
+
__triedInstances,
|
|
1491
|
+
__retries,
|
|
1492
|
+
__broadcast,
|
|
1493
|
+
targetServiceInstanceId
|
|
1494
|
+
} = context;
|
|
1482
1495
|
let retries = __retries ?? 0;
|
|
1483
1496
|
let triedInstances = __triedInstances ?? [];
|
|
1484
1497
|
const preferredRole = this.getRoutingTransportRole();
|
|
1485
1498
|
const instances = this.instances.get(__serviceName)?.filter((instance) => {
|
|
1499
|
+
if (targetServiceInstanceId && instance.uuid !== targetServiceInstanceId) {
|
|
1500
|
+
return false;
|
|
1501
|
+
}
|
|
1486
1502
|
if (!instance.isActive || instance.isNonResponsive || instance.isBlocked) {
|
|
1487
1503
|
return false;
|
|
1488
1504
|
}
|
|
1489
1505
|
return Boolean(
|
|
1490
|
-
this.
|
|
1491
|
-
instance,
|
|
1492
|
-
this.useSocket ? "socket" : "rest",
|
|
1493
|
-
preferredRole
|
|
1494
|
-
) ?? this.getRouteableTransport(instance, "rest", preferredRole)
|
|
1506
|
+
this.selectTransportForInstance(instance, context, preferredRole)
|
|
1495
1507
|
);
|
|
1496
1508
|
}).sort((a, b) => {
|
|
1497
1509
|
const leftStatus = this.resolveRuntimeStatusSnapshot(
|
|
@@ -1523,13 +1535,17 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1523
1535
|
}
|
|
1524
1536
|
if (__broadcast || instances[0].isFrontend) {
|
|
1525
1537
|
for (const instance of instances) {
|
|
1526
|
-
const selectedTransport2 = this.
|
|
1538
|
+
const selectedTransport2 = this.selectTransportForInstance(
|
|
1539
|
+
instance,
|
|
1540
|
+
context,
|
|
1541
|
+
preferredRole
|
|
1542
|
+
);
|
|
1527
1543
|
if (!selectedTransport2) {
|
|
1528
1544
|
continue;
|
|
1529
1545
|
}
|
|
1530
1546
|
const transportKey = buildTransportClientKey(selectedTransport2);
|
|
1531
1547
|
emit(
|
|
1532
|
-
`${this.
|
|
1548
|
+
`${this.resolveTransportProtocolOrder(context)[0] === "socket" && transportSupportsProtocol(selectedTransport2, "socket") ? "meta.service_registry.selected_instance_for_socket" : "meta.service_registry.selected_instance_for_fetch"}:${transportKey}`,
|
|
1533
1549
|
{
|
|
1534
1550
|
...context,
|
|
1535
1551
|
__instance: instance.uuid,
|
|
@@ -1560,7 +1576,11 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1560
1576
|
if (retries > 0) {
|
|
1561
1577
|
selected = instancesToTry[Math.floor(Math.random() * instancesToTry.length)];
|
|
1562
1578
|
}
|
|
1563
|
-
const selectedTransport = this.
|
|
1579
|
+
const selectedTransport = this.selectTransportForInstance(
|
|
1580
|
+
selected,
|
|
1581
|
+
context,
|
|
1582
|
+
preferredRole
|
|
1583
|
+
);
|
|
1564
1584
|
if (!selectedTransport) {
|
|
1565
1585
|
context.errored = true;
|
|
1566
1586
|
context.__error = `No routeable ${preferredRole} transport available for ${selected.serviceName}/${selected.uuid}.`;
|
|
@@ -1578,7 +1598,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1578
1598
|
context.__triedInstances = triedInstances;
|
|
1579
1599
|
context.__triedInstances.push(selected.uuid);
|
|
1580
1600
|
context.__retries = retries;
|
|
1581
|
-
if (this.
|
|
1601
|
+
if (this.resolveTransportProtocolOrder(context)[0] === "socket" && transportSupportsProtocol(selectedTransport, "socket")) {
|
|
1582
1602
|
emit(
|
|
1583
1603
|
`meta.service_registry.selected_instance_for_socket:${context.__fetchId}`,
|
|
1584
1604
|
context
|
|
@@ -1604,50 +1624,10 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1604
1624
|
"meta.service_registry.selected_instance_for_fetch",
|
|
1605
1625
|
"meta.service_registry.socket_failed"
|
|
1606
1626
|
);
|
|
1607
|
-
this.getStatusTask = CadenzaService.createMetaTask(
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
__error: "No service name defined",
|
|
1612
|
-
errored: true
|
|
1613
|
-
};
|
|
1614
|
-
}
|
|
1615
|
-
if (!this.serviceInstanceId) {
|
|
1616
|
-
return {
|
|
1617
|
-
__status: "error",
|
|
1618
|
-
__error: "No service instance id defined",
|
|
1619
|
-
errored: true
|
|
1620
|
-
};
|
|
1621
|
-
}
|
|
1622
|
-
const report = this.buildLocalRuntimeStatusReport("full");
|
|
1623
|
-
if (!report) {
|
|
1624
|
-
return {
|
|
1625
|
-
...ctx,
|
|
1626
|
-
__status: "error",
|
|
1627
|
-
__error: "No local service instance available for status check",
|
|
1628
|
-
errored: true
|
|
1629
|
-
};
|
|
1630
|
-
}
|
|
1631
|
-
return {
|
|
1632
|
-
...ctx,
|
|
1633
|
-
__status: "ok",
|
|
1634
|
-
__serviceName: report.serviceName,
|
|
1635
|
-
__serviceInstanceId: report.serviceInstanceId,
|
|
1636
|
-
__numberOfRunningGraphs: report.numberOfRunningGraphs,
|
|
1637
|
-
__health: report.health ?? {},
|
|
1638
|
-
__active: report.isActive,
|
|
1639
|
-
reportedAt: report.reportedAt,
|
|
1640
|
-
serviceName: report.serviceName,
|
|
1641
|
-
serviceInstanceId: report.serviceInstanceId,
|
|
1642
|
-
numberOfRunningGraphs: report.numberOfRunningGraphs,
|
|
1643
|
-
health: report.health ?? {},
|
|
1644
|
-
isActive: report.isActive,
|
|
1645
|
-
isNonResponsive: report.isNonResponsive,
|
|
1646
|
-
isBlocked: report.isBlocked,
|
|
1647
|
-
state: report.state,
|
|
1648
|
-
acceptingWork: report.acceptingWork
|
|
1649
|
-
};
|
|
1650
|
-
}).doOn(
|
|
1627
|
+
this.getStatusTask = CadenzaService.createMetaTask(
|
|
1628
|
+
"Get status",
|
|
1629
|
+
(ctx) => this.resolveLocalStatusCheck(ctx)
|
|
1630
|
+
).doOn(
|
|
1651
1631
|
"meta.socket.status_check_requested",
|
|
1652
1632
|
"meta.rest.status_check_requested"
|
|
1653
1633
|
);
|
|
@@ -2359,6 +2339,65 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2359
2339
|
}
|
|
2360
2340
|
return this.getInstance(this.serviceName, this.serviceInstanceId);
|
|
2361
2341
|
}
|
|
2342
|
+
resolveLocalStatusCheck(ctx = {}) {
|
|
2343
|
+
if (!this.serviceName) {
|
|
2344
|
+
return {
|
|
2345
|
+
__status: "error",
|
|
2346
|
+
__error: "No service name defined",
|
|
2347
|
+
errored: true
|
|
2348
|
+
};
|
|
2349
|
+
}
|
|
2350
|
+
if (!this.serviceInstanceId) {
|
|
2351
|
+
return {
|
|
2352
|
+
__status: "error",
|
|
2353
|
+
__error: "No service instance id defined",
|
|
2354
|
+
errored: true
|
|
2355
|
+
};
|
|
2356
|
+
}
|
|
2357
|
+
const report = this.buildLocalRuntimeStatusReport("full");
|
|
2358
|
+
if (!report) {
|
|
2359
|
+
return {
|
|
2360
|
+
...ctx,
|
|
2361
|
+
__status: "error",
|
|
2362
|
+
__error: "No local service instance available for status check",
|
|
2363
|
+
errored: true
|
|
2364
|
+
};
|
|
2365
|
+
}
|
|
2366
|
+
return {
|
|
2367
|
+
...ctx,
|
|
2368
|
+
__status: "ok",
|
|
2369
|
+
__serviceName: report.serviceName,
|
|
2370
|
+
__serviceInstanceId: report.serviceInstanceId,
|
|
2371
|
+
__numberOfRunningGraphs: report.numberOfRunningGraphs,
|
|
2372
|
+
__health: report.health ?? {},
|
|
2373
|
+
__active: report.isActive,
|
|
2374
|
+
reportedAt: report.reportedAt,
|
|
2375
|
+
serviceName: report.serviceName,
|
|
2376
|
+
serviceInstanceId: report.serviceInstanceId,
|
|
2377
|
+
numberOfRunningGraphs: report.numberOfRunningGraphs,
|
|
2378
|
+
health: report.health ?? {},
|
|
2379
|
+
isActive: report.isActive,
|
|
2380
|
+
isNonResponsive: report.isNonResponsive,
|
|
2381
|
+
isBlocked: report.isBlocked,
|
|
2382
|
+
state: report.state,
|
|
2383
|
+
acceptingWork: report.acceptingWork
|
|
2384
|
+
};
|
|
2385
|
+
}
|
|
2386
|
+
resolveTransportProtocolOrder(ctx) {
|
|
2387
|
+
const explicit = ctx.__preferredTransportProtocol === "rest" || ctx.__preferredTransportProtocol === "socket" ? ctx.__preferredTransportProtocol : void 0;
|
|
2388
|
+
const preferred = explicit ?? (this.useSocket ? "socket" : "rest");
|
|
2389
|
+
const fallback = preferred === "socket" ? "rest" : "socket";
|
|
2390
|
+
return [preferred, fallback];
|
|
2391
|
+
}
|
|
2392
|
+
selectTransportForInstance(instance, ctx, role = this.getRoutingTransportRole()) {
|
|
2393
|
+
for (const protocol of this.resolveTransportProtocolOrder(ctx)) {
|
|
2394
|
+
const transport = this.getRouteableTransport(instance, protocol, role);
|
|
2395
|
+
if (transport) {
|
|
2396
|
+
return transport;
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
return void 0;
|
|
2400
|
+
}
|
|
2362
2401
|
getRoutingTransportRole() {
|
|
2363
2402
|
return this.isFrontend ? "public" : "internal";
|
|
2364
2403
|
}
|
|
@@ -2618,12 +2657,41 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2618
2657
|
return null;
|
|
2619
2658
|
}
|
|
2620
2659
|
async resolveRuntimeStatusFallbackInquiry(serviceName, serviceInstanceId, options = {}) {
|
|
2660
|
+
const instance = this.getInstance(serviceName, serviceInstanceId);
|
|
2661
|
+
if (instance) {
|
|
2662
|
+
const directReport = await this.requestRuntimeStatusViaRest(
|
|
2663
|
+
instance,
|
|
2664
|
+
serviceName,
|
|
2665
|
+
serviceInstanceId
|
|
2666
|
+
);
|
|
2667
|
+
if (directReport) {
|
|
2668
|
+
if (!this.applyRuntimeStatusReport(directReport)) {
|
|
2669
|
+
throw new Error(
|
|
2670
|
+
`No tracked instance for runtime fallback ${serviceName}/${serviceInstanceId}`
|
|
2671
|
+
);
|
|
2672
|
+
}
|
|
2673
|
+
this.lastHeartbeatAtByInstance.set(serviceInstanceId, Date.now());
|
|
2674
|
+
this.missedHeartbeatsByInstance.set(serviceInstanceId, 0);
|
|
2675
|
+
return {
|
|
2676
|
+
report: directReport,
|
|
2677
|
+
inquiryMeta: {
|
|
2678
|
+
inquiry: META_RUNTIME_STATUS_INTENT,
|
|
2679
|
+
responded: 1,
|
|
2680
|
+
failed: 0,
|
|
2681
|
+
timedOut: 0,
|
|
2682
|
+
pending: 0,
|
|
2683
|
+
directStatusCheck: true
|
|
2684
|
+
}
|
|
2685
|
+
};
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2621
2688
|
const inquiryResult = await CadenzaService.inquire(
|
|
2622
2689
|
META_RUNTIME_STATUS_INTENT,
|
|
2623
2690
|
{
|
|
2624
2691
|
targetServiceName: serviceName,
|
|
2625
2692
|
targetServiceInstanceId: serviceInstanceId,
|
|
2626
|
-
detailLevel: options.detailLevel ?? "minimal"
|
|
2693
|
+
detailLevel: options.detailLevel ?? "minimal",
|
|
2694
|
+
__preferredTransportProtocol: "rest"
|
|
2627
2695
|
},
|
|
2628
2696
|
{
|
|
2629
2697
|
overallTimeoutMs: options.overallTimeoutMs ?? this.runtimeStatusFallbackTimeoutMs,
|
|
@@ -2653,6 +2721,46 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2653
2721
|
inquiryMeta: inquiryResult.__inquiryMeta ?? {}
|
|
2654
2722
|
};
|
|
2655
2723
|
}
|
|
2724
|
+
async requestRuntimeStatusViaRest(instance, serviceName, serviceInstanceId) {
|
|
2725
|
+
if (typeof globalThis.fetch !== "function") {
|
|
2726
|
+
return null;
|
|
2727
|
+
}
|
|
2728
|
+
const transport = this.getRouteableTransport(instance, "rest");
|
|
2729
|
+
if (!transport) {
|
|
2730
|
+
return null;
|
|
2731
|
+
}
|
|
2732
|
+
const controller = typeof AbortController === "function" ? new AbortController() : null;
|
|
2733
|
+
const timeoutId = controller ? setTimeout(() => controller.abort(), this.runtimeStatusFallbackTimeoutMs) : null;
|
|
2734
|
+
try {
|
|
2735
|
+
const response = await globalThis.fetch(`${transport.origin}/status`, {
|
|
2736
|
+
method: "GET",
|
|
2737
|
+
signal: controller?.signal
|
|
2738
|
+
});
|
|
2739
|
+
if ("ok" in response && response.ok === false) {
|
|
2740
|
+
return null;
|
|
2741
|
+
}
|
|
2742
|
+
const payload = typeof response.json === "function" ? await response.json() : response;
|
|
2743
|
+
const report = this.normalizeRuntimeStatusReport({
|
|
2744
|
+
...payload,
|
|
2745
|
+
serviceTransportId: payload?.serviceTransportId ?? transport.uuid,
|
|
2746
|
+
serviceOrigin: payload?.serviceOrigin ?? transport.origin,
|
|
2747
|
+
transportProtocols: payload?.transportProtocols ?? transport.protocols
|
|
2748
|
+
});
|
|
2749
|
+
if (!report) {
|
|
2750
|
+
return null;
|
|
2751
|
+
}
|
|
2752
|
+
if (report.serviceName !== serviceName || report.serviceInstanceId !== serviceInstanceId) {
|
|
2753
|
+
return null;
|
|
2754
|
+
}
|
|
2755
|
+
return report;
|
|
2756
|
+
} catch {
|
|
2757
|
+
return null;
|
|
2758
|
+
} finally {
|
|
2759
|
+
if (timeoutId) {
|
|
2760
|
+
clearTimeout(timeoutId);
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2656
2764
|
evaluateDependencyReadinessDetail(serviceName, serviceInstanceId, now = Date.now()) {
|
|
2657
2765
|
const instance = this.getInstance(serviceName, serviceInstanceId);
|
|
2658
2766
|
const missedHeartbeats = this.getHeartbeatMisses(serviceInstanceId, now);
|
|
@@ -3772,13 +3880,7 @@ var SocketController = class _SocketController {
|
|
|
3772
3880
|
ws.on(
|
|
3773
3881
|
"status_check",
|
|
3774
3882
|
(ctx, callback) => {
|
|
3775
|
-
CadenzaService.
|
|
3776
|
-
"Resolve status check",
|
|
3777
|
-
callback,
|
|
3778
|
-
"Resolves a status check request",
|
|
3779
|
-
{ register: false }
|
|
3780
|
-
).doAfter(CadenzaService.serviceRegistry.getStatusTask);
|
|
3781
|
-
CadenzaService.emit("meta.socket.status_check_requested", ctx);
|
|
3883
|
+
callback(CadenzaService.serviceRegistry.resolveLocalStatusCheck(ctx));
|
|
3782
3884
|
}
|
|
3783
3885
|
);
|
|
3784
3886
|
ws.on("disconnect", () => {
|