@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/index.mjs
CHANGED
|
@@ -409,7 +409,14 @@ function selectTransportForRole(transports, role, protocol) {
|
|
|
409
409
|
const filtered = transports.filter(
|
|
410
410
|
(transport) => !transport.deleted && transport.role === role && (!protocol || transportSupportsProtocol(transport, protocol))
|
|
411
411
|
);
|
|
412
|
-
return filtered
|
|
412
|
+
return filtered.sort((left, right) => {
|
|
413
|
+
const leftIsBootstrap = left.uuid.endsWith("-bootstrap") ? 1 : 0;
|
|
414
|
+
const rightIsBootstrap = right.uuid.endsWith("-bootstrap") ? 1 : 0;
|
|
415
|
+
if (leftIsBootstrap !== rightIsBootstrap) {
|
|
416
|
+
return leftIsBootstrap - rightIsBootstrap;
|
|
417
|
+
}
|
|
418
|
+
return left.origin.localeCompare(right.origin);
|
|
419
|
+
})[0];
|
|
413
420
|
}
|
|
414
421
|
function buildTransportClientKey(transport) {
|
|
415
422
|
return transport.uuid;
|
|
@@ -1427,20 +1434,25 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1427
1434
|
this.getBalancedInstance = CadenzaService.createMetaTask(
|
|
1428
1435
|
"Get balanced instance",
|
|
1429
1436
|
(context, emit) => {
|
|
1430
|
-
const {
|
|
1437
|
+
const {
|
|
1438
|
+
__serviceName,
|
|
1439
|
+
__triedInstances,
|
|
1440
|
+
__retries,
|
|
1441
|
+
__broadcast,
|
|
1442
|
+
targetServiceInstanceId
|
|
1443
|
+
} = context;
|
|
1431
1444
|
let retries = __retries ?? 0;
|
|
1432
1445
|
let triedInstances = __triedInstances ?? [];
|
|
1433
1446
|
const preferredRole = this.getRoutingTransportRole();
|
|
1434
1447
|
const instances = this.instances.get(__serviceName)?.filter((instance) => {
|
|
1448
|
+
if (targetServiceInstanceId && instance.uuid !== targetServiceInstanceId) {
|
|
1449
|
+
return false;
|
|
1450
|
+
}
|
|
1435
1451
|
if (!instance.isActive || instance.isNonResponsive || instance.isBlocked) {
|
|
1436
1452
|
return false;
|
|
1437
1453
|
}
|
|
1438
1454
|
return Boolean(
|
|
1439
|
-
this.
|
|
1440
|
-
instance,
|
|
1441
|
-
this.useSocket ? "socket" : "rest",
|
|
1442
|
-
preferredRole
|
|
1443
|
-
) ?? this.getRouteableTransport(instance, "rest", preferredRole)
|
|
1455
|
+
this.selectTransportForInstance(instance, context, preferredRole)
|
|
1444
1456
|
);
|
|
1445
1457
|
}).sort((a, b) => {
|
|
1446
1458
|
const leftStatus = this.resolveRuntimeStatusSnapshot(
|
|
@@ -1472,13 +1484,17 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1472
1484
|
}
|
|
1473
1485
|
if (__broadcast || instances[0].isFrontend) {
|
|
1474
1486
|
for (const instance of instances) {
|
|
1475
|
-
const selectedTransport2 = this.
|
|
1487
|
+
const selectedTransport2 = this.selectTransportForInstance(
|
|
1488
|
+
instance,
|
|
1489
|
+
context,
|
|
1490
|
+
preferredRole
|
|
1491
|
+
);
|
|
1476
1492
|
if (!selectedTransport2) {
|
|
1477
1493
|
continue;
|
|
1478
1494
|
}
|
|
1479
1495
|
const transportKey = buildTransportClientKey(selectedTransport2);
|
|
1480
1496
|
emit(
|
|
1481
|
-
`${this.
|
|
1497
|
+
`${this.resolveTransportProtocolOrder(context)[0] === "socket" && transportSupportsProtocol(selectedTransport2, "socket") ? "meta.service_registry.selected_instance_for_socket" : "meta.service_registry.selected_instance_for_fetch"}:${transportKey}`,
|
|
1482
1498
|
{
|
|
1483
1499
|
...context,
|
|
1484
1500
|
__instance: instance.uuid,
|
|
@@ -1509,7 +1525,11 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1509
1525
|
if (retries > 0) {
|
|
1510
1526
|
selected = instancesToTry[Math.floor(Math.random() * instancesToTry.length)];
|
|
1511
1527
|
}
|
|
1512
|
-
const selectedTransport = this.
|
|
1528
|
+
const selectedTransport = this.selectTransportForInstance(
|
|
1529
|
+
selected,
|
|
1530
|
+
context,
|
|
1531
|
+
preferredRole
|
|
1532
|
+
);
|
|
1513
1533
|
if (!selectedTransport) {
|
|
1514
1534
|
context.errored = true;
|
|
1515
1535
|
context.__error = `No routeable ${preferredRole} transport available for ${selected.serviceName}/${selected.uuid}.`;
|
|
@@ -1527,7 +1547,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1527
1547
|
context.__triedInstances = triedInstances;
|
|
1528
1548
|
context.__triedInstances.push(selected.uuid);
|
|
1529
1549
|
context.__retries = retries;
|
|
1530
|
-
if (this.
|
|
1550
|
+
if (this.resolveTransportProtocolOrder(context)[0] === "socket" && transportSupportsProtocol(selectedTransport, "socket")) {
|
|
1531
1551
|
emit(
|
|
1532
1552
|
`meta.service_registry.selected_instance_for_socket:${context.__fetchId}`,
|
|
1533
1553
|
context
|
|
@@ -1553,50 +1573,10 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1553
1573
|
"meta.service_registry.selected_instance_for_fetch",
|
|
1554
1574
|
"meta.service_registry.socket_failed"
|
|
1555
1575
|
);
|
|
1556
|
-
this.getStatusTask = CadenzaService.createMetaTask(
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
__error: "No service name defined",
|
|
1561
|
-
errored: true
|
|
1562
|
-
};
|
|
1563
|
-
}
|
|
1564
|
-
if (!this.serviceInstanceId) {
|
|
1565
|
-
return {
|
|
1566
|
-
__status: "error",
|
|
1567
|
-
__error: "No service instance id defined",
|
|
1568
|
-
errored: true
|
|
1569
|
-
};
|
|
1570
|
-
}
|
|
1571
|
-
const report = this.buildLocalRuntimeStatusReport("full");
|
|
1572
|
-
if (!report) {
|
|
1573
|
-
return {
|
|
1574
|
-
...ctx,
|
|
1575
|
-
__status: "error",
|
|
1576
|
-
__error: "No local service instance available for status check",
|
|
1577
|
-
errored: true
|
|
1578
|
-
};
|
|
1579
|
-
}
|
|
1580
|
-
return {
|
|
1581
|
-
...ctx,
|
|
1582
|
-
__status: "ok",
|
|
1583
|
-
__serviceName: report.serviceName,
|
|
1584
|
-
__serviceInstanceId: report.serviceInstanceId,
|
|
1585
|
-
__numberOfRunningGraphs: report.numberOfRunningGraphs,
|
|
1586
|
-
__health: report.health ?? {},
|
|
1587
|
-
__active: report.isActive,
|
|
1588
|
-
reportedAt: report.reportedAt,
|
|
1589
|
-
serviceName: report.serviceName,
|
|
1590
|
-
serviceInstanceId: report.serviceInstanceId,
|
|
1591
|
-
numberOfRunningGraphs: report.numberOfRunningGraphs,
|
|
1592
|
-
health: report.health ?? {},
|
|
1593
|
-
isActive: report.isActive,
|
|
1594
|
-
isNonResponsive: report.isNonResponsive,
|
|
1595
|
-
isBlocked: report.isBlocked,
|
|
1596
|
-
state: report.state,
|
|
1597
|
-
acceptingWork: report.acceptingWork
|
|
1598
|
-
};
|
|
1599
|
-
}).doOn(
|
|
1576
|
+
this.getStatusTask = CadenzaService.createMetaTask(
|
|
1577
|
+
"Get status",
|
|
1578
|
+
(ctx) => this.resolveLocalStatusCheck(ctx)
|
|
1579
|
+
).doOn(
|
|
1600
1580
|
"meta.socket.status_check_requested",
|
|
1601
1581
|
"meta.rest.status_check_requested"
|
|
1602
1582
|
);
|
|
@@ -2308,6 +2288,65 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2308
2288
|
}
|
|
2309
2289
|
return this.getInstance(this.serviceName, this.serviceInstanceId);
|
|
2310
2290
|
}
|
|
2291
|
+
resolveLocalStatusCheck(ctx = {}) {
|
|
2292
|
+
if (!this.serviceName) {
|
|
2293
|
+
return {
|
|
2294
|
+
__status: "error",
|
|
2295
|
+
__error: "No service name defined",
|
|
2296
|
+
errored: true
|
|
2297
|
+
};
|
|
2298
|
+
}
|
|
2299
|
+
if (!this.serviceInstanceId) {
|
|
2300
|
+
return {
|
|
2301
|
+
__status: "error",
|
|
2302
|
+
__error: "No service instance id defined",
|
|
2303
|
+
errored: true
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
const report = this.buildLocalRuntimeStatusReport("full");
|
|
2307
|
+
if (!report) {
|
|
2308
|
+
return {
|
|
2309
|
+
...ctx,
|
|
2310
|
+
__status: "error",
|
|
2311
|
+
__error: "No local service instance available for status check",
|
|
2312
|
+
errored: true
|
|
2313
|
+
};
|
|
2314
|
+
}
|
|
2315
|
+
return {
|
|
2316
|
+
...ctx,
|
|
2317
|
+
__status: "ok",
|
|
2318
|
+
__serviceName: report.serviceName,
|
|
2319
|
+
__serviceInstanceId: report.serviceInstanceId,
|
|
2320
|
+
__numberOfRunningGraphs: report.numberOfRunningGraphs,
|
|
2321
|
+
__health: report.health ?? {},
|
|
2322
|
+
__active: report.isActive,
|
|
2323
|
+
reportedAt: report.reportedAt,
|
|
2324
|
+
serviceName: report.serviceName,
|
|
2325
|
+
serviceInstanceId: report.serviceInstanceId,
|
|
2326
|
+
numberOfRunningGraphs: report.numberOfRunningGraphs,
|
|
2327
|
+
health: report.health ?? {},
|
|
2328
|
+
isActive: report.isActive,
|
|
2329
|
+
isNonResponsive: report.isNonResponsive,
|
|
2330
|
+
isBlocked: report.isBlocked,
|
|
2331
|
+
state: report.state,
|
|
2332
|
+
acceptingWork: report.acceptingWork
|
|
2333
|
+
};
|
|
2334
|
+
}
|
|
2335
|
+
resolveTransportProtocolOrder(ctx) {
|
|
2336
|
+
const explicit = ctx.__preferredTransportProtocol === "rest" || ctx.__preferredTransportProtocol === "socket" ? ctx.__preferredTransportProtocol : void 0;
|
|
2337
|
+
const preferred = explicit ?? (this.useSocket ? "socket" : "rest");
|
|
2338
|
+
const fallback = preferred === "socket" ? "rest" : "socket";
|
|
2339
|
+
return [preferred, fallback];
|
|
2340
|
+
}
|
|
2341
|
+
selectTransportForInstance(instance, ctx, role = this.getRoutingTransportRole()) {
|
|
2342
|
+
for (const protocol of this.resolveTransportProtocolOrder(ctx)) {
|
|
2343
|
+
const transport = this.getRouteableTransport(instance, protocol, role);
|
|
2344
|
+
if (transport) {
|
|
2345
|
+
return transport;
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
return void 0;
|
|
2349
|
+
}
|
|
2311
2350
|
getRoutingTransportRole() {
|
|
2312
2351
|
return this.isFrontend ? "public" : "internal";
|
|
2313
2352
|
}
|
|
@@ -2567,12 +2606,41 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2567
2606
|
return null;
|
|
2568
2607
|
}
|
|
2569
2608
|
async resolveRuntimeStatusFallbackInquiry(serviceName, serviceInstanceId, options = {}) {
|
|
2609
|
+
const instance = this.getInstance(serviceName, serviceInstanceId);
|
|
2610
|
+
if (instance) {
|
|
2611
|
+
const directReport = await this.requestRuntimeStatusViaRest(
|
|
2612
|
+
instance,
|
|
2613
|
+
serviceName,
|
|
2614
|
+
serviceInstanceId
|
|
2615
|
+
);
|
|
2616
|
+
if (directReport) {
|
|
2617
|
+
if (!this.applyRuntimeStatusReport(directReport)) {
|
|
2618
|
+
throw new Error(
|
|
2619
|
+
`No tracked instance for runtime fallback ${serviceName}/${serviceInstanceId}`
|
|
2620
|
+
);
|
|
2621
|
+
}
|
|
2622
|
+
this.lastHeartbeatAtByInstance.set(serviceInstanceId, Date.now());
|
|
2623
|
+
this.missedHeartbeatsByInstance.set(serviceInstanceId, 0);
|
|
2624
|
+
return {
|
|
2625
|
+
report: directReport,
|
|
2626
|
+
inquiryMeta: {
|
|
2627
|
+
inquiry: META_RUNTIME_STATUS_INTENT,
|
|
2628
|
+
responded: 1,
|
|
2629
|
+
failed: 0,
|
|
2630
|
+
timedOut: 0,
|
|
2631
|
+
pending: 0,
|
|
2632
|
+
directStatusCheck: true
|
|
2633
|
+
}
|
|
2634
|
+
};
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2570
2637
|
const inquiryResult = await CadenzaService.inquire(
|
|
2571
2638
|
META_RUNTIME_STATUS_INTENT,
|
|
2572
2639
|
{
|
|
2573
2640
|
targetServiceName: serviceName,
|
|
2574
2641
|
targetServiceInstanceId: serviceInstanceId,
|
|
2575
|
-
detailLevel: options.detailLevel ?? "minimal"
|
|
2642
|
+
detailLevel: options.detailLevel ?? "minimal",
|
|
2643
|
+
__preferredTransportProtocol: "rest"
|
|
2576
2644
|
},
|
|
2577
2645
|
{
|
|
2578
2646
|
overallTimeoutMs: options.overallTimeoutMs ?? this.runtimeStatusFallbackTimeoutMs,
|
|
@@ -2602,6 +2670,46 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2602
2670
|
inquiryMeta: inquiryResult.__inquiryMeta ?? {}
|
|
2603
2671
|
};
|
|
2604
2672
|
}
|
|
2673
|
+
async requestRuntimeStatusViaRest(instance, serviceName, serviceInstanceId) {
|
|
2674
|
+
if (typeof globalThis.fetch !== "function") {
|
|
2675
|
+
return null;
|
|
2676
|
+
}
|
|
2677
|
+
const transport = this.getRouteableTransport(instance, "rest");
|
|
2678
|
+
if (!transport) {
|
|
2679
|
+
return null;
|
|
2680
|
+
}
|
|
2681
|
+
const controller = typeof AbortController === "function" ? new AbortController() : null;
|
|
2682
|
+
const timeoutId = controller ? setTimeout(() => controller.abort(), this.runtimeStatusFallbackTimeoutMs) : null;
|
|
2683
|
+
try {
|
|
2684
|
+
const response = await globalThis.fetch(`${transport.origin}/status`, {
|
|
2685
|
+
method: "GET",
|
|
2686
|
+
signal: controller?.signal
|
|
2687
|
+
});
|
|
2688
|
+
if ("ok" in response && response.ok === false) {
|
|
2689
|
+
return null;
|
|
2690
|
+
}
|
|
2691
|
+
const payload = typeof response.json === "function" ? await response.json() : response;
|
|
2692
|
+
const report = this.normalizeRuntimeStatusReport({
|
|
2693
|
+
...payload,
|
|
2694
|
+
serviceTransportId: payload?.serviceTransportId ?? transport.uuid,
|
|
2695
|
+
serviceOrigin: payload?.serviceOrigin ?? transport.origin,
|
|
2696
|
+
transportProtocols: payload?.transportProtocols ?? transport.protocols
|
|
2697
|
+
});
|
|
2698
|
+
if (!report) {
|
|
2699
|
+
return null;
|
|
2700
|
+
}
|
|
2701
|
+
if (report.serviceName !== serviceName || report.serviceInstanceId !== serviceInstanceId) {
|
|
2702
|
+
return null;
|
|
2703
|
+
}
|
|
2704
|
+
return report;
|
|
2705
|
+
} catch {
|
|
2706
|
+
return null;
|
|
2707
|
+
} finally {
|
|
2708
|
+
if (timeoutId) {
|
|
2709
|
+
clearTimeout(timeoutId);
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2605
2713
|
evaluateDependencyReadinessDetail(serviceName, serviceInstanceId, now = Date.now()) {
|
|
2606
2714
|
const instance = this.getInstance(serviceName, serviceInstanceId);
|
|
2607
2715
|
const missedHeartbeats = this.getHeartbeatMisses(serviceInstanceId, now);
|
|
@@ -3103,15 +3211,11 @@ var RestController = class _RestController {
|
|
|
3103
3211
|
CadenzaService.emit(ctx2.__signalName, ctx2);
|
|
3104
3212
|
});
|
|
3105
3213
|
app.get("/status", (req, res) => {
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
).doAfter(CadenzaService.serviceRegistry.getStatusTask);
|
|
3112
|
-
CadenzaService.emit(
|
|
3113
|
-
"meta.rest.status_check_requested",
|
|
3114
|
-
req.body.query
|
|
3214
|
+
const statusCheckQuery = req?.body?.query && typeof req.body.query === "object" ? req.body.query : req?.query && typeof req.query === "object" ? { ...req.query } : {};
|
|
3215
|
+
res.json(
|
|
3216
|
+
CadenzaService.serviceRegistry.resolveLocalStatusCheck(
|
|
3217
|
+
statusCheckQuery
|
|
3218
|
+
)
|
|
3115
3219
|
);
|
|
3116
3220
|
});
|
|
3117
3221
|
return true;
|
|
@@ -4183,13 +4287,7 @@ var SocketController = class _SocketController {
|
|
|
4183
4287
|
ws.on(
|
|
4184
4288
|
"status_check",
|
|
4185
4289
|
(ctx, callback) => {
|
|
4186
|
-
CadenzaService.
|
|
4187
|
-
"Resolve status check",
|
|
4188
|
-
callback,
|
|
4189
|
-
"Resolves a status check request",
|
|
4190
|
-
{ register: false }
|
|
4191
|
-
).doAfter(CadenzaService.serviceRegistry.getStatusTask);
|
|
4192
|
-
CadenzaService.emit("meta.socket.status_check_requested", ctx);
|
|
4290
|
+
callback(CadenzaService.serviceRegistry.resolveLocalStatusCheck(ctx));
|
|
4193
4291
|
}
|
|
4194
4292
|
);
|
|
4195
4293
|
ws.on("disconnect", () => {
|