@cadenza.io/service 2.15.0 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -0
- package/dist/browser/index.js +8005 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/index.mjs +7978 -0
- package/dist/browser/index.mjs.map +1 -0
- package/dist/index.d.mts +196 -22
- package/dist/index.d.ts +196 -22
- package/dist/index.js +1489 -468
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1483 -464
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
Actor: () => import_core5.Actor,
|
|
34
|
+
DatabaseController: () => DatabaseController,
|
|
34
35
|
DatabaseTask: () => DatabaseTask,
|
|
35
36
|
DebounceTask: () => import_core5.DebounceTask,
|
|
36
37
|
DeputyTask: () => DeputyTask,
|
|
@@ -43,6 +44,7 @@ __export(index_exports, {
|
|
|
43
44
|
SignalTransmissionTask: () => SignalTransmissionTask,
|
|
44
45
|
SocketController: () => SocketController,
|
|
45
46
|
Task: () => import_core5.Task,
|
|
47
|
+
createSSRInquiryBridge: () => createSSRInquiryBridge,
|
|
46
48
|
default: () => index_default
|
|
47
49
|
});
|
|
48
50
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -87,7 +89,7 @@ var DeputyTask = class extends import_core.Task {
|
|
|
87
89
|
return;
|
|
88
90
|
}
|
|
89
91
|
if (context.__metadata.__skipRemoteExecution) {
|
|
90
|
-
resolve(
|
|
92
|
+
resolve(context);
|
|
91
93
|
return;
|
|
92
94
|
}
|
|
93
95
|
const processId = (0, import_uuid.v4)();
|
|
@@ -190,6 +192,8 @@ var DeputyTask = class extends import_core.Task {
|
|
|
190
192
|
__executionTraceId: metadata.__executionTraceId ?? null,
|
|
191
193
|
__metadata: {
|
|
192
194
|
...metadata,
|
|
195
|
+
__skipRemoteExecution: metadata.__skipRemoteExecution ?? ctx.__skipRemoteExecution ?? false,
|
|
196
|
+
__blockRemoteExecution: metadata.__blockRemoteExecution ?? ctx.__blockRemoteExecution ?? false,
|
|
193
197
|
__deputyTaskName: this.name
|
|
194
198
|
},
|
|
195
199
|
...ctx
|
|
@@ -268,6 +272,7 @@ var DatabaseTask = class extends DeputyTask {
|
|
|
268
272
|
const dynamicQueryData = ctx.queryData ?? {};
|
|
269
273
|
delete ctx.queryData;
|
|
270
274
|
const deputyContext = {
|
|
275
|
+
...ctx,
|
|
271
276
|
__localTaskName: this.name,
|
|
272
277
|
__localTaskVersion: this.version,
|
|
273
278
|
__localServiceName: CadenzaService.serviceRegistry.serviceName,
|
|
@@ -278,6 +283,8 @@ var DatabaseTask = class extends DeputyTask {
|
|
|
278
283
|
__localRoutineExecId: metadata.__routineExecId ?? metadata.__metadata?.__routineExecId,
|
|
279
284
|
__metadata: {
|
|
280
285
|
...metadata,
|
|
286
|
+
__skipRemoteExecution: metadata.__skipRemoteExecution ?? ctx.__skipRemoteExecution ?? false,
|
|
287
|
+
__blockRemoteExecution: metadata.__blockRemoteExecution ?? ctx.__blockRemoteExecution ?? false,
|
|
281
288
|
__deputyTaskName: this.name
|
|
282
289
|
},
|
|
283
290
|
queryData: {
|
|
@@ -364,6 +371,167 @@ function summarizeResponderStatuses(statuses) {
|
|
|
364
371
|
return { responded, failed, timedOut, pending };
|
|
365
372
|
}
|
|
366
373
|
|
|
374
|
+
// src/utils/transport.ts
|
|
375
|
+
var DEFAULT_PROTOCOLS = ["rest", "socket"];
|
|
376
|
+
function normalizeString(value) {
|
|
377
|
+
return typeof value === "string" ? value.trim() : "";
|
|
378
|
+
}
|
|
379
|
+
function normalizeTransportProtocols(value) {
|
|
380
|
+
const rawValues = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : [];
|
|
381
|
+
const normalized = rawValues.map((entry) => normalizeString(entry)).filter(
|
|
382
|
+
(entry) => entry === "rest" || entry === "socket"
|
|
383
|
+
);
|
|
384
|
+
return Array.from(new Set(normalized));
|
|
385
|
+
}
|
|
386
|
+
function normalizeTransportOrigin(origin) {
|
|
387
|
+
const raw = normalizeString(origin);
|
|
388
|
+
if (!raw) {
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
let parsed;
|
|
392
|
+
try {
|
|
393
|
+
parsed = new URL(raw);
|
|
394
|
+
} catch {
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
if (parsed.pathname && parsed.pathname !== "/") {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
if (parsed.search || parsed.hash) {
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
return parsed.origin;
|
|
407
|
+
}
|
|
408
|
+
function normalizeSecurityProfile(value) {
|
|
409
|
+
const normalized = normalizeString(value);
|
|
410
|
+
if (normalized === "low" || normalized === "medium" || normalized === "high") {
|
|
411
|
+
return normalized;
|
|
412
|
+
}
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
function normalizeServiceTransportConfig(value) {
|
|
416
|
+
const raw = value ?? {};
|
|
417
|
+
const role = normalizeString(raw.role);
|
|
418
|
+
const origin = normalizeTransportOrigin(raw.origin);
|
|
419
|
+
const protocols = normalizeTransportProtocols(raw.protocols);
|
|
420
|
+
if (!origin) {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
if (role !== "internal" && role !== "public") {
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
role,
|
|
428
|
+
origin,
|
|
429
|
+
protocols: protocols.length > 0 ? protocols : [...DEFAULT_PROTOCOLS],
|
|
430
|
+
securityProfile: normalizeSecurityProfile(raw.securityProfile),
|
|
431
|
+
authStrategy: normalizeString(raw.authStrategy) || null
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
function normalizeServiceTransportDescriptor(value) {
|
|
435
|
+
const raw = value ?? {};
|
|
436
|
+
const uuid5 = normalizeString(raw.uuid);
|
|
437
|
+
const serviceInstanceId = normalizeString(
|
|
438
|
+
raw.serviceInstanceId ?? raw.service_instance_id
|
|
439
|
+
);
|
|
440
|
+
const config = normalizeServiceTransportConfig(raw);
|
|
441
|
+
if (!uuid5 || !serviceInstanceId || !config) {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
uuid: uuid5,
|
|
446
|
+
serviceInstanceId,
|
|
447
|
+
role: config.role,
|
|
448
|
+
origin: config.origin,
|
|
449
|
+
protocols: config.protocols ?? [...DEFAULT_PROTOCOLS],
|
|
450
|
+
securityProfile: config.securityProfile ?? null,
|
|
451
|
+
authStrategy: config.authStrategy ?? null,
|
|
452
|
+
deleted: Boolean(raw.deleted),
|
|
453
|
+
clientCreated: Boolean(raw.clientCreated ?? raw.client_created ?? false)
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
function transportSupportsProtocol(transport, protocol) {
|
|
457
|
+
return !!transport && transport.protocols.includes(protocol);
|
|
458
|
+
}
|
|
459
|
+
function selectTransportForRole(transports, role, protocol) {
|
|
460
|
+
const filtered = transports.filter(
|
|
461
|
+
(transport) => !transport.deleted && transport.role === role && (!protocol || transportSupportsProtocol(transport, protocol))
|
|
462
|
+
);
|
|
463
|
+
return filtered[0];
|
|
464
|
+
}
|
|
465
|
+
function buildTransportClientKey(transport) {
|
|
466
|
+
return transport.uuid;
|
|
467
|
+
}
|
|
468
|
+
function parseTransportOrigin(origin) {
|
|
469
|
+
const normalized = normalizeTransportOrigin(origin);
|
|
470
|
+
if (!normalized) {
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
const parsed = new URL(normalized);
|
|
474
|
+
const protocol = parsed.protocol === "https:" ? "https" : "http";
|
|
475
|
+
const port = parsed.port ? Number(parsed.port) : protocol === "https" ? 443 : 80;
|
|
476
|
+
return {
|
|
477
|
+
protocol,
|
|
478
|
+
hostname: parsed.hostname,
|
|
479
|
+
port
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// src/utils/serviceInstance.ts
|
|
484
|
+
function normalizeString2(value) {
|
|
485
|
+
return typeof value === "string" ? value.trim() : "";
|
|
486
|
+
}
|
|
487
|
+
function normalizeTransportArray(value, serviceInstanceId) {
|
|
488
|
+
if (!Array.isArray(value)) {
|
|
489
|
+
return [];
|
|
490
|
+
}
|
|
491
|
+
return value.map(
|
|
492
|
+
(entry) => normalizeServiceTransportDescriptor({
|
|
493
|
+
...entry ?? {},
|
|
494
|
+
service_instance_id: entry?.service_instance_id ?? entry?.serviceInstanceId ?? serviceInstanceId
|
|
495
|
+
})
|
|
496
|
+
).filter((transport) => !!transport).sort((left, right) => left.origin.localeCompare(right.origin));
|
|
497
|
+
}
|
|
498
|
+
function normalizeServiceInstanceDescriptor(value) {
|
|
499
|
+
const raw = value ?? {};
|
|
500
|
+
const uuid5 = normalizeString2(raw.uuid);
|
|
501
|
+
const serviceName = normalizeString2(raw.serviceName ?? raw.service_name);
|
|
502
|
+
if (!uuid5 || !serviceName) {
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
const transports = normalizeTransportArray(raw.transports, uuid5);
|
|
506
|
+
return {
|
|
507
|
+
uuid: uuid5,
|
|
508
|
+
serviceName,
|
|
509
|
+
numberOfRunningGraphs: Math.max(
|
|
510
|
+
0,
|
|
511
|
+
Math.trunc(
|
|
512
|
+
Number(raw.numberOfRunningGraphs ?? raw.number_of_running_graphs ?? 0) || 0
|
|
513
|
+
)
|
|
514
|
+
),
|
|
515
|
+
isPrimary: Boolean(raw.isPrimary ?? raw.is_primary ?? false),
|
|
516
|
+
isActive: Boolean(raw.isActive ?? raw.is_active ?? true),
|
|
517
|
+
isNonResponsive: Boolean(
|
|
518
|
+
raw.isNonResponsive ?? raw.is_non_responsive ?? false
|
|
519
|
+
),
|
|
520
|
+
isBlocked: Boolean(raw.isBlocked ?? raw.is_blocked ?? false),
|
|
521
|
+
runtimeState: raw.runtimeState === "healthy" || raw.runtimeState === "degraded" || raw.runtimeState === "overloaded" || raw.runtimeState === "unavailable" ? raw.runtimeState : void 0,
|
|
522
|
+
acceptingWork: typeof raw.acceptingWork === "boolean" ? raw.acceptingWork : void 0,
|
|
523
|
+
reportedAt: typeof raw.reportedAt === "string" ? raw.reportedAt : typeof raw.reported_at === "string" ? raw.reported_at : void 0,
|
|
524
|
+
health: raw.health ?? {},
|
|
525
|
+
isFrontend: Boolean(raw.isFrontend ?? raw.is_frontend ?? false),
|
|
526
|
+
isDatabase: Boolean(raw.isDatabase ?? raw.is_database ?? false),
|
|
527
|
+
transports,
|
|
528
|
+
clientCreatedTransportIds: Array.isArray(raw.clientCreatedTransportIds) ? raw.clientCreatedTransportIds.map((entry) => normalizeString2(entry)).filter((entry) => entry.length > 0) : void 0
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
function getRouteableTransport(instance, role, protocol) {
|
|
532
|
+
return selectTransportForRole(instance.transports ?? [], role, protocol);
|
|
533
|
+
}
|
|
534
|
+
|
|
367
535
|
// src/utils/readiness.ts
|
|
368
536
|
function evaluateDependencyReadiness(input) {
|
|
369
537
|
const missedHeartbeats = Math.max(
|
|
@@ -610,6 +778,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
610
778
|
this.numberOfRunningGraphs = 0;
|
|
611
779
|
this.useSocket = false;
|
|
612
780
|
this.retryCount = 3;
|
|
781
|
+
this.isFrontend = false;
|
|
613
782
|
CadenzaService.defineIntent({
|
|
614
783
|
name: META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT,
|
|
615
784
|
description: "Gather transport diagnostics across all services and communication clients.",
|
|
@@ -757,57 +926,60 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
757
926
|
this.handleInstanceUpdateTask = CadenzaService.createMetaTask(
|
|
758
927
|
"Handle Instance Update",
|
|
759
928
|
(ctx, emit) => {
|
|
760
|
-
const serviceInstance =
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
if (!serviceInstance
|
|
929
|
+
const serviceInstance = normalizeServiceInstanceDescriptor(
|
|
930
|
+
ctx.serviceInstance ?? ctx.data ?? ctx.queryData?.data ?? (ctx.__serviceInstanceId || ctx.serviceInstanceId ? {
|
|
931
|
+
uuid: ctx.__serviceInstanceId ?? ctx.serviceInstanceId,
|
|
932
|
+
serviceName: ctx.__serviceName ?? ctx.serviceName,
|
|
933
|
+
isFrontend: !!ctx.isFrontend,
|
|
934
|
+
isActive: typeof ctx.isActive === "boolean" ? ctx.isActive : typeof ctx.__active === "boolean" ? ctx.__active : true,
|
|
935
|
+
isNonResponsive: !!ctx.isNonResponsive,
|
|
936
|
+
isBlocked: !!ctx.isBlocked,
|
|
937
|
+
health: ctx.health ?? ctx.__health ?? {},
|
|
938
|
+
numberOfRunningGraphs: ctx.numberOfRunningGraphs ?? ctx.__numberOfRunningGraphs ?? 0,
|
|
939
|
+
isPrimary: false,
|
|
940
|
+
transports: ctx.transports ?? []
|
|
941
|
+
} : void 0)
|
|
942
|
+
);
|
|
943
|
+
if (!serviceInstance) {
|
|
775
944
|
return false;
|
|
776
945
|
}
|
|
777
|
-
const
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
isFrontend,
|
|
784
|
-
deleted
|
|
785
|
-
} = serviceInstance;
|
|
786
|
-
if (uuid4 === this.serviceInstanceId) return;
|
|
946
|
+
const uuid5 = serviceInstance.uuid;
|
|
947
|
+
const serviceName = serviceInstance.serviceName;
|
|
948
|
+
const deleted = Boolean(
|
|
949
|
+
ctx.deleted ?? ctx.serviceInstance?.deleted ?? ctx.data?.deleted
|
|
950
|
+
);
|
|
951
|
+
if (uuid5 === this.serviceInstanceId) return;
|
|
787
952
|
if (deleted) {
|
|
788
|
-
const
|
|
789
|
-
|
|
953
|
+
const existingInstance = this.instances.get(serviceName)?.find((instance) => instance.uuid === uuid5);
|
|
954
|
+
const indexToDelete = this.instances.get(serviceName)?.findIndex((i) => i.uuid === uuid5) ?? -1;
|
|
955
|
+
if (indexToDelete >= 0 && existingInstance) {
|
|
790
956
|
this.instances.get(serviceName)?.splice(indexToDelete, 1);
|
|
957
|
+
for (const transport of existingInstance.transports) {
|
|
958
|
+
const transportKey = buildTransportClientKey(transport);
|
|
959
|
+
emit(`meta.socket_shutdown_requested:${transportKey}`, {});
|
|
960
|
+
emit(`meta.fetch.destroy_requested:${transportKey}`, {});
|
|
961
|
+
}
|
|
791
962
|
}
|
|
792
963
|
if (this.instances.get(serviceName)?.length === 0) {
|
|
793
964
|
this.instances.delete(serviceName);
|
|
794
|
-
} else if (this.instances.get(serviceName)?.filter((i) => i.address === address && i.port === port).length === 0) {
|
|
795
|
-
emit(`meta.socket_shutdown_requested:${address}_${port}`, {});
|
|
796
|
-
emit(`meta.fetch.destroy_requested:${address}_${port}`, {});
|
|
797
965
|
}
|
|
798
|
-
this.unregisterDependee(
|
|
966
|
+
this.unregisterDependee(uuid5, serviceName);
|
|
799
967
|
return;
|
|
800
968
|
}
|
|
801
969
|
if (!this.instances.has(serviceName))
|
|
802
970
|
this.instances.set(serviceName, []);
|
|
803
971
|
const instances = this.instances.get(serviceName);
|
|
804
|
-
const existing = instances.find((i) => i.uuid ===
|
|
972
|
+
const existing = instances.find((i) => i.uuid === uuid5);
|
|
805
973
|
if (existing) {
|
|
806
|
-
Object.assign(existing,
|
|
974
|
+
Object.assign(existing, {
|
|
975
|
+
...serviceInstance,
|
|
976
|
+
transports: serviceInstance.transports.length > 0 ? serviceInstance.transports : existing.transports,
|
|
977
|
+
clientCreatedTransportIds: existing.clientCreatedTransportIds ?? []
|
|
978
|
+
});
|
|
807
979
|
} else {
|
|
808
980
|
instances.push(serviceInstance);
|
|
809
981
|
}
|
|
810
|
-
const trackedInstance = existing ?? instances.find((instance) => instance.uuid ===
|
|
982
|
+
const trackedInstance = existing ?? instances.find((instance) => instance.uuid === uuid5);
|
|
811
983
|
if (trackedInstance) {
|
|
812
984
|
const snapshot = this.resolveRuntimeStatusSnapshot(
|
|
813
985
|
trackedInstance.numberOfRunningGraphs ?? 0,
|
|
@@ -822,31 +994,44 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
822
994
|
if (this.serviceName === serviceName) {
|
|
823
995
|
return false;
|
|
824
996
|
}
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
997
|
+
const trackedTransport = this.getRouteableTransport(
|
|
998
|
+
trackedInstance,
|
|
999
|
+
this.useSocket ? "socket" : "rest"
|
|
1000
|
+
);
|
|
1001
|
+
if (!serviceInstance.isFrontend && (this.deputies.has(serviceName) || this.remoteIntents.has(serviceName)) || this.remoteSignals.has(serviceName)) {
|
|
1002
|
+
const communicationTypes = Array.from(
|
|
1003
|
+
new Set(
|
|
1004
|
+
this.deputies.get(serviceName)?.map((d) => d.communicationType) ?? []
|
|
1005
|
+
)
|
|
828
1006
|
);
|
|
829
|
-
if (!
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
1007
|
+
if (!communicationTypes.includes("signal") && this.remoteSignals.has(serviceName)) {
|
|
1008
|
+
communicationTypes.push("signal");
|
|
1009
|
+
}
|
|
1010
|
+
if (trackedTransport) {
|
|
1011
|
+
const clientCreated = this.hasTransportClientCreated(
|
|
1012
|
+
trackedInstance,
|
|
1013
|
+
trackedTransport.uuid
|
|
834
1014
|
);
|
|
835
|
-
if (!
|
|
836
|
-
|
|
1015
|
+
if (!clientCreated) {
|
|
1016
|
+
emit("meta.service_registry.dependee_registered", {
|
|
1017
|
+
serviceName,
|
|
1018
|
+
serviceInstanceId: uuid5,
|
|
1019
|
+
serviceTransportId: trackedTransport.uuid,
|
|
1020
|
+
serviceOrigin: trackedTransport.origin,
|
|
1021
|
+
transportProtocols: trackedTransport.protocols,
|
|
1022
|
+
communicationTypes
|
|
1023
|
+
});
|
|
1024
|
+
this.markTransportClientCreated(
|
|
1025
|
+
trackedInstance,
|
|
1026
|
+
trackedTransport.uuid
|
|
1027
|
+
);
|
|
837
1028
|
}
|
|
838
|
-
|
|
1029
|
+
} else {
|
|
1030
|
+
emit("meta.service_registry.routeable_transport_missing", {
|
|
839
1031
|
serviceName,
|
|
840
|
-
serviceInstanceId:
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
protocol: exposed ? "https" : "http",
|
|
844
|
-
communicationTypes
|
|
845
|
-
});
|
|
846
|
-
instances?.filter(
|
|
847
|
-
(i) => i.address === address && i.port === port && i.isActive
|
|
848
|
-
).forEach((i) => {
|
|
849
|
-
i.clientCreated = true;
|
|
1032
|
+
serviceInstanceId: uuid5,
|
|
1033
|
+
requiredRole: this.getRoutingTransportRole(),
|
|
1034
|
+
isFrontend: this.isFrontend
|
|
850
1035
|
});
|
|
851
1036
|
}
|
|
852
1037
|
}
|
|
@@ -864,6 +1049,81 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
864
1049
|
"meta.socket_shutdown_requested",
|
|
865
1050
|
"meta.fetch.destroy_requested"
|
|
866
1051
|
);
|
|
1052
|
+
this.handleTransportUpdateTask = CadenzaService.createMetaTask(
|
|
1053
|
+
"Handle Transport Update",
|
|
1054
|
+
(ctx, emit) => {
|
|
1055
|
+
const transport = normalizeServiceTransportDescriptor(
|
|
1056
|
+
ctx.serviceTransport ?? ctx.data ?? ctx.queryData?.data ?? ctx
|
|
1057
|
+
);
|
|
1058
|
+
if (!transport) {
|
|
1059
|
+
return false;
|
|
1060
|
+
}
|
|
1061
|
+
let ownerInstance;
|
|
1062
|
+
for (const instances of this.instances.values()) {
|
|
1063
|
+
ownerInstance = instances.find(
|
|
1064
|
+
(instance) => instance.uuid === transport.serviceInstanceId
|
|
1065
|
+
);
|
|
1066
|
+
if (ownerInstance) {
|
|
1067
|
+
break;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
if (!ownerInstance) {
|
|
1071
|
+
return false;
|
|
1072
|
+
}
|
|
1073
|
+
if (transport.deleted) {
|
|
1074
|
+
ownerInstance.transports = ownerInstance.transports.filter(
|
|
1075
|
+
(existingTransport2) => existingTransport2.uuid !== transport.uuid
|
|
1076
|
+
);
|
|
1077
|
+
const transportKey = buildTransportClientKey(transport);
|
|
1078
|
+
emit(`meta.socket_shutdown_requested:${transportKey}`, {});
|
|
1079
|
+
emit(`meta.fetch.destroy_requested:${transportKey}`, {});
|
|
1080
|
+
return true;
|
|
1081
|
+
}
|
|
1082
|
+
const existingTransport = this.getTransportById(ownerInstance, transport.uuid);
|
|
1083
|
+
if (existingTransport) {
|
|
1084
|
+
Object.assign(existingTransport, transport);
|
|
1085
|
+
} else {
|
|
1086
|
+
ownerInstance.transports.push(transport);
|
|
1087
|
+
}
|
|
1088
|
+
if (ownerInstance.uuid === this.serviceInstanceId) {
|
|
1089
|
+
return true;
|
|
1090
|
+
}
|
|
1091
|
+
const hasRemoteInterest = (!ownerInstance.isFrontend && (this.deputies.has(ownerInstance.serviceName) || this.remoteIntents.has(ownerInstance.serviceName)) || this.remoteSignals.has(ownerInstance.serviceName)) && transport.role === this.getRoutingTransportRole();
|
|
1092
|
+
if (!hasRemoteInterest) {
|
|
1093
|
+
return true;
|
|
1094
|
+
}
|
|
1095
|
+
if (!this.hasTransportClientCreated(ownerInstance, transport.uuid)) {
|
|
1096
|
+
const communicationTypes = Array.from(
|
|
1097
|
+
new Set(
|
|
1098
|
+
this.deputies.get(ownerInstance.serviceName)?.map((descriptor) => descriptor.communicationType) ?? []
|
|
1099
|
+
)
|
|
1100
|
+
);
|
|
1101
|
+
if (!communicationTypes.includes("signal") && this.remoteSignals.has(ownerInstance.serviceName)) {
|
|
1102
|
+
communicationTypes.push("signal");
|
|
1103
|
+
}
|
|
1104
|
+
emit("meta.service_registry.dependee_registered", {
|
|
1105
|
+
serviceName: ownerInstance.serviceName,
|
|
1106
|
+
serviceInstanceId: ownerInstance.uuid,
|
|
1107
|
+
serviceTransportId: transport.uuid,
|
|
1108
|
+
serviceOrigin: transport.origin,
|
|
1109
|
+
transportProtocols: transport.protocols,
|
|
1110
|
+
communicationTypes
|
|
1111
|
+
});
|
|
1112
|
+
this.markTransportClientCreated(ownerInstance, transport.uuid);
|
|
1113
|
+
}
|
|
1114
|
+
return true;
|
|
1115
|
+
},
|
|
1116
|
+
"Handles service transport updates independently from instance rows."
|
|
1117
|
+
).doOn(
|
|
1118
|
+
"global.meta.service_instance_transport.inserted",
|
|
1119
|
+
"global.meta.service_instance_transport.updated",
|
|
1120
|
+
"meta.service_instance_transport.inserted",
|
|
1121
|
+
"meta.service_instance_transport.updated"
|
|
1122
|
+
).attachSignal(
|
|
1123
|
+
"meta.service_registry.dependee_registered",
|
|
1124
|
+
"meta.socket_shutdown_requested",
|
|
1125
|
+
"meta.fetch.destroy_requested"
|
|
1126
|
+
);
|
|
867
1127
|
CadenzaService.createMetaTask(
|
|
868
1128
|
"Track dependee registration",
|
|
869
1129
|
(ctx) => {
|
|
@@ -959,17 +1219,25 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
959
1219
|
this.handleServiceNotRespondingTask = CadenzaService.createMetaTask(
|
|
960
1220
|
"Handle service not responding",
|
|
961
1221
|
(ctx, emit) => {
|
|
962
|
-
const { serviceName,
|
|
1222
|
+
const { serviceName, serviceInstanceId, serviceTransportId } = ctx;
|
|
963
1223
|
const serviceInstances = this.instances.get(serviceName);
|
|
964
|
-
const instances = serviceInstances?.filter(
|
|
965
|
-
(
|
|
966
|
-
|
|
1224
|
+
const instances = serviceInstances?.filter((instance) => {
|
|
1225
|
+
if (serviceInstanceId && instance.uuid === serviceInstanceId) {
|
|
1226
|
+
return true;
|
|
1227
|
+
}
|
|
1228
|
+
if (serviceTransportId) {
|
|
1229
|
+
return instance.transports.some(
|
|
1230
|
+
(transport) => transport.uuid === serviceTransportId
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
1233
|
+
return false;
|
|
1234
|
+
});
|
|
967
1235
|
CadenzaService.log(
|
|
968
1236
|
"Service not responding.",
|
|
969
1237
|
{
|
|
970
1238
|
serviceName,
|
|
971
|
-
|
|
972
|
-
|
|
1239
|
+
serviceInstanceId,
|
|
1240
|
+
serviceTransportId,
|
|
973
1241
|
instances
|
|
974
1242
|
},
|
|
975
1243
|
"warning",
|
|
@@ -1010,7 +1278,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1010
1278
|
this.handleServiceHandshakeTask = CadenzaService.createMetaTask(
|
|
1011
1279
|
"Handle service handshake",
|
|
1012
1280
|
(ctx, emit) => {
|
|
1013
|
-
const { serviceName, serviceInstanceId
|
|
1281
|
+
const { serviceName, serviceInstanceId } = ctx;
|
|
1014
1282
|
const serviceInstances = this.instances.get(serviceName);
|
|
1015
1283
|
const instance = serviceInstances?.find(
|
|
1016
1284
|
(i) => i.uuid === serviceInstanceId
|
|
@@ -1038,26 +1306,6 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1038
1306
|
uuid: instance.uuid
|
|
1039
1307
|
}
|
|
1040
1308
|
});
|
|
1041
|
-
const instancesToDelete = serviceInstances?.filter(
|
|
1042
|
-
(i) => i.uuid !== serviceInstanceId && i.address === serviceAddress && i.port === servicePort
|
|
1043
|
-
);
|
|
1044
|
-
for (const i of instancesToDelete ?? []) {
|
|
1045
|
-
const indexToDelete = this.instances.get(serviceName)?.indexOf(i) ?? -1;
|
|
1046
|
-
if (indexToDelete >= 0) {
|
|
1047
|
-
this.instances.get(serviceName)?.splice(indexToDelete, 1);
|
|
1048
|
-
}
|
|
1049
|
-
this.unregisterDependee(i.uuid, serviceName);
|
|
1050
|
-
emit("global.meta.service_registry.deleted", {
|
|
1051
|
-
data: {
|
|
1052
|
-
isActive: false,
|
|
1053
|
-
isNonResponsive: false,
|
|
1054
|
-
deleted: true
|
|
1055
|
-
},
|
|
1056
|
-
filter: {
|
|
1057
|
-
uuid: i.uuid
|
|
1058
|
-
}
|
|
1059
|
-
});
|
|
1060
|
-
}
|
|
1061
1309
|
return true;
|
|
1062
1310
|
},
|
|
1063
1311
|
"Handles service handshake"
|
|
@@ -1076,16 +1324,13 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1076
1324
|
return false;
|
|
1077
1325
|
}
|
|
1078
1326
|
let applied = this.applyRuntimeStatusReport(report);
|
|
1079
|
-
if (!applied && report.
|
|
1327
|
+
if (!applied && report.transportId && report.transportOrigin) {
|
|
1080
1328
|
if (!this.instances.has(report.serviceName)) {
|
|
1081
1329
|
this.instances.set(report.serviceName, []);
|
|
1082
1330
|
}
|
|
1083
1331
|
this.instances.get(report.serviceName).push({
|
|
1084
1332
|
uuid: report.serviceInstanceId,
|
|
1085
1333
|
serviceName: report.serviceName,
|
|
1086
|
-
address: report.serviceAddress,
|
|
1087
|
-
port: report.servicePort,
|
|
1088
|
-
exposed: !!report.exposed,
|
|
1089
1334
|
isFrontend: !!report.isFrontend,
|
|
1090
1335
|
isActive: report.isActive,
|
|
1091
1336
|
isNonResponsive: report.isNonResponsive,
|
|
@@ -1095,7 +1340,18 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1095
1340
|
acceptingWork: report.acceptingWork,
|
|
1096
1341
|
reportedAt: report.reportedAt,
|
|
1097
1342
|
health: report.health ?? {},
|
|
1098
|
-
isPrimary: false
|
|
1343
|
+
isPrimary: false,
|
|
1344
|
+
transports: [
|
|
1345
|
+
{
|
|
1346
|
+
uuid: report.transportId,
|
|
1347
|
+
serviceInstanceId: report.serviceInstanceId,
|
|
1348
|
+
role: this.getRoutingTransportRole(),
|
|
1349
|
+
origin: report.transportOrigin,
|
|
1350
|
+
protocols: report.transportProtocols && report.transportProtocols.length > 0 ? report.transportProtocols : ["rest", "socket"],
|
|
1351
|
+
securityProfile: null,
|
|
1352
|
+
authStrategy: null
|
|
1353
|
+
}
|
|
1354
|
+
]
|
|
1099
1355
|
});
|
|
1100
1356
|
applied = true;
|
|
1101
1357
|
}
|
|
@@ -1136,21 +1392,9 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1136
1392
|
deleted: !!m.deleted
|
|
1137
1393
|
})
|
|
1138
1394
|
);
|
|
1139
|
-
const serviceInstances = (inquiryResult.serviceInstances ?? []).filter(
|
|
1140
|
-
(instance) =>
|
|
1141
|
-
)
|
|
1142
|
-
uuid: instance.uuid,
|
|
1143
|
-
address: instance.address,
|
|
1144
|
-
port: instance.port,
|
|
1145
|
-
serviceName: instance.serviceName,
|
|
1146
|
-
isActive: !!instance.isActive,
|
|
1147
|
-
isNonResponsive: !!instance.isNonResponsive,
|
|
1148
|
-
isBlocked: !!instance.isBlocked,
|
|
1149
|
-
health: instance.health ?? {},
|
|
1150
|
-
exposed: !!instance.exposed,
|
|
1151
|
-
created: instance.created,
|
|
1152
|
-
isFrontend: !!instance.isFrontend
|
|
1153
|
-
}));
|
|
1395
|
+
const serviceInstances = (inquiryResult.serviceInstances ?? []).map((instance) => normalizeServiceInstanceDescriptor(instance)).filter(
|
|
1396
|
+
(instance) => !!instance && !!instance.isActive && !instance.isNonResponsive && !instance.isBlocked
|
|
1397
|
+
);
|
|
1154
1398
|
return {
|
|
1155
1399
|
...ctx,
|
|
1156
1400
|
signalToTaskMaps,
|
|
@@ -1237,7 +1481,19 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1237
1481
|
const { __serviceName, __triedInstances, __retries, __broadcast } = context;
|
|
1238
1482
|
let retries = __retries ?? 0;
|
|
1239
1483
|
let triedInstances = __triedInstances ?? [];
|
|
1240
|
-
const
|
|
1484
|
+
const preferredRole = this.getRoutingTransportRole();
|
|
1485
|
+
const instances = this.instances.get(__serviceName)?.filter((instance) => {
|
|
1486
|
+
if (!instance.isActive || instance.isNonResponsive || instance.isBlocked) {
|
|
1487
|
+
return false;
|
|
1488
|
+
}
|
|
1489
|
+
return Boolean(
|
|
1490
|
+
this.getRouteableTransport(
|
|
1491
|
+
instance,
|
|
1492
|
+
this.useSocket ? "socket" : "rest",
|
|
1493
|
+
preferredRole
|
|
1494
|
+
) ?? this.getRouteableTransport(instance, "rest", preferredRole)
|
|
1495
|
+
);
|
|
1496
|
+
}).sort((a, b) => {
|
|
1241
1497
|
const leftStatus = this.resolveRuntimeStatusSnapshot(
|
|
1242
1498
|
a.numberOfRunningGraphs ?? 0,
|
|
1243
1499
|
a.isActive,
|
|
@@ -1258,9 +1514,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1258
1514
|
});
|
|
1259
1515
|
if (!instances || instances.length === 0 || retries > this.retryCount) {
|
|
1260
1516
|
context.errored = true;
|
|
1261
|
-
context.__error = `No
|
|
1262
|
-
__serviceName
|
|
1263
|
-
)}`;
|
|
1517
|
+
context.__error = this.isFrontend && preferredRole === "public" ? `No public transport available for ${__serviceName}.` : `No routeable ${preferredRole} transport available for ${__serviceName}. Retries: ${retries}.`;
|
|
1264
1518
|
emit(
|
|
1265
1519
|
`meta.service_registry.load_balance_failed:${context.__metadata.__deputyExecId}`,
|
|
1266
1520
|
context
|
|
@@ -1269,10 +1523,21 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1269
1523
|
}
|
|
1270
1524
|
if (__broadcast || instances[0].isFrontend) {
|
|
1271
1525
|
for (const instance of instances) {
|
|
1272
|
-
const
|
|
1526
|
+
const selectedTransport2 = this.getRouteableTransport(instance, "socket", preferredRole) ?? this.getRouteableTransport(instance, "rest", preferredRole);
|
|
1527
|
+
if (!selectedTransport2) {
|
|
1528
|
+
continue;
|
|
1529
|
+
}
|
|
1530
|
+
const transportKey = buildTransportClientKey(selectedTransport2);
|
|
1273
1531
|
emit(
|
|
1274
|
-
|
|
1275
|
-
|
|
1532
|
+
`${this.useSocket && transportSupportsProtocol(selectedTransport2, "socket") ? "meta.service_registry.selected_instance_for_socket" : "meta.service_registry.selected_instance_for_fetch"}:${transportKey}`,
|
|
1533
|
+
{
|
|
1534
|
+
...context,
|
|
1535
|
+
__instance: instance.uuid,
|
|
1536
|
+
__transportId: selectedTransport2.uuid,
|
|
1537
|
+
__transportOrigin: selectedTransport2.origin,
|
|
1538
|
+
__transportProtocols: selectedTransport2.protocols,
|
|
1539
|
+
__fetchId: transportKey
|
|
1540
|
+
}
|
|
1276
1541
|
);
|
|
1277
1542
|
}
|
|
1278
1543
|
return context;
|
|
@@ -1295,12 +1560,25 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1295
1560
|
if (retries > 0) {
|
|
1296
1561
|
selected = instancesToTry[Math.floor(Math.random() * instancesToTry.length)];
|
|
1297
1562
|
}
|
|
1563
|
+
const selectedTransport = this.getRouteableTransport(selected, "socket", preferredRole) ?? this.getRouteableTransport(selected, "rest", preferredRole);
|
|
1564
|
+
if (!selectedTransport) {
|
|
1565
|
+
context.errored = true;
|
|
1566
|
+
context.__error = `No routeable ${preferredRole} transport available for ${selected.serviceName}/${selected.uuid}.`;
|
|
1567
|
+
emit(
|
|
1568
|
+
`meta.service_registry.load_balance_failed:${context.__metadata.__deputyExecId}`,
|
|
1569
|
+
context
|
|
1570
|
+
);
|
|
1571
|
+
return context;
|
|
1572
|
+
}
|
|
1298
1573
|
context.__instance = selected.uuid;
|
|
1299
|
-
context.
|
|
1574
|
+
context.__transportId = selectedTransport.uuid;
|
|
1575
|
+
context.__transportOrigin = selectedTransport.origin;
|
|
1576
|
+
context.__transportProtocols = selectedTransport.protocols;
|
|
1577
|
+
context.__fetchId = buildTransportClientKey(selectedTransport);
|
|
1300
1578
|
context.__triedInstances = triedInstances;
|
|
1301
1579
|
context.__triedInstances.push(selected.uuid);
|
|
1302
1580
|
context.__retries = retries;
|
|
1303
|
-
if (this.useSocket) {
|
|
1581
|
+
if (this.useSocket && transportSupportsProtocol(selectedTransport, "socket")) {
|
|
1304
1582
|
emit(
|
|
1305
1583
|
`meta.service_registry.selected_instance_for_socket:${context.__fetchId}`,
|
|
1306
1584
|
context
|
|
@@ -1492,9 +1770,9 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1492
1770
|
__active: report.isActive,
|
|
1493
1771
|
serviceName: report.serviceName,
|
|
1494
1772
|
serviceInstanceId: report.serviceInstanceId,
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1773
|
+
transportId: report.transportId,
|
|
1774
|
+
transportOrigin: report.transportOrigin,
|
|
1775
|
+
transportProtocols: report.transportProtocols,
|
|
1498
1776
|
isFrontend: report.isFrontend,
|
|
1499
1777
|
reportedAt: report.reportedAt,
|
|
1500
1778
|
numberOfRunningGraphs: report.numberOfRunningGraphs,
|
|
@@ -1537,12 +1815,17 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1537
1815
|
continue;
|
|
1538
1816
|
}
|
|
1539
1817
|
this.runtimeStatusFallbackInFlightByInstance.add(serviceInstanceId);
|
|
1818
|
+
const transport = this.getRouteableTransport(
|
|
1819
|
+
instance,
|
|
1820
|
+
this.useSocket ? "socket" : "rest"
|
|
1821
|
+
);
|
|
1540
1822
|
emit("meta.service_registry.runtime_status_fallback_requested", {
|
|
1541
1823
|
...ctx,
|
|
1542
1824
|
serviceName,
|
|
1543
1825
|
serviceInstanceId,
|
|
1544
|
-
|
|
1545
|
-
|
|
1826
|
+
serviceTransportId: transport?.uuid,
|
|
1827
|
+
serviceOrigin: transport?.origin,
|
|
1828
|
+
transportProtocols: transport?.protocols
|
|
1546
1829
|
});
|
|
1547
1830
|
}
|
|
1548
1831
|
}
|
|
@@ -1576,6 +1859,10 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1576
1859
|
};
|
|
1577
1860
|
} catch (error) {
|
|
1578
1861
|
const instance = this.getInstance(serviceName, serviceInstanceId);
|
|
1862
|
+
const transport = instance ? this.getRouteableTransport(
|
|
1863
|
+
instance,
|
|
1864
|
+
this.useSocket ? "socket" : "rest"
|
|
1865
|
+
) : void 0;
|
|
1579
1866
|
const message = error instanceof Error ? error.message : String(error);
|
|
1580
1867
|
CadenzaService.log(
|
|
1581
1868
|
"Runtime status fallback inquiry failed.",
|
|
@@ -1590,8 +1877,9 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1590
1877
|
...ctx,
|
|
1591
1878
|
serviceName,
|
|
1592
1879
|
serviceInstanceId,
|
|
1593
|
-
|
|
1594
|
-
|
|
1880
|
+
serviceTransportId: transport?.uuid ?? ctx.serviceTransportId,
|
|
1881
|
+
serviceOrigin: transport?.origin ?? ctx.serviceOrigin,
|
|
1882
|
+
transportProtocols: transport?.protocols ?? ctx.transportProtocols,
|
|
1595
1883
|
__error: message,
|
|
1596
1884
|
errored: true
|
|
1597
1885
|
});
|
|
@@ -1704,85 +1992,185 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1704
1992
|
inputSchema: {
|
|
1705
1993
|
type: "object",
|
|
1706
1994
|
properties: {
|
|
1707
|
-
|
|
1708
|
-
type: "
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1995
|
+
data: {
|
|
1996
|
+
type: "object",
|
|
1997
|
+
properties: {
|
|
1998
|
+
uuid: {
|
|
1999
|
+
type: "string"
|
|
2000
|
+
},
|
|
2001
|
+
process_pid: {
|
|
2002
|
+
type: "number"
|
|
2003
|
+
},
|
|
2004
|
+
is_primary: {
|
|
2005
|
+
type: "boolean"
|
|
2006
|
+
},
|
|
2007
|
+
service_name: {
|
|
2008
|
+
type: "string"
|
|
2009
|
+
},
|
|
2010
|
+
is_active: {
|
|
2011
|
+
type: "boolean"
|
|
2012
|
+
},
|
|
2013
|
+
is_frontend: {
|
|
2014
|
+
type: "boolean"
|
|
2015
|
+
},
|
|
2016
|
+
is_database: {
|
|
2017
|
+
type: "boolean"
|
|
2018
|
+
},
|
|
2019
|
+
is_non_responsive: {
|
|
2020
|
+
type: "boolean"
|
|
2021
|
+
},
|
|
2022
|
+
is_blocked: {
|
|
2023
|
+
type: "boolean"
|
|
2024
|
+
},
|
|
2025
|
+
health: {
|
|
2026
|
+
type: "object"
|
|
2027
|
+
}
|
|
2028
|
+
},
|
|
2029
|
+
required: ["uuid", "process_pid", "service_name"]
|
|
1736
2030
|
}
|
|
1737
2031
|
},
|
|
1738
|
-
required: [
|
|
1739
|
-
"id",
|
|
1740
|
-
"address",
|
|
1741
|
-
"port",
|
|
1742
|
-
"process_pid",
|
|
1743
|
-
"service_name",
|
|
1744
|
-
"exposed"
|
|
1745
|
-
]
|
|
2032
|
+
required: ["data"]
|
|
1746
2033
|
},
|
|
1747
|
-
// validateInputContext: true,
|
|
1748
2034
|
outputSchema: {
|
|
1749
2035
|
type: "object",
|
|
1750
2036
|
properties: {
|
|
1751
|
-
|
|
2037
|
+
uuid: {
|
|
1752
2038
|
type: "string"
|
|
1753
2039
|
}
|
|
1754
2040
|
},
|
|
1755
|
-
required: ["
|
|
2041
|
+
required: ["uuid"]
|
|
1756
2042
|
},
|
|
1757
|
-
// validateOutputContext: true,
|
|
1758
2043
|
retryCount: 5,
|
|
1759
2044
|
retryDelay: 1e3
|
|
1760
2045
|
}
|
|
1761
|
-
).doOn("
|
|
2046
|
+
).doOn("meta.service_registry.instance_registration_requested").then(
|
|
1762
2047
|
CadenzaService.createMetaTask(
|
|
1763
2048
|
"Setup service",
|
|
1764
2049
|
(ctx) => {
|
|
1765
|
-
const {
|
|
1766
|
-
|
|
2050
|
+
const {
|
|
2051
|
+
serviceInstance,
|
|
2052
|
+
data,
|
|
2053
|
+
queryData,
|
|
2054
|
+
__useSocket,
|
|
2055
|
+
__retryCount,
|
|
2056
|
+
__isFrontend
|
|
2057
|
+
} = ctx;
|
|
2058
|
+
const normalizedLocalInstance = normalizeServiceInstanceDescriptor({
|
|
2059
|
+
...serviceInstance ?? data ?? queryData?.data ?? {},
|
|
2060
|
+
transports: ctx.transportData ?? []
|
|
2061
|
+
});
|
|
2062
|
+
if (!normalizedLocalInstance?.uuid || !normalizedLocalInstance.serviceName) {
|
|
2063
|
+
return false;
|
|
2064
|
+
}
|
|
2065
|
+
this.serviceInstanceId = normalizedLocalInstance.uuid;
|
|
1767
2066
|
this.instances.set(
|
|
1768
|
-
|
|
1769
|
-
[{ ...
|
|
2067
|
+
normalizedLocalInstance.serviceName,
|
|
2068
|
+
[{ ...normalizedLocalInstance }]
|
|
1770
2069
|
);
|
|
1771
2070
|
this.useSocket = __useSocket;
|
|
1772
2071
|
this.retryCount = __retryCount;
|
|
2072
|
+
this.isFrontend = typeof __isFrontend === "boolean" ? __isFrontend : !!normalizedLocalInstance.isFrontend;
|
|
1773
2073
|
console.log("SETUP SERVICE", this.serviceInstanceId);
|
|
1774
2074
|
return true;
|
|
1775
2075
|
},
|
|
1776
2076
|
"Sets service instance id after insertion"
|
|
1777
|
-
).emits("meta.service_registry.instance_inserted")
|
|
2077
|
+
).emits("meta.service_registry.instance_inserted").then(
|
|
2078
|
+
CadenzaService.createMetaTask(
|
|
2079
|
+
"Prepare service transport inserts",
|
|
2080
|
+
function* (ctx, emit) {
|
|
2081
|
+
const transportData = Array.isArray(ctx.transportData) ? ctx.transportData : [];
|
|
2082
|
+
for (const transport of transportData) {
|
|
2083
|
+
const transportContext = {
|
|
2084
|
+
...ctx,
|
|
2085
|
+
data: {
|
|
2086
|
+
...transport,
|
|
2087
|
+
service_instance_id: transport.service_instance_id ?? ctx.__serviceInstanceId
|
|
2088
|
+
}
|
|
2089
|
+
};
|
|
2090
|
+
emit(
|
|
2091
|
+
"meta.service_registry.transport_registration_requested",
|
|
2092
|
+
transportContext
|
|
2093
|
+
);
|
|
2094
|
+
yield transportContext;
|
|
2095
|
+
}
|
|
2096
|
+
},
|
|
2097
|
+
"Splits declared service transports into individual insert payloads."
|
|
2098
|
+
).attachSignal("meta.service_registry.transport_registration_requested")
|
|
2099
|
+
)
|
|
1778
2100
|
);
|
|
2101
|
+
this.insertServiceTransportTask = CadenzaService.createCadenzaDBInsertTask(
|
|
2102
|
+
"service_instance_transport",
|
|
2103
|
+
{
|
|
2104
|
+
onConflict: {
|
|
2105
|
+
target: ["service_instance_id", "role", "origin"],
|
|
2106
|
+
action: {
|
|
2107
|
+
do: "update",
|
|
2108
|
+
set: {
|
|
2109
|
+
protocols: "excluded",
|
|
2110
|
+
security_profile: "excluded",
|
|
2111
|
+
auth_strategy: "excluded",
|
|
2112
|
+
deleted: "false"
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
},
|
|
2117
|
+
{
|
|
2118
|
+
inputSchema: {
|
|
2119
|
+
type: "object",
|
|
2120
|
+
properties: {
|
|
2121
|
+
data: {
|
|
2122
|
+
type: "object",
|
|
2123
|
+
properties: {
|
|
2124
|
+
uuid: {
|
|
2125
|
+
type: "string"
|
|
2126
|
+
},
|
|
2127
|
+
service_instance_id: {
|
|
2128
|
+
type: "string"
|
|
2129
|
+
},
|
|
2130
|
+
role: {
|
|
2131
|
+
type: "string"
|
|
2132
|
+
},
|
|
2133
|
+
origin: {
|
|
2134
|
+
type: "string"
|
|
2135
|
+
},
|
|
2136
|
+
protocols: {
|
|
2137
|
+
type: "array",
|
|
2138
|
+
items: {
|
|
2139
|
+
type: "string"
|
|
2140
|
+
}
|
|
2141
|
+
},
|
|
2142
|
+
security_profile: {
|
|
2143
|
+
type: "string"
|
|
2144
|
+
},
|
|
2145
|
+
auth_strategy: {
|
|
2146
|
+
type: "string"
|
|
2147
|
+
}
|
|
2148
|
+
},
|
|
2149
|
+
required: ["uuid", "service_instance_id", "role", "origin"]
|
|
2150
|
+
}
|
|
2151
|
+
},
|
|
2152
|
+
required: ["data"]
|
|
2153
|
+
},
|
|
2154
|
+
outputSchema: {
|
|
2155
|
+
type: "object",
|
|
2156
|
+
properties: {
|
|
2157
|
+
uuid: {
|
|
2158
|
+
type: "string"
|
|
2159
|
+
}
|
|
2160
|
+
},
|
|
2161
|
+
required: ["uuid"]
|
|
2162
|
+
},
|
|
2163
|
+
retryCount: 5,
|
|
2164
|
+
retryDelay: 1e3
|
|
2165
|
+
}
|
|
2166
|
+
).doOn("meta.service_registry.transport_registration_requested").emits("meta.service_registry.transport_registered").emitsOnFail("meta.service_registry.transport_registration_failed");
|
|
1779
2167
|
CadenzaService.createMetaTask(
|
|
1780
2168
|
"Handle service creation",
|
|
1781
2169
|
(ctx) => {
|
|
1782
2170
|
if (!ctx.__cadenzaDBConnect) {
|
|
1783
2171
|
ctx.__skipRemoteExecution = true;
|
|
1784
2172
|
}
|
|
1785
|
-
if (isBrowser) {
|
|
2173
|
+
if (isBrowser || ctx.__isFrontend) {
|
|
1786
2174
|
CadenzaService.createMetaTask("Prepare for signal sync", () => {
|
|
1787
2175
|
return {};
|
|
1788
2176
|
}).then(
|
|
@@ -1815,28 +2203,24 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1815
2203
|
for (const service of services) {
|
|
1816
2204
|
const instances = this.instances.get(service).filter((i) => i.isActive);
|
|
1817
2205
|
for (const instance of instances) {
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
const clientCreated = instances?.some(
|
|
1822
|
-
(i) => i.address === address && i.port === port && i.clientCreated && i.isActive
|
|
2206
|
+
const transport = this.getRouteableTransport(
|
|
2207
|
+
instance,
|
|
2208
|
+
this.useSocket ? "socket" : "rest"
|
|
1823
2209
|
);
|
|
1824
|
-
if (!
|
|
2210
|
+
if (!transport) {
|
|
2211
|
+
continue;
|
|
2212
|
+
}
|
|
2213
|
+
if (!this.hasTransportClientCreated(instance, transport.uuid)) {
|
|
1825
2214
|
emit("meta.service_registry.dependee_registered", {
|
|
1826
2215
|
serviceName: service,
|
|
1827
2216
|
serviceInstanceId: instance.uuid,
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
2217
|
+
serviceTransportId: transport.uuid,
|
|
2218
|
+
serviceOrigin: transport.origin,
|
|
2219
|
+
transportProtocols: transport.protocols,
|
|
1831
2220
|
communicationTypes: ["signal"]
|
|
1832
2221
|
});
|
|
2222
|
+
this.markTransportClientCreated(instance, transport.uuid);
|
|
1833
2223
|
}
|
|
1834
|
-
instance.clientCreated = true;
|
|
1835
|
-
instances.forEach((i) => {
|
|
1836
|
-
if (i.address === address && i.port === port) {
|
|
1837
|
-
i.clientCreated = true;
|
|
1838
|
-
}
|
|
1839
|
-
});
|
|
1840
2224
|
}
|
|
1841
2225
|
}
|
|
1842
2226
|
return {};
|
|
@@ -1975,6 +2359,33 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1975
2359
|
}
|
|
1976
2360
|
return this.getInstance(this.serviceName, this.serviceInstanceId);
|
|
1977
2361
|
}
|
|
2362
|
+
getRoutingTransportRole() {
|
|
2363
|
+
return this.isFrontend ? "public" : "internal";
|
|
2364
|
+
}
|
|
2365
|
+
getTransportById(instance, transportId) {
|
|
2366
|
+
return instance.transports.find((transport) => transport.uuid === transportId);
|
|
2367
|
+
}
|
|
2368
|
+
getRouteableTransport(instance, protocol, role = this.getRoutingTransportRole()) {
|
|
2369
|
+
return getRouteableTransport(instance, role, protocol);
|
|
2370
|
+
}
|
|
2371
|
+
getTransportClientKey(instance, protocol, role = this.getRoutingTransportRole()) {
|
|
2372
|
+
const transport = this.getRouteableTransport(instance, protocol, role);
|
|
2373
|
+
if (!transport) {
|
|
2374
|
+
return null;
|
|
2375
|
+
}
|
|
2376
|
+
return buildTransportClientKey(transport);
|
|
2377
|
+
}
|
|
2378
|
+
hasTransportClientCreated(instance, transportId) {
|
|
2379
|
+
return (instance.clientCreatedTransportIds ?? []).includes(transportId);
|
|
2380
|
+
}
|
|
2381
|
+
markTransportClientCreated(instance, transportId) {
|
|
2382
|
+
if (!instance.clientCreatedTransportIds) {
|
|
2383
|
+
instance.clientCreatedTransportIds = [];
|
|
2384
|
+
}
|
|
2385
|
+
if (!instance.clientCreatedTransportIds.includes(transportId)) {
|
|
2386
|
+
instance.clientCreatedTransportIds.push(transportId);
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
1978
2389
|
registerDependee(serviceName, serviceInstanceId, options = {}) {
|
|
1979
2390
|
if (!serviceName || !serviceInstanceId) {
|
|
1980
2391
|
return;
|
|
@@ -2052,7 +2463,13 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2052
2463
|
if (!serviceName || !serviceInstanceId) {
|
|
2053
2464
|
return null;
|
|
2054
2465
|
}
|
|
2055
|
-
const
|
|
2466
|
+
const transportId = ctx.transportId ?? ctx.serviceTransportId ?? ctx.serviceTransport?.uuid ?? void 0;
|
|
2467
|
+
const transportOrigin = ctx.transportOrigin ?? ctx.serviceOrigin ?? ctx.serviceTransport?.origin ?? void 0;
|
|
2468
|
+
const transportProtocols = Array.isArray(
|
|
2469
|
+
ctx.transportProtocols ?? ctx.serviceTransport?.protocols
|
|
2470
|
+
) ? (ctx.transportProtocols ?? ctx.serviceTransport?.protocols).map((entry) => String(entry)).filter(
|
|
2471
|
+
(entry) => entry === "rest" || entry === "socket"
|
|
2472
|
+
) : void 0;
|
|
2056
2473
|
const numberOfRunningGraphs = Math.max(
|
|
2057
2474
|
0,
|
|
2058
2475
|
Math.trunc(
|
|
@@ -2071,9 +2488,9 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2071
2488
|
return {
|
|
2072
2489
|
serviceName,
|
|
2073
2490
|
serviceInstanceId,
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2491
|
+
transportId: typeof transportId === "string" && transportId.trim().length > 0 ? transportId : void 0,
|
|
2492
|
+
transportOrigin: typeof transportOrigin === "string" && transportOrigin.trim().length > 0 ? transportOrigin : void 0,
|
|
2493
|
+
transportProtocols: transportProtocols && transportProtocols.length > 0 ? Array.from(new Set(transportProtocols)) : void 0,
|
|
2077
2494
|
isFrontend: typeof ctx.isFrontend === "boolean" ? ctx.isFrontend : typeof ctx.serviceInstance?.isFrontend === "boolean" ? ctx.serviceInstance.isFrontend : void 0,
|
|
2078
2495
|
reportedAt: ctx.reportedAt ?? (typeof ctx.__reportedAt === "string" ? ctx.__reportedAt : void 0) ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
2079
2496
|
state: ctx.state === "healthy" || ctx.state === "degraded" || ctx.state === "overloaded" || ctx.state === "unavailable" ? ctx.state : resolved.state,
|
|
@@ -2090,14 +2507,23 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2090
2507
|
if (!instance) {
|
|
2091
2508
|
return false;
|
|
2092
2509
|
}
|
|
2093
|
-
if (report.
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2510
|
+
if (report.transportId && report.transportOrigin) {
|
|
2511
|
+
const protocols = report.transportProtocols && report.transportProtocols.length > 0 ? report.transportProtocols : ["rest", "socket"];
|
|
2512
|
+
const existingTransport = this.getTransportById(instance, report.transportId);
|
|
2513
|
+
if (existingTransport) {
|
|
2514
|
+
existingTransport.origin = report.transportOrigin;
|
|
2515
|
+
existingTransport.protocols = protocols;
|
|
2516
|
+
} else {
|
|
2517
|
+
instance.transports.push({
|
|
2518
|
+
uuid: report.transportId,
|
|
2519
|
+
serviceInstanceId: report.serviceInstanceId,
|
|
2520
|
+
role: this.getRoutingTransportRole(),
|
|
2521
|
+
origin: report.transportOrigin,
|
|
2522
|
+
protocols,
|
|
2523
|
+
securityProfile: null,
|
|
2524
|
+
authStrategy: null
|
|
2525
|
+
});
|
|
2526
|
+
}
|
|
2101
2527
|
}
|
|
2102
2528
|
if (typeof report.isFrontend === "boolean") {
|
|
2103
2529
|
instance.isFrontend = report.isFrontend;
|
|
@@ -2140,9 +2566,21 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2140
2566
|
const report = {
|
|
2141
2567
|
serviceName: this.serviceName,
|
|
2142
2568
|
serviceInstanceId: this.serviceInstanceId,
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2569
|
+
transportId: this.getRouteableTransport(
|
|
2570
|
+
localInstance,
|
|
2571
|
+
this.useSocket ? "socket" : "rest",
|
|
2572
|
+
"internal"
|
|
2573
|
+
)?.uuid ?? void 0,
|
|
2574
|
+
transportOrigin: this.getRouteableTransport(
|
|
2575
|
+
localInstance,
|
|
2576
|
+
this.useSocket ? "socket" : "rest",
|
|
2577
|
+
"internal"
|
|
2578
|
+
)?.origin ?? void 0,
|
|
2579
|
+
transportProtocols: this.getRouteableTransport(
|
|
2580
|
+
localInstance,
|
|
2581
|
+
this.useSocket ? "socket" : "rest",
|
|
2582
|
+
"internal"
|
|
2583
|
+
)?.protocols ?? void 0,
|
|
2146
2584
|
isFrontend: localInstance.isFrontend,
|
|
2147
2585
|
reportedAt,
|
|
2148
2586
|
state: snapshot.state,
|
|
@@ -2357,6 +2795,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2357
2795
|
this.numberOfRunningGraphs = 0;
|
|
2358
2796
|
this.runtimeStatusHeartbeatStarted = false;
|
|
2359
2797
|
this.lastRuntimeStatusSnapshot = null;
|
|
2798
|
+
this.isFrontend = false;
|
|
2360
2799
|
}
|
|
2361
2800
|
};
|
|
2362
2801
|
|
|
@@ -2528,13 +2967,10 @@ var RestController = class _RestController {
|
|
|
2528
2967
|
CadenzaService.createMetaTask(
|
|
2529
2968
|
"Setup Express app security",
|
|
2530
2969
|
(ctx, emit) => {
|
|
2531
|
-
if (isBrowser) {
|
|
2532
|
-
emit("meta.
|
|
2970
|
+
if (isBrowser || ctx.__isFrontend) {
|
|
2971
|
+
emit("meta.service_registry.instance_registration_requested", {
|
|
2533
2972
|
data: {
|
|
2534
2973
|
uuid: ctx.__serviceInstanceId,
|
|
2535
|
-
address: `browser:${ctx.__serviceInstanceId}`,
|
|
2536
|
-
port: 0,
|
|
2537
|
-
exposed: false,
|
|
2538
2974
|
process_pid: 1,
|
|
2539
2975
|
service_name: ctx.__serviceName,
|
|
2540
2976
|
is_frontend: true,
|
|
@@ -2543,6 +2979,7 @@ var RestController = class _RestController {
|
|
|
2543
2979
|
is_blocked: false,
|
|
2544
2980
|
health: {}
|
|
2545
2981
|
},
|
|
2982
|
+
transportData: [],
|
|
2546
2983
|
...ctx
|
|
2547
2984
|
});
|
|
2548
2985
|
return;
|
|
@@ -2615,7 +3052,7 @@ var RestController = class _RestController {
|
|
|
2615
3052
|
return { ...ctx, __app: app };
|
|
2616
3053
|
},
|
|
2617
3054
|
"Sets up the Express server according to the security profile"
|
|
2618
|
-
).attachSignal("meta.
|
|
3055
|
+
).attachSignal("meta.service_registry.instance_registration_requested").then(
|
|
2619
3056
|
CadenzaService.createMetaTask(
|
|
2620
3057
|
"Define RestServer",
|
|
2621
3058
|
(ctx) => {
|
|
@@ -2735,28 +3172,32 @@ var RestController = class _RestController {
|
|
|
2735
3172
|
CadenzaService.createMetaTask(
|
|
2736
3173
|
"Configure network",
|
|
2737
3174
|
async (ctx) => {
|
|
2738
|
-
let
|
|
2739
|
-
let
|
|
2740
|
-
|
|
3175
|
+
let httpOrigin = null;
|
|
3176
|
+
let httpsOrigin = null;
|
|
3177
|
+
const resolveBoundAddress = (server) => {
|
|
3178
|
+
if (typeof server?.address() === "string") {
|
|
3179
|
+
return server.address();
|
|
3180
|
+
}
|
|
3181
|
+
if (server?.address()?.address === "::") {
|
|
3182
|
+
if (process.env.NODE_ENV === "development") {
|
|
3183
|
+
return "localhost";
|
|
3184
|
+
}
|
|
3185
|
+
if (process.env.IS_DOCKER === "true") {
|
|
3186
|
+
return process.env.CADENZA_SERVER_URL || "localhost";
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
return server?.address()?.address || "localhost";
|
|
3190
|
+
};
|
|
2741
3191
|
const createHttpServer = async (ctx2) => {
|
|
2742
3192
|
await new Promise((resolve) => {
|
|
2743
3193
|
const server = import_node_http.default.createServer(ctx2.__app);
|
|
2744
3194
|
ctx2.httpServer = server;
|
|
2745
3195
|
server.listen(ctx2.__port, () => {
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
} else if (process.env.IS_DOCKER === "true") {
|
|
2752
|
-
address = process.env.CADENZA_SERVER_URL || "localhost";
|
|
2753
|
-
}
|
|
2754
|
-
} else {
|
|
2755
|
-
address = server?.address()?.address || "undefined";
|
|
2756
|
-
}
|
|
2757
|
-
console.log(
|
|
2758
|
-
`Server is running on ${address}:${port}`
|
|
2759
|
-
);
|
|
3196
|
+
const addressInfo = server.address();
|
|
3197
|
+
const address = resolveBoundAddress(server);
|
|
3198
|
+
const port = typeof addressInfo === "object" && addressInfo ? addressInfo.port || ctx2.__port : ctx2.__port;
|
|
3199
|
+
httpOrigin = `http://${address}:${port}`;
|
|
3200
|
+
console.log(`Server is running on ${httpOrigin}`);
|
|
2760
3201
|
resolve(address);
|
|
2761
3202
|
});
|
|
2762
3203
|
CadenzaService.createMetaTask(
|
|
@@ -2782,22 +3223,12 @@ var RestController = class _RestController {
|
|
|
2782
3223
|
ctx2.__app
|
|
2783
3224
|
);
|
|
2784
3225
|
ctx2.httpsServer = httpsServer;
|
|
2785
|
-
ctx2.__port = 443;
|
|
2786
|
-
port = 443;
|
|
2787
3226
|
httpsServer.listen(443, () => {
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
}
|
|
2794
|
-
} else {
|
|
2795
|
-
address = httpsServer?.address()?.address || "";
|
|
2796
|
-
}
|
|
2797
|
-
exposed = true;
|
|
2798
|
-
console.log(
|
|
2799
|
-
`HTTPS Server is running on ${address}:443`
|
|
2800
|
-
);
|
|
3227
|
+
const addressInfo = httpsServer.address();
|
|
3228
|
+
const address = resolveBoundAddress(httpsServer);
|
|
3229
|
+
const port = typeof addressInfo === "object" && addressInfo ? addressInfo.port || 443 : 443;
|
|
3230
|
+
httpsOrigin = `https://${address}:${port}`;
|
|
3231
|
+
console.log(`HTTPS Server is running on ${httpsOrigin}`);
|
|
2801
3232
|
resolve(address);
|
|
2802
3233
|
});
|
|
2803
3234
|
CadenzaService.createMetaTask(
|
|
@@ -2817,11 +3248,34 @@ var RestController = class _RestController {
|
|
|
2817
3248
|
} else if (ctx.__networkMode === "auto") {
|
|
2818
3249
|
await createHttpServer(ctx);
|
|
2819
3250
|
}
|
|
3251
|
+
const declaredTransports = Array.isArray(ctx.__declaredTransports) ? ctx.__declaredTransports : [];
|
|
3252
|
+
const hasExplicitInternalTransport = declaredTransports.some(
|
|
3253
|
+
(transport) => transport.role === "internal"
|
|
3254
|
+
);
|
|
3255
|
+
const transportData = declaredTransports.map((transport) => ({
|
|
3256
|
+
uuid: transport.uuid,
|
|
3257
|
+
service_instance_id: ctx.__serviceInstanceId,
|
|
3258
|
+
role: transport.role,
|
|
3259
|
+
origin: transport.origin,
|
|
3260
|
+
protocols: transport.protocols ?? ["rest", "socket"],
|
|
3261
|
+
...transport.securityProfile ? { security_profile: transport.securityProfile } : {},
|
|
3262
|
+
...transport.authStrategy ? { auth_strategy: transport.authStrategy } : {}
|
|
3263
|
+
}));
|
|
3264
|
+
if (!hasExplicitInternalTransport) {
|
|
3265
|
+
const internalOrigin = httpOrigin ?? httpsOrigin;
|
|
3266
|
+
if (internalOrigin) {
|
|
3267
|
+
transportData.unshift({
|
|
3268
|
+
uuid: `${ctx.__serviceInstanceId}-internal-auto`,
|
|
3269
|
+
service_instance_id: ctx.__serviceInstanceId,
|
|
3270
|
+
role: "internal",
|
|
3271
|
+
origin: internalOrigin,
|
|
3272
|
+
protocols: ["rest", "socket"],
|
|
3273
|
+
...ctx.__securityProfile ? { security_profile: ctx.__securityProfile } : {}
|
|
3274
|
+
});
|
|
3275
|
+
}
|
|
3276
|
+
}
|
|
2820
3277
|
ctx.data = {
|
|
2821
3278
|
uuid: ctx.__serviceInstanceId,
|
|
2822
|
-
address,
|
|
2823
|
-
port,
|
|
2824
|
-
exposed,
|
|
2825
3279
|
process_pid: process.pid,
|
|
2826
3280
|
service_name: ctx.__serviceName,
|
|
2827
3281
|
is_active: true,
|
|
@@ -2830,7 +3284,12 @@ var RestController = class _RestController {
|
|
|
2830
3284
|
is_blocked: false,
|
|
2831
3285
|
health: {}
|
|
2832
3286
|
};
|
|
3287
|
+
ctx.transportData = transportData;
|
|
2833
3288
|
delete ctx.__app;
|
|
3289
|
+
CadenzaService.emit(
|
|
3290
|
+
"meta.service_registry.instance_registration_requested",
|
|
3291
|
+
ctx
|
|
3292
|
+
);
|
|
2834
3293
|
return ctx;
|
|
2835
3294
|
},
|
|
2836
3295
|
"Configures network mode"
|
|
@@ -2880,10 +3339,12 @@ var RestController = class _RestController {
|
|
|
2880
3339
|
CadenzaService.createMetaTask(
|
|
2881
3340
|
"Setup fetch client",
|
|
2882
3341
|
(ctx) => {
|
|
2883
|
-
const
|
|
2884
|
-
const
|
|
2885
|
-
const
|
|
2886
|
-
|
|
3342
|
+
const serviceName = String(ctx.serviceName ?? "");
|
|
3343
|
+
const URL2 = String(ctx.serviceOrigin ?? "");
|
|
3344
|
+
const fetchId = String(ctx.serviceTransportId ?? "");
|
|
3345
|
+
if (!serviceName || !URL2 || !fetchId) {
|
|
3346
|
+
return false;
|
|
3347
|
+
}
|
|
2887
3348
|
const fetchDiagnostics = this.ensureFetchClientDiagnostics(
|
|
2888
3349
|
fetchId,
|
|
2889
3350
|
serviceName,
|
|
@@ -3135,18 +3596,18 @@ var RestController = class _RestController {
|
|
|
3135
3596
|
serviceName,
|
|
3136
3597
|
serviceInstanceId,
|
|
3137
3598
|
communicationTypes,
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3599
|
+
serviceTransportId,
|
|
3600
|
+
serviceOrigin,
|
|
3601
|
+
transportProtocols
|
|
3141
3602
|
} = ctx;
|
|
3142
|
-
const fetchId =
|
|
3603
|
+
const fetchId = String(serviceTransportId ?? "");
|
|
3143
3604
|
emit(`meta.fetch.handshake_requested:${fetchId}`, {
|
|
3144
3605
|
serviceInstanceId,
|
|
3145
3606
|
serviceName,
|
|
3146
3607
|
communicationTypes,
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3608
|
+
serviceTransportId,
|
|
3609
|
+
serviceOrigin,
|
|
3610
|
+
transportProtocols,
|
|
3150
3611
|
handshakeData: {
|
|
3151
3612
|
instanceId: CadenzaService.serviceRegistry.serviceInstanceId,
|
|
3152
3613
|
serviceName: CadenzaService.serviceRegistry.serviceName
|
|
@@ -3329,9 +3790,8 @@ var RestController = class _RestController {
|
|
|
3329
3790
|
};
|
|
3330
3791
|
|
|
3331
3792
|
// src/network/SocketController.ts
|
|
3332
|
-
var import_socket = require("socket.io");
|
|
3333
3793
|
var import_rate_limiter_flexible2 = require("rate-limiter-flexible");
|
|
3334
|
-
var
|
|
3794
|
+
var import_socket = require("socket.io-client");
|
|
3335
3795
|
|
|
3336
3796
|
// src/network/socketClientUtils.ts
|
|
3337
3797
|
var waitForSocketConnection = async (socket, timeoutMs, createError) => {
|
|
@@ -3372,6 +3832,13 @@ var waitForSocketConnection = async (socket, timeoutMs, createError) => {
|
|
|
3372
3832
|
};
|
|
3373
3833
|
|
|
3374
3834
|
// src/network/SocketController.ts
|
|
3835
|
+
var dynamicImport = new Function(
|
|
3836
|
+
"specifier",
|
|
3837
|
+
"return import(specifier);"
|
|
3838
|
+
);
|
|
3839
|
+
async function importNodeModule(specifier) {
|
|
3840
|
+
return dynamicImport(specifier);
|
|
3841
|
+
}
|
|
3375
3842
|
var SocketController = class _SocketController {
|
|
3376
3843
|
constructor() {
|
|
3377
3844
|
this.diagnosticsErrorHistoryLimit = 100;
|
|
@@ -3396,9 +3863,9 @@ var SocketController = class _SocketController {
|
|
|
3396
3863
|
serviceInstanceId: "",
|
|
3397
3864
|
communicationTypes: [],
|
|
3398
3865
|
serviceName: "",
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3866
|
+
serviceTransportId: "",
|
|
3867
|
+
serviceOrigin: "",
|
|
3868
|
+
transportProtocols: [],
|
|
3402
3869
|
url: "",
|
|
3403
3870
|
socketId: null,
|
|
3404
3871
|
connected: false,
|
|
@@ -3571,7 +4038,7 @@ var SocketController = class _SocketController {
|
|
|
3571
4038
|
const setupSocketServerTask = CadenzaService.createMetaTask(
|
|
3572
4039
|
"Setup SocketServer",
|
|
3573
4040
|
this.socketServerActor.task(
|
|
3574
|
-
({ state, runtimeState, input, actor, setState, setRuntimeState, emit }) => {
|
|
4041
|
+
async ({ state, runtimeState, input, actor, setState, setRuntimeState, emit }) => {
|
|
3575
4042
|
const serverKey = this.resolveSocketServerKey(input) ?? actor.key ?? this.socketServerDefaultKey;
|
|
3576
4043
|
const shouldUseSocket = Boolean(input.__useSocket);
|
|
3577
4044
|
if (!shouldUseSocket) {
|
|
@@ -3590,7 +4057,9 @@ var SocketController = class _SocketController {
|
|
|
3590
4057
|
}
|
|
3591
4058
|
let runtimeHandle = runtimeState;
|
|
3592
4059
|
if (!runtimeHandle) {
|
|
3593
|
-
runtimeHandle = this.createSocketServerRuntimeHandleFromContext(
|
|
4060
|
+
runtimeHandle = await this.createSocketServerRuntimeHandleFromContext(
|
|
4061
|
+
input
|
|
4062
|
+
);
|
|
3594
4063
|
setRuntimeState(runtimeHandle);
|
|
3595
4064
|
}
|
|
3596
4065
|
const profile = String(input.__securityProfile ?? state.securityProfile ?? "medium");
|
|
@@ -3848,21 +4317,21 @@ var SocketController = class _SocketController {
|
|
|
3848
4317
|
if (input.serviceName !== void 0) {
|
|
3849
4318
|
next.serviceName = String(input.serviceName);
|
|
3850
4319
|
}
|
|
3851
|
-
if (input.
|
|
3852
|
-
next.
|
|
4320
|
+
if (input.serviceTransportId !== void 0) {
|
|
4321
|
+
next.serviceTransportId = String(input.serviceTransportId);
|
|
3853
4322
|
}
|
|
3854
4323
|
if (input.serviceInstanceId !== void 0) {
|
|
3855
4324
|
next.serviceInstanceId = String(input.serviceInstanceId);
|
|
3856
4325
|
}
|
|
3857
|
-
if (input.
|
|
3858
|
-
next.
|
|
4326
|
+
if (input.serviceOrigin !== void 0) {
|
|
4327
|
+
next.serviceOrigin = String(input.serviceOrigin);
|
|
4328
|
+
}
|
|
4329
|
+
if (input.transportProtocols !== void 0) {
|
|
4330
|
+
next.transportProtocols = Array.isArray(input.transportProtocols) ? input.transportProtocols.map((entry) => String(entry)) : [];
|
|
3859
4331
|
}
|
|
3860
4332
|
if (input.url !== void 0) {
|
|
3861
4333
|
next.url = String(input.url);
|
|
3862
4334
|
}
|
|
3863
|
-
if (input.servicePort !== void 0) {
|
|
3864
|
-
next.servicePort = Number(input.servicePort);
|
|
3865
|
-
}
|
|
3866
4335
|
if (input.fetchId !== void 0) {
|
|
3867
4336
|
next.fetchId = String(input.fetchId);
|
|
3868
4337
|
}
|
|
@@ -3906,25 +4375,24 @@ var SocketController = class _SocketController {
|
|
|
3906
4375
|
input.communicationTypes
|
|
3907
4376
|
);
|
|
3908
4377
|
const serviceName = String(input.serviceName ?? "");
|
|
3909
|
-
const
|
|
3910
|
-
const
|
|
3911
|
-
const
|
|
3912
|
-
if (!
|
|
4378
|
+
const serviceTransportId = String(input.serviceTransportId ?? "");
|
|
4379
|
+
const serviceOrigin = String(input.serviceOrigin ?? "");
|
|
4380
|
+
const parsedOrigin = parseTransportOrigin(serviceOrigin);
|
|
4381
|
+
if (!serviceTransportId || !serviceOrigin || !parsedOrigin) {
|
|
3913
4382
|
CadenzaService.log(
|
|
3914
|
-
"Socket client setup skipped due to missing
|
|
4383
|
+
"Socket client setup skipped due to missing transport origin",
|
|
3915
4384
|
{
|
|
3916
4385
|
serviceName,
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
protocol
|
|
4386
|
+
serviceTransportId,
|
|
4387
|
+
serviceOrigin
|
|
3920
4388
|
},
|
|
3921
4389
|
"warning"
|
|
3922
4390
|
);
|
|
3923
4391
|
return false;
|
|
3924
4392
|
}
|
|
3925
|
-
const socketProtocol = protocol === "https" ? "wss" : "ws";
|
|
3926
|
-
const url = `${socketProtocol}://${
|
|
3927
|
-
const fetchId =
|
|
4393
|
+
const socketProtocol = parsedOrigin.protocol === "https" ? "wss" : "ws";
|
|
4394
|
+
const url = `${socketProtocol}://${parsedOrigin.hostname}:${parsedOrigin.port}`;
|
|
4395
|
+
const fetchId = serviceTransportId;
|
|
3928
4396
|
const applySessionOperation = (operation, patch = {}) => {
|
|
3929
4397
|
CadenzaService.emit("meta.socket_client.session_operation_requested", {
|
|
3930
4398
|
fetchId,
|
|
@@ -3933,9 +4401,9 @@ var SocketController = class _SocketController {
|
|
|
3933
4401
|
serviceInstanceId,
|
|
3934
4402
|
communicationTypes,
|
|
3935
4403
|
serviceName,
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
4404
|
+
serviceTransportId,
|
|
4405
|
+
serviceOrigin,
|
|
4406
|
+
transportProtocols: input.transportProtocols,
|
|
3939
4407
|
url
|
|
3940
4408
|
});
|
|
3941
4409
|
};
|
|
@@ -3954,9 +4422,9 @@ var SocketController = class _SocketController {
|
|
|
3954
4422
|
serviceInstanceId,
|
|
3955
4423
|
communicationTypes,
|
|
3956
4424
|
serviceName,
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
4425
|
+
serviceTransportId,
|
|
4426
|
+
serviceOrigin,
|
|
4427
|
+
transportProtocols: Array.isArray(input.transportProtocols) ? input.transportProtocols.map((entry) => String(entry)) : [],
|
|
3960
4428
|
url,
|
|
3961
4429
|
destroyed: false,
|
|
3962
4430
|
updatedAt: Date.now()
|
|
@@ -4284,8 +4752,8 @@ var SocketController = class _SocketController {
|
|
|
4284
4752
|
);
|
|
4285
4753
|
CadenzaService.emit(`meta.socket_client.disconnected:${fetchId}`, {
|
|
4286
4754
|
serviceName,
|
|
4287
|
-
|
|
4288
|
-
|
|
4755
|
+
serviceTransportId,
|
|
4756
|
+
serviceOrigin
|
|
4289
4757
|
});
|
|
4290
4758
|
runtimeHandle.handshake = false;
|
|
4291
4759
|
});
|
|
@@ -4306,7 +4774,7 @@ var SocketController = class _SocketController {
|
|
|
4306
4774
|
{
|
|
4307
4775
|
serviceInstanceId: CadenzaService.serviceRegistry.serviceInstanceId,
|
|
4308
4776
|
serviceName: CadenzaService.serviceRegistry.serviceName,
|
|
4309
|
-
isFrontend: isBrowser,
|
|
4777
|
+
isFrontend: CadenzaService.serviceRegistry.isFrontend || isBrowser,
|
|
4310
4778
|
__status: "success"
|
|
4311
4779
|
},
|
|
4312
4780
|
1e4,
|
|
@@ -4484,9 +4952,9 @@ var SocketController = class _SocketController {
|
|
|
4484
4952
|
serviceInstanceId,
|
|
4485
4953
|
serviceName,
|
|
4486
4954
|
communicationTypes,
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4955
|
+
serviceTransportId,
|
|
4956
|
+
serviceOrigin,
|
|
4957
|
+
transportProtocols: input.transportProtocols,
|
|
4490
4958
|
handshakeData: {
|
|
4491
4959
|
instanceId: CadenzaService.serviceRegistry.serviceInstanceId,
|
|
4492
4960
|
serviceName: CadenzaService.serviceRegistry.serviceName
|
|
@@ -4525,32 +4993,21 @@ var SocketController = class _SocketController {
|
|
|
4525
4993
|
if (explicitFetchId) {
|
|
4526
4994
|
return explicitFetchId;
|
|
4527
4995
|
}
|
|
4528
|
-
const
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
return void 0;
|
|
4533
|
-
}
|
|
4534
|
-
return `${serviceAddress}_${port}`;
|
|
4535
|
-
}
|
|
4536
|
-
resolveServicePort(protocol, rawPort) {
|
|
4537
|
-
if (protocol === "https") {
|
|
4538
|
-
return 443;
|
|
4539
|
-
}
|
|
4540
|
-
const parsed = Number(rawPort);
|
|
4541
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
4542
|
-
return void 0;
|
|
4543
|
-
}
|
|
4544
|
-
return Math.trunc(parsed);
|
|
4996
|
+
const transportId = String(
|
|
4997
|
+
input.serviceTransportId ?? input.transportId ?? ""
|
|
4998
|
+
).trim();
|
|
4999
|
+
return transportId || void 0;
|
|
4545
5000
|
}
|
|
4546
|
-
createSocketServerRuntimeHandleFromContext(context) {
|
|
5001
|
+
async createSocketServerRuntimeHandleFromContext(context) {
|
|
4547
5002
|
const baseServer = context.httpsServer ?? context.httpServer;
|
|
4548
5003
|
if (!baseServer) {
|
|
4549
5004
|
throw new Error(
|
|
4550
5005
|
"Socket server runtime setup requires either httpsServer or httpServer"
|
|
4551
5006
|
);
|
|
4552
5007
|
}
|
|
4553
|
-
const
|
|
5008
|
+
const socketServerModule = await importNodeModule("socket.io");
|
|
5009
|
+
const Server = socketServerModule.Server;
|
|
5010
|
+
const server = new Server(baseServer, {
|
|
4554
5011
|
pingInterval: 3e4,
|
|
4555
5012
|
pingTimeout: 2e4,
|
|
4556
5013
|
maxHttpBufferSize: 1e7,
|
|
@@ -4583,7 +5040,7 @@ var SocketController = class _SocketController {
|
|
|
4583
5040
|
createSocketClientRuntimeHandle(url) {
|
|
4584
5041
|
return {
|
|
4585
5042
|
url,
|
|
4586
|
-
socket: (0,
|
|
5043
|
+
socket: (0, import_socket.io)(url, {
|
|
4587
5044
|
reconnection: true,
|
|
4588
5045
|
reconnectionAttempts: 5,
|
|
4589
5046
|
reconnectionDelay: 2e3,
|
|
@@ -4840,16 +5297,140 @@ var SignalController = class _SignalController {
|
|
|
4840
5297
|
service_name: CadenzaService.serviceRegistry.serviceName,
|
|
4841
5298
|
service_instance_id: CadenzaService.serviceRegistry.serviceInstanceId
|
|
4842
5299
|
}
|
|
4843
|
-
};
|
|
4844
|
-
},
|
|
4845
|
-
"",
|
|
4846
|
-
{ isSubMeta: true, concurrency: 100 }
|
|
4847
|
-
).doOn("sub_meta.signal_broker.emitting_signal").emits("global.sub_meta.signal_controller.signal_emitted");
|
|
4848
|
-
}
|
|
4849
|
-
};
|
|
5300
|
+
};
|
|
5301
|
+
},
|
|
5302
|
+
"",
|
|
5303
|
+
{ isSubMeta: true, concurrency: 100 }
|
|
5304
|
+
).doOn("sub_meta.signal_broker.emitting_signal").emits("global.sub_meta.signal_controller.signal_emitted");
|
|
5305
|
+
}
|
|
5306
|
+
};
|
|
5307
|
+
|
|
5308
|
+
// src/graph/controllers/registerActorSessionPersistence.ts
|
|
5309
|
+
var import_core3 = require("@cadenza.io/core");
|
|
5310
|
+
function registerActorSessionPersistenceTasks() {
|
|
5311
|
+
if (CadenzaService.get("Persist actor session state")) {
|
|
5312
|
+
return;
|
|
5313
|
+
}
|
|
5314
|
+
const actorSessionStateInsertTask = CadenzaService.get("dbInsertActorSessionState") ?? CadenzaService.get("Insert actor_session_state in CadenzaDB") ?? CadenzaService.createCadenzaDBInsertTask(
|
|
5315
|
+
"actor_session_state",
|
|
5316
|
+
{},
|
|
5317
|
+
{ concurrency: 100, isSubMeta: true }
|
|
5318
|
+
);
|
|
5319
|
+
const validateActorSessionStatePersistenceTask = CadenzaService.createMetaTask(
|
|
5320
|
+
"Validate actor session state persistence",
|
|
5321
|
+
(ctx) => {
|
|
5322
|
+
if (ctx.errored || ctx.failed || ctx.__success !== true) {
|
|
5323
|
+
throw new Error(
|
|
5324
|
+
String(
|
|
5325
|
+
ctx.__error ?? ctx.error ?? "actor_session_state persistence query failed"
|
|
5326
|
+
)
|
|
5327
|
+
);
|
|
5328
|
+
}
|
|
5329
|
+
const rowCount = Number(ctx.rowCount ?? 0);
|
|
5330
|
+
if (!Number.isFinite(rowCount) || rowCount <= 0) {
|
|
5331
|
+
throw new Error(
|
|
5332
|
+
"actor_session_state persistence did not affect any rows (possible stale durable_version)"
|
|
5333
|
+
);
|
|
5334
|
+
}
|
|
5335
|
+
return {
|
|
5336
|
+
__success: true,
|
|
5337
|
+
persisted: true,
|
|
5338
|
+
actor_name: ctx.actor_name,
|
|
5339
|
+
actor_version: ctx.actor_version,
|
|
5340
|
+
actor_key: ctx.actor_key,
|
|
5341
|
+
service_name: ctx.service_name,
|
|
5342
|
+
durable_version: ctx.durable_version
|
|
5343
|
+
};
|
|
5344
|
+
},
|
|
5345
|
+
"Enforces strict actor session persistence success contract.",
|
|
5346
|
+
{ isSubMeta: true, concurrency: 100 }
|
|
5347
|
+
);
|
|
5348
|
+
const insertAndValidateActorSessionStateTask = actorSessionStateInsertTask.then(
|
|
5349
|
+
validateActorSessionStatePersistenceTask
|
|
5350
|
+
);
|
|
5351
|
+
CadenzaService.createMetaTask(
|
|
5352
|
+
"Persist actor session state",
|
|
5353
|
+
(ctx) => {
|
|
5354
|
+
const actorName = typeof ctx.actor_name === "string" ? ctx.actor_name.trim() : "";
|
|
5355
|
+
const actorKey = typeof ctx.actor_key === "string" ? ctx.actor_key.trim() : "";
|
|
5356
|
+
const actorVersion = Number(ctx.actor_version ?? 1);
|
|
5357
|
+
const durableVersion = Number(ctx.durable_version);
|
|
5358
|
+
if (!actorName) {
|
|
5359
|
+
throw new Error("actor_name is required for actor session persistence");
|
|
5360
|
+
}
|
|
5361
|
+
if (!actorKey) {
|
|
5362
|
+
throw new Error("actor_key is required for actor session persistence");
|
|
5363
|
+
}
|
|
5364
|
+
if (!Number.isInteger(actorVersion) || actorVersion < 1) {
|
|
5365
|
+
throw new Error("actor_version must be a positive integer");
|
|
5366
|
+
}
|
|
5367
|
+
if (!Number.isInteger(durableVersion) || durableVersion < 0) {
|
|
5368
|
+
throw new Error("durable_version must be a non-negative integer");
|
|
5369
|
+
}
|
|
5370
|
+
if (typeof ctx.durable_state !== "object" || ctx.durable_state === null || Array.isArray(ctx.durable_state)) {
|
|
5371
|
+
throw new Error("durable_state must be a non-null object");
|
|
5372
|
+
}
|
|
5373
|
+
const serviceName = CadenzaService.serviceRegistry.serviceName;
|
|
5374
|
+
if (!serviceName) {
|
|
5375
|
+
throw new Error("service_name is not available for actor session persistence");
|
|
5376
|
+
}
|
|
5377
|
+
let expiresAt = null;
|
|
5378
|
+
if (ctx.expires_at !== void 0 && ctx.expires_at !== null) {
|
|
5379
|
+
if (ctx.expires_at instanceof Date) {
|
|
5380
|
+
expiresAt = ctx.expires_at.toISOString();
|
|
5381
|
+
} else if (typeof ctx.expires_at === "string" && ctx.expires_at.trim().length > 0) {
|
|
5382
|
+
expiresAt = ctx.expires_at;
|
|
5383
|
+
} else {
|
|
5384
|
+
throw new Error("expires_at must be null, Date, or non-empty string");
|
|
5385
|
+
}
|
|
5386
|
+
}
|
|
5387
|
+
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5388
|
+
return {
|
|
5389
|
+
...ctx,
|
|
5390
|
+
actor_name: actorName,
|
|
5391
|
+
actor_key: actorKey,
|
|
5392
|
+
actor_version: actorVersion,
|
|
5393
|
+
durable_version: durableVersion,
|
|
5394
|
+
expires_at: expiresAt,
|
|
5395
|
+
service_name: serviceName,
|
|
5396
|
+
queryData: {
|
|
5397
|
+
data: {
|
|
5398
|
+
actor_name: actorName,
|
|
5399
|
+
actor_version: actorVersion,
|
|
5400
|
+
actor_key: actorKey,
|
|
5401
|
+
service_name: serviceName,
|
|
5402
|
+
durable_state: ctx.durable_state,
|
|
5403
|
+
durable_version: durableVersion,
|
|
5404
|
+
expires_at: expiresAt,
|
|
5405
|
+
updated: updatedAt
|
|
5406
|
+
},
|
|
5407
|
+
onConflict: {
|
|
5408
|
+
target: [
|
|
5409
|
+
"actor_name",
|
|
5410
|
+
"actor_version",
|
|
5411
|
+
"actor_key",
|
|
5412
|
+
"service_name"
|
|
5413
|
+
],
|
|
5414
|
+
action: {
|
|
5415
|
+
do: "update",
|
|
5416
|
+
set: {
|
|
5417
|
+
durable_state: "excluded",
|
|
5418
|
+
durable_version: "excluded",
|
|
5419
|
+
expires_at: "excluded",
|
|
5420
|
+
updated: "excluded"
|
|
5421
|
+
},
|
|
5422
|
+
where: "actor_session_state.durable_version <= excluded.durable_version"
|
|
5423
|
+
}
|
|
5424
|
+
}
|
|
5425
|
+
}
|
|
5426
|
+
};
|
|
5427
|
+
},
|
|
5428
|
+
"Validates and prepares actor_session_state payload for strict write-through persistence.",
|
|
5429
|
+
{ isSubMeta: true, concurrency: 100 }
|
|
5430
|
+
).then(insertAndValidateActorSessionStateTask).respondsTo(import_core3.META_ACTOR_SESSION_STATE_PERSIST_INTENT);
|
|
5431
|
+
}
|
|
4850
5432
|
|
|
4851
5433
|
// src/graph/controllers/GraphMetadataController.ts
|
|
4852
|
-
var import_core3 = require("@cadenza.io/core");
|
|
4853
5434
|
var GraphMetadataController = class _GraphMetadataController {
|
|
4854
5435
|
static get instance() {
|
|
4855
5436
|
if (!this._instance) this._instance = new _GraphMetadataController();
|
|
@@ -5083,123 +5664,7 @@ var GraphMetadataController = class _GraphMetadataController {
|
|
|
5083
5664
|
}
|
|
5084
5665
|
};
|
|
5085
5666
|
}).doOn("meta.actor.task_associated").emits("global.meta.graph_metadata.actor_task_associated");
|
|
5086
|
-
|
|
5087
|
-
"actor_session_state",
|
|
5088
|
-
{},
|
|
5089
|
-
{ concurrency: 100, isSubMeta: true }
|
|
5090
|
-
);
|
|
5091
|
-
const validateActorSessionStatePersistenceTask = CadenzaService.createMetaTask(
|
|
5092
|
-
"Validate actor session state persistence",
|
|
5093
|
-
(ctx) => {
|
|
5094
|
-
if (ctx.errored || ctx.failed || ctx.__success !== true) {
|
|
5095
|
-
throw new Error(
|
|
5096
|
-
String(
|
|
5097
|
-
ctx.__error ?? ctx.error ?? "actor_session_state persistence query failed"
|
|
5098
|
-
)
|
|
5099
|
-
);
|
|
5100
|
-
}
|
|
5101
|
-
const rowCount = Number(ctx.rowCount ?? 0);
|
|
5102
|
-
if (!Number.isFinite(rowCount) || rowCount <= 0) {
|
|
5103
|
-
throw new Error(
|
|
5104
|
-
"actor_session_state persistence did not affect any rows (possible stale durable_version)"
|
|
5105
|
-
);
|
|
5106
|
-
}
|
|
5107
|
-
return {
|
|
5108
|
-
__success: true,
|
|
5109
|
-
persisted: true,
|
|
5110
|
-
actor_name: ctx.actor_name,
|
|
5111
|
-
actor_version: ctx.actor_version,
|
|
5112
|
-
actor_key: ctx.actor_key,
|
|
5113
|
-
service_name: ctx.service_name,
|
|
5114
|
-
durable_version: ctx.durable_version
|
|
5115
|
-
};
|
|
5116
|
-
},
|
|
5117
|
-
"Enforces strict actor session persistence success contract.",
|
|
5118
|
-
{ isSubMeta: true, concurrency: 100 }
|
|
5119
|
-
);
|
|
5120
|
-
const insertAndValidateActorSessionStateTask = actorSessionStateInsertTask.then(
|
|
5121
|
-
validateActorSessionStatePersistenceTask
|
|
5122
|
-
);
|
|
5123
|
-
CadenzaService.createMetaTask(
|
|
5124
|
-
"Persist actor session state",
|
|
5125
|
-
(ctx) => {
|
|
5126
|
-
const actorName = typeof ctx.actor_name === "string" ? ctx.actor_name.trim() : "";
|
|
5127
|
-
const actorKey = typeof ctx.actor_key === "string" ? ctx.actor_key.trim() : "";
|
|
5128
|
-
const actorVersion = Number(ctx.actor_version ?? 1);
|
|
5129
|
-
const durableVersion = Number(ctx.durable_version);
|
|
5130
|
-
if (!actorName) {
|
|
5131
|
-
throw new Error("actor_name is required for actor session persistence");
|
|
5132
|
-
}
|
|
5133
|
-
if (!actorKey) {
|
|
5134
|
-
throw new Error("actor_key is required for actor session persistence");
|
|
5135
|
-
}
|
|
5136
|
-
if (!Number.isInteger(actorVersion) || actorVersion < 1) {
|
|
5137
|
-
throw new Error("actor_version must be a positive integer");
|
|
5138
|
-
}
|
|
5139
|
-
if (!Number.isInteger(durableVersion) || durableVersion < 0) {
|
|
5140
|
-
throw new Error("durable_version must be a non-negative integer");
|
|
5141
|
-
}
|
|
5142
|
-
if (typeof ctx.durable_state !== "object" || ctx.durable_state === null || Array.isArray(ctx.durable_state)) {
|
|
5143
|
-
throw new Error("durable_state must be a non-null object");
|
|
5144
|
-
}
|
|
5145
|
-
const serviceName = CadenzaService.serviceRegistry.serviceName;
|
|
5146
|
-
if (!serviceName) {
|
|
5147
|
-
throw new Error("service_name is not available for actor session persistence");
|
|
5148
|
-
}
|
|
5149
|
-
let expiresAt = null;
|
|
5150
|
-
if (ctx.expires_at !== void 0 && ctx.expires_at !== null) {
|
|
5151
|
-
if (ctx.expires_at instanceof Date) {
|
|
5152
|
-
expiresAt = ctx.expires_at.toISOString();
|
|
5153
|
-
} else if (typeof ctx.expires_at === "string" && ctx.expires_at.trim().length > 0) {
|
|
5154
|
-
expiresAt = ctx.expires_at;
|
|
5155
|
-
} else {
|
|
5156
|
-
throw new Error("expires_at must be null, Date, or non-empty string");
|
|
5157
|
-
}
|
|
5158
|
-
}
|
|
5159
|
-
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5160
|
-
return {
|
|
5161
|
-
...ctx,
|
|
5162
|
-
actor_name: actorName,
|
|
5163
|
-
actor_key: actorKey,
|
|
5164
|
-
actor_version: actorVersion,
|
|
5165
|
-
durable_version: durableVersion,
|
|
5166
|
-
expires_at: expiresAt,
|
|
5167
|
-
service_name: serviceName,
|
|
5168
|
-
queryData: {
|
|
5169
|
-
data: {
|
|
5170
|
-
actor_name: actorName,
|
|
5171
|
-
actor_version: actorVersion,
|
|
5172
|
-
actor_key: actorKey,
|
|
5173
|
-
service_name: serviceName,
|
|
5174
|
-
durable_state: ctx.durable_state,
|
|
5175
|
-
durable_version: durableVersion,
|
|
5176
|
-
expires_at: expiresAt,
|
|
5177
|
-
updated: updatedAt
|
|
5178
|
-
},
|
|
5179
|
-
onConflict: {
|
|
5180
|
-
target: [
|
|
5181
|
-
"actor_name",
|
|
5182
|
-
"actor_version",
|
|
5183
|
-
"actor_key",
|
|
5184
|
-
"service_name"
|
|
5185
|
-
],
|
|
5186
|
-
action: {
|
|
5187
|
-
do: "update",
|
|
5188
|
-
set: {
|
|
5189
|
-
durable_state: "excluded",
|
|
5190
|
-
durable_version: "excluded",
|
|
5191
|
-
expires_at: "excluded",
|
|
5192
|
-
updated: "excluded"
|
|
5193
|
-
},
|
|
5194
|
-
where: "actor_session_state.durable_version <= excluded.durable_version"
|
|
5195
|
-
}
|
|
5196
|
-
}
|
|
5197
|
-
}
|
|
5198
|
-
};
|
|
5199
|
-
},
|
|
5200
|
-
"Validates and prepares actor_session_state payload for strict write-through persistence.",
|
|
5201
|
-
{ isSubMeta: true, concurrency: 100 }
|
|
5202
|
-
).then(insertAndValidateActorSessionStateTask).respondsTo(import_core3.META_ACTOR_SESSION_STATE_PERSIST_INTENT);
|
|
5667
|
+
registerActorSessionPersistenceTasks();
|
|
5203
5668
|
CadenzaService.createMetaTask("Handle Intent Creation", (ctx) => {
|
|
5204
5669
|
const intentName = ctx.data?.name;
|
|
5205
5670
|
return {
|
|
@@ -7835,6 +8300,165 @@ var GraphSyncController = class _GraphSyncController {
|
|
|
7835
8300
|
}
|
|
7836
8301
|
};
|
|
7837
8302
|
|
|
8303
|
+
// src/utils/bootstrap.ts
|
|
8304
|
+
var DEFAULT_BOOTSTRAP_GLOBAL_KEY = "__CADENZA_RUNTIME__";
|
|
8305
|
+
function normalizeString3(value) {
|
|
8306
|
+
if (typeof value !== "string") {
|
|
8307
|
+
return void 0;
|
|
8308
|
+
}
|
|
8309
|
+
const normalized = value.trim();
|
|
8310
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
8311
|
+
}
|
|
8312
|
+
function readEnvString(name) {
|
|
8313
|
+
if (typeof process === "undefined") {
|
|
8314
|
+
return void 0;
|
|
8315
|
+
}
|
|
8316
|
+
return normalizeString3(process.env?.[name]);
|
|
8317
|
+
}
|
|
8318
|
+
function readConfiguredPort(value) {
|
|
8319
|
+
if (value === void 0 || value === null || value === "") {
|
|
8320
|
+
return void 0;
|
|
8321
|
+
}
|
|
8322
|
+
const parsed = Number(value);
|
|
8323
|
+
if (!Number.isFinite(parsed)) {
|
|
8324
|
+
throw new Error(`Invalid port value: ${String(value)}`);
|
|
8325
|
+
}
|
|
8326
|
+
const normalized = Math.trunc(parsed);
|
|
8327
|
+
if (normalized <= 0) {
|
|
8328
|
+
throw new Error(`Port must be a positive integer: ${String(value)}`);
|
|
8329
|
+
}
|
|
8330
|
+
return normalized;
|
|
8331
|
+
}
|
|
8332
|
+
function buildBootstrapUrl(protocol, address, port) {
|
|
8333
|
+
return `${protocol}://${address}:${port}`;
|
|
8334
|
+
}
|
|
8335
|
+
function resolveInjectedBootstrapUrl(injectedGlobalKey) {
|
|
8336
|
+
if (typeof globalThis === "undefined") {
|
|
8337
|
+
return void 0;
|
|
8338
|
+
}
|
|
8339
|
+
const runtimeConfig = globalThis[injectedGlobalKey];
|
|
8340
|
+
return normalizeString3(runtimeConfig?.bootstrapUrl);
|
|
8341
|
+
}
|
|
8342
|
+
function resolveExplicitBootstrapValue(options) {
|
|
8343
|
+
const injectedGlobalKey = normalizeString3(options.bootstrap?.injectedGlobalKey) ?? DEFAULT_BOOTSTRAP_GLOBAL_KEY;
|
|
8344
|
+
const explicitBootstrapUrl = normalizeString3(options.bootstrap?.url);
|
|
8345
|
+
if (explicitBootstrapUrl) {
|
|
8346
|
+
return {
|
|
8347
|
+
value: explicitBootstrapUrl,
|
|
8348
|
+
port: readConfiguredPort(options.cadenzaDB?.port),
|
|
8349
|
+
injectedGlobalKey
|
|
8350
|
+
};
|
|
8351
|
+
}
|
|
8352
|
+
if (options.runtime === "browser") {
|
|
8353
|
+
const injected = resolveInjectedBootstrapUrl(injectedGlobalKey);
|
|
8354
|
+
if (injected) {
|
|
8355
|
+
return {
|
|
8356
|
+
value: injected,
|
|
8357
|
+
port: readConfiguredPort(options.cadenzaDB?.port),
|
|
8358
|
+
injectedGlobalKey
|
|
8359
|
+
};
|
|
8360
|
+
}
|
|
8361
|
+
}
|
|
8362
|
+
const explicitAddress = normalizeString3(options.cadenzaDB?.address);
|
|
8363
|
+
if (explicitAddress) {
|
|
8364
|
+
return {
|
|
8365
|
+
value: explicitAddress,
|
|
8366
|
+
port: readConfiguredPort(options.cadenzaDB?.port),
|
|
8367
|
+
injectedGlobalKey
|
|
8368
|
+
};
|
|
8369
|
+
}
|
|
8370
|
+
const envAddress = readEnvString("CADENZA_DB_ADDRESS");
|
|
8371
|
+
return {
|
|
8372
|
+
value: envAddress,
|
|
8373
|
+
port: readConfiguredPort(options.cadenzaDB?.port ?? readEnvString("CADENZA_DB_PORT")),
|
|
8374
|
+
injectedGlobalKey
|
|
8375
|
+
};
|
|
8376
|
+
}
|
|
8377
|
+
function readIntegerEnv(name, fallback) {
|
|
8378
|
+
const raw = readEnvString(name);
|
|
8379
|
+
if (!raw) {
|
|
8380
|
+
return fallback;
|
|
8381
|
+
}
|
|
8382
|
+
const parsed = Number(raw);
|
|
8383
|
+
if (!Number.isFinite(parsed)) {
|
|
8384
|
+
return fallback;
|
|
8385
|
+
}
|
|
8386
|
+
const normalized = Math.trunc(parsed);
|
|
8387
|
+
if (normalized <= 0) {
|
|
8388
|
+
return fallback;
|
|
8389
|
+
}
|
|
8390
|
+
return normalized;
|
|
8391
|
+
}
|
|
8392
|
+
function readStringEnv(name) {
|
|
8393
|
+
return readEnvString(name);
|
|
8394
|
+
}
|
|
8395
|
+
function readListEnv(name) {
|
|
8396
|
+
const raw = readEnvString(name);
|
|
8397
|
+
if (!raw) {
|
|
8398
|
+
return [];
|
|
8399
|
+
}
|
|
8400
|
+
return raw.split("|").map((entry) => entry.trim()).filter((entry) => entry.length > 0).map((entry) => entry.split(",").map((part) => part.trim()));
|
|
8401
|
+
}
|
|
8402
|
+
function resolveBootstrapEndpoint(options) {
|
|
8403
|
+
const { value, port: fallbackPort, injectedGlobalKey } = resolveExplicitBootstrapValue(options);
|
|
8404
|
+
if (!value) {
|
|
8405
|
+
throw new Error(
|
|
8406
|
+
options.runtime === "browser" ? `No bootstrap URL available. Pass bootstrap.url or inject globalThis.${injectedGlobalKey}.bootstrapUrl.` : "No bootstrap URL available. Set CADENZA_DB_ADDRESS or pass bootstrap.url."
|
|
8407
|
+
);
|
|
8408
|
+
}
|
|
8409
|
+
const raw = value.trim();
|
|
8410
|
+
if (raw.length === 0) {
|
|
8411
|
+
throw new Error("Bootstrap URL cannot be empty");
|
|
8412
|
+
}
|
|
8413
|
+
if (raw.includes("://")) {
|
|
8414
|
+
const parsed2 = new URL(raw);
|
|
8415
|
+
const protocol2 = parsed2.protocol.replace(":", "");
|
|
8416
|
+
if (protocol2 !== "http" && protocol2 !== "https") {
|
|
8417
|
+
throw new Error(`Unsupported bootstrap protocol: ${parsed2.protocol}`);
|
|
8418
|
+
}
|
|
8419
|
+
if (parsed2.pathname && parsed2.pathname !== "/" && parsed2.pathname.trim().length > 0) {
|
|
8420
|
+
throw new Error(
|
|
8421
|
+
"Bootstrap URL must be an origin without a path component."
|
|
8422
|
+
);
|
|
8423
|
+
}
|
|
8424
|
+
const port2 = parsed2.port ? readConfiguredPort(parsed2.port) : fallbackPort;
|
|
8425
|
+
if (!port2) {
|
|
8426
|
+
throw new Error(
|
|
8427
|
+
"Bootstrap URL must include a port or CADENZA_DB_PORT must be provided."
|
|
8428
|
+
);
|
|
8429
|
+
}
|
|
8430
|
+
return {
|
|
8431
|
+
url: buildBootstrapUrl(protocol2, parsed2.hostname, port2),
|
|
8432
|
+
protocol: protocol2,
|
|
8433
|
+
address: parsed2.hostname,
|
|
8434
|
+
port: port2,
|
|
8435
|
+
exposed: protocol2 === "https",
|
|
8436
|
+
injectedGlobalKey
|
|
8437
|
+
};
|
|
8438
|
+
}
|
|
8439
|
+
if (raw.includes("/") || raw.includes("?") || raw.includes("#")) {
|
|
8440
|
+
throw new Error(
|
|
8441
|
+
"Bootstrap address without protocol must not include a path, query, or hash."
|
|
8442
|
+
);
|
|
8443
|
+
}
|
|
8444
|
+
const parsed = new URL(`http://${raw}`);
|
|
8445
|
+
const protocol = "http";
|
|
8446
|
+
const port = parsed.port ? readConfiguredPort(parsed.port) : fallbackPort;
|
|
8447
|
+
if (!port) {
|
|
8448
|
+
throw new Error(
|
|
8449
|
+
"Bootstrap address must include a port or CADENZA_DB_PORT must be provided."
|
|
8450
|
+
);
|
|
8451
|
+
}
|
|
8452
|
+
return {
|
|
8453
|
+
url: buildBootstrapUrl(protocol, parsed.hostname, port),
|
|
8454
|
+
protocol,
|
|
8455
|
+
address: parsed.hostname,
|
|
8456
|
+
port,
|
|
8457
|
+
exposed: false,
|
|
8458
|
+
injectedGlobalKey
|
|
8459
|
+
};
|
|
8460
|
+
}
|
|
8461
|
+
|
|
7838
8462
|
// src/Cadenza.ts
|
|
7839
8463
|
var CadenzaService = class {
|
|
7840
8464
|
/**
|
|
@@ -7853,11 +8477,60 @@ var CadenzaService = class {
|
|
|
7853
8477
|
this.metaRunner = import_core4.default.metaRunner;
|
|
7854
8478
|
this.registry = import_core4.default.registry;
|
|
7855
8479
|
this.serviceRegistry = ServiceRegistry.instance;
|
|
7856
|
-
SignalController.instance;
|
|
7857
8480
|
RestController.instance;
|
|
7858
8481
|
SocketController.instance;
|
|
7859
8482
|
console.log("BOOTSTRAPPED");
|
|
7860
8483
|
}
|
|
8484
|
+
static ensureTransportControllers(isFrontend) {
|
|
8485
|
+
if (!isFrontend) {
|
|
8486
|
+
SignalController.instance;
|
|
8487
|
+
}
|
|
8488
|
+
}
|
|
8489
|
+
static setHydrationResults(hydration) {
|
|
8490
|
+
this.hydratedInquiryResults = /* @__PURE__ */ new Map();
|
|
8491
|
+
const initialInquiryResults = hydration?.initialInquiryResults ?? {};
|
|
8492
|
+
for (const [key, value] of Object.entries(initialInquiryResults)) {
|
|
8493
|
+
this.hydratedInquiryResults.set(key, value);
|
|
8494
|
+
}
|
|
8495
|
+
}
|
|
8496
|
+
static consumeHydratedInquiryResult(hydrationKey) {
|
|
8497
|
+
if (!hydrationKey) {
|
|
8498
|
+
return void 0;
|
|
8499
|
+
}
|
|
8500
|
+
const result = this.hydratedInquiryResults.get(hydrationKey);
|
|
8501
|
+
if (result === void 0) {
|
|
8502
|
+
return void 0;
|
|
8503
|
+
}
|
|
8504
|
+
this.hydratedInquiryResults.delete(hydrationKey);
|
|
8505
|
+
return result;
|
|
8506
|
+
}
|
|
8507
|
+
static ensureFrontendSyncLoop() {
|
|
8508
|
+
if (this.frontendSyncScheduled) {
|
|
8509
|
+
return;
|
|
8510
|
+
}
|
|
8511
|
+
this.frontendSyncScheduled = true;
|
|
8512
|
+
import_core4.default.interval("meta.sync_requested", { __syncing: false }, 18e4);
|
|
8513
|
+
import_core4.default.schedule("meta.sync_requested", { __syncing: false }, 250);
|
|
8514
|
+
}
|
|
8515
|
+
static normalizeDeclaredTransports(transports, serviceId) {
|
|
8516
|
+
return (transports ?? []).map((transport) => normalizeServiceTransportConfig(transport)).filter(
|
|
8517
|
+
(transport) => !!transport
|
|
8518
|
+
).map((transport, index) => ({
|
|
8519
|
+
...transport,
|
|
8520
|
+
uuid: `${serviceId}-transport-${index + 1}`
|
|
8521
|
+
}));
|
|
8522
|
+
}
|
|
8523
|
+
static createBootstrapTransport(serviceInstanceId, role, endpoint) {
|
|
8524
|
+
return {
|
|
8525
|
+
uuid: `${serviceInstanceId}-${role}-bootstrap`,
|
|
8526
|
+
service_instance_id: serviceInstanceId,
|
|
8527
|
+
role,
|
|
8528
|
+
origin: endpoint.url,
|
|
8529
|
+
protocols: ["rest", "socket"],
|
|
8530
|
+
security_profile: null,
|
|
8531
|
+
auth_strategy: null
|
|
8532
|
+
};
|
|
8533
|
+
}
|
|
7861
8534
|
/**
|
|
7862
8535
|
* Validates the provided service name based on specific rules.
|
|
7863
8536
|
*
|
|
@@ -7970,6 +8643,12 @@ var CadenzaService = class {
|
|
|
7970
8643
|
}
|
|
7971
8644
|
static async inquire(inquiry, context, options = {}) {
|
|
7972
8645
|
this.bootstrap();
|
|
8646
|
+
const hydratedResult = this.consumeHydratedInquiryResult(
|
|
8647
|
+
options.hydrationKey
|
|
8648
|
+
);
|
|
8649
|
+
if (hydratedResult !== void 0) {
|
|
8650
|
+
return hydratedResult;
|
|
8651
|
+
}
|
|
7973
8652
|
const observer = this.inquiryBroker?.inquiryObservers.get(inquiry);
|
|
7974
8653
|
const allResponders = observer ? Array.from(observer.tasks).map((task) => ({
|
|
7975
8654
|
task,
|
|
@@ -8574,58 +9253,97 @@ var CadenzaService = class {
|
|
|
8574
9253
|
const serviceId = options.customServiceId ?? (0, import_uuid3.v4)();
|
|
8575
9254
|
this.serviceRegistry.serviceName = serviceName;
|
|
8576
9255
|
this.serviceRegistry.serviceInstanceId = serviceId;
|
|
9256
|
+
this.setHydrationResults(options.hydration);
|
|
9257
|
+
const explicitFrontendMode = options.isFrontend;
|
|
8577
9258
|
options = {
|
|
8578
9259
|
loadBalance: true,
|
|
8579
9260
|
useSocket: true,
|
|
8580
9261
|
displayName: void 0,
|
|
8581
9262
|
isMeta: false,
|
|
8582
|
-
port:
|
|
8583
|
-
securityProfile:
|
|
8584
|
-
networkMode:
|
|
9263
|
+
port: readIntegerEnv("HTTP_PORT", 3e3),
|
|
9264
|
+
securityProfile: readStringEnv("SECURITY_PROFILE") ?? "medium",
|
|
9265
|
+
networkMode: readStringEnv("NETWORK_MODE") ?? "dev",
|
|
8585
9266
|
retryCount: 3,
|
|
8586
9267
|
cadenzaDB: {
|
|
8587
|
-
connect: true
|
|
8588
|
-
address: process.env.CADENZA_DB_ADDRESS ?? "localhost",
|
|
8589
|
-
port: parseInt(process.env.CADENZA_DB_PORT ?? "5000")
|
|
9268
|
+
connect: true
|
|
8590
9269
|
},
|
|
8591
|
-
relatedServices:
|
|
8592
|
-
|
|
8593
|
-
) : [],
|
|
8594
|
-
isFrontend: isBrowser,
|
|
9270
|
+
relatedServices: readListEnv("RELATED_SERVICES"),
|
|
9271
|
+
isFrontend: typeof explicitFrontendMode === "boolean" ? explicitFrontendMode : isBrowser,
|
|
8595
9272
|
...options
|
|
8596
9273
|
};
|
|
9274
|
+
const isFrontend = !!options.isFrontend;
|
|
9275
|
+
const declaredTransports = this.normalizeDeclaredTransports(
|
|
9276
|
+
options.transports,
|
|
9277
|
+
serviceId
|
|
9278
|
+
);
|
|
9279
|
+
this.serviceRegistry.isFrontend = isFrontend;
|
|
9280
|
+
this.serviceRegistry.useSocket = !!options.useSocket;
|
|
9281
|
+
this.serviceRegistry.retryCount = options.retryCount ?? 3;
|
|
9282
|
+
this.ensureTransportControllers(isFrontend);
|
|
9283
|
+
const resolvedBootstrapEndpoint = options.cadenzaDB?.connect ? resolveBootstrapEndpoint({
|
|
9284
|
+
runtime: isFrontend ? "browser" : "server",
|
|
9285
|
+
bootstrap: options.bootstrap,
|
|
9286
|
+
cadenzaDB: options.cadenzaDB
|
|
9287
|
+
}) : void 0;
|
|
9288
|
+
if (resolvedBootstrapEndpoint) {
|
|
9289
|
+
options.cadenzaDB = {
|
|
9290
|
+
...options.cadenzaDB,
|
|
9291
|
+
connect: true,
|
|
9292
|
+
address: resolvedBootstrapEndpoint.address,
|
|
9293
|
+
port: resolvedBootstrapEndpoint.port
|
|
9294
|
+
};
|
|
9295
|
+
}
|
|
8597
9296
|
if (options.cadenzaDB?.connect) {
|
|
8598
9297
|
this.emit("meta.initializing_service", {
|
|
8599
9298
|
// Seed the CadenzaDB
|
|
8600
9299
|
serviceInstance: {
|
|
8601
9300
|
uuid: "cadenza-db",
|
|
8602
9301
|
serviceName: "CadenzaDB",
|
|
8603
|
-
address: options.cadenzaDB?.address,
|
|
8604
|
-
port: options.cadenzaDB?.port,
|
|
8605
|
-
exposed: options.networkMode !== "dev",
|
|
8606
9302
|
numberOfRunningGraphs: 0,
|
|
8607
9303
|
isActive: true,
|
|
8608
9304
|
// Assume it is deployed
|
|
8609
9305
|
isNonResponsive: false,
|
|
8610
9306
|
isBlocked: false,
|
|
8611
|
-
health: {}
|
|
9307
|
+
health: {},
|
|
9308
|
+
isFrontend: false,
|
|
9309
|
+
transports: resolvedBootstrapEndpoint ? [
|
|
9310
|
+
this.createBootstrapTransport(
|
|
9311
|
+
"cadenza-db",
|
|
9312
|
+
isFrontend ? "public" : "internal",
|
|
9313
|
+
resolvedBootstrapEndpoint
|
|
9314
|
+
)
|
|
9315
|
+
] : []
|
|
8612
9316
|
}
|
|
8613
9317
|
});
|
|
8614
9318
|
}
|
|
8615
9319
|
options.relatedServices?.forEach((service) => {
|
|
9320
|
+
const relatedTransport = normalizeServiceTransportConfig({
|
|
9321
|
+
role: isFrontend ? "public" : "internal",
|
|
9322
|
+
origin: service[2].includes("://") ? service[2] : `http://${service[2]}`,
|
|
9323
|
+
protocols: ["rest", "socket"]
|
|
9324
|
+
});
|
|
8616
9325
|
this.emit("meta.initializing_service", {
|
|
8617
9326
|
serviceInstance: {
|
|
8618
9327
|
uuid: service[0],
|
|
8619
9328
|
serviceName: service[1],
|
|
8620
|
-
address: service[2].split(":")[0],
|
|
8621
|
-
port: service[2].split(":")[1] ?? 3e3,
|
|
8622
|
-
exposed: options.networkMode !== "dev",
|
|
8623
9329
|
numberOfRunningGraphs: 0,
|
|
8624
9330
|
isActive: true,
|
|
8625
9331
|
// Assume it is deployed
|
|
8626
9332
|
isNonResponsive: false,
|
|
8627
9333
|
isBlocked: false,
|
|
8628
|
-
health: {}
|
|
9334
|
+
health: {},
|
|
9335
|
+
isFrontend: false,
|
|
9336
|
+
transports: relatedTransport ? [
|
|
9337
|
+
{
|
|
9338
|
+
uuid: `${service[0]}-${relatedTransport.role}`,
|
|
9339
|
+
service_instance_id: service[0],
|
|
9340
|
+
role: relatedTransport.role,
|
|
9341
|
+
origin: relatedTransport.origin,
|
|
9342
|
+
protocols: relatedTransport.protocols ?? ["rest", "socket"],
|
|
9343
|
+
security_profile: relatedTransport.securityProfile ?? null,
|
|
9344
|
+
auth_strategy: relatedTransport.authStrategy ?? null
|
|
9345
|
+
}
|
|
9346
|
+
] : []
|
|
8629
9347
|
}
|
|
8630
9348
|
});
|
|
8631
9349
|
});
|
|
@@ -8646,7 +9364,9 @@ var CadenzaService = class {
|
|
|
8646
9364
|
__networkMode: options.networkMode,
|
|
8647
9365
|
__retryCount: options.retryCount,
|
|
8648
9366
|
__cadenzaDBConnect: options.cadenzaDB?.connect,
|
|
8649
|
-
__isDatabase: options.isDatabase
|
|
9367
|
+
__isDatabase: options.isDatabase,
|
|
9368
|
+
__isFrontend: isFrontend,
|
|
9369
|
+
__declaredTransports: declaredTransports
|
|
8650
9370
|
};
|
|
8651
9371
|
if (options.cadenzaDB?.connect) {
|
|
8652
9372
|
this.createEphemeralMetaTask("Create service", async (context, emit) => {
|
|
@@ -8662,12 +9382,42 @@ var CadenzaService = class {
|
|
|
8662
9382
|
}).doOn("meta.rest.handshake");
|
|
8663
9383
|
}
|
|
8664
9384
|
this.createMetaTask("Handle service setup completion", () => {
|
|
8665
|
-
|
|
8666
|
-
|
|
8667
|
-
|
|
9385
|
+
if (isFrontend) {
|
|
9386
|
+
registerActorSessionPersistenceTasks();
|
|
9387
|
+
this.ensureFrontendSyncLoop();
|
|
9388
|
+
} else {
|
|
9389
|
+
GraphMetadataController.instance;
|
|
9390
|
+
GraphSyncController.instance.isCadenzaDBReady = !!options.cadenzaDB?.connect;
|
|
9391
|
+
GraphSyncController.instance.init();
|
|
9392
|
+
}
|
|
8668
9393
|
this.log("Service created.");
|
|
8669
9394
|
return true;
|
|
8670
9395
|
}).doOn("meta.service_registry.instance_inserted");
|
|
9396
|
+
if (!options.cadenzaDB?.connect && isFrontend) {
|
|
9397
|
+
import_core4.default.schedule(
|
|
9398
|
+
"meta.service_registry.instance_registration_requested",
|
|
9399
|
+
{
|
|
9400
|
+
data: {
|
|
9401
|
+
uuid: serviceId,
|
|
9402
|
+
process_pid: 1,
|
|
9403
|
+
service_name: serviceName,
|
|
9404
|
+
is_frontend: true,
|
|
9405
|
+
is_active: true,
|
|
9406
|
+
is_non_responsive: false,
|
|
9407
|
+
is_blocked: false,
|
|
9408
|
+
health: {}
|
|
9409
|
+
},
|
|
9410
|
+
transportData: [],
|
|
9411
|
+
__serviceName: serviceName,
|
|
9412
|
+
__serviceInstanceId: serviceId,
|
|
9413
|
+
__useSocket: options.useSocket,
|
|
9414
|
+
__retryCount: options.retryCount,
|
|
9415
|
+
__isFrontend: true,
|
|
9416
|
+
__skipRemoteExecution: true
|
|
9417
|
+
},
|
|
9418
|
+
0
|
|
9419
|
+
);
|
|
9420
|
+
}
|
|
8671
9421
|
this.serviceCreated = true;
|
|
8672
9422
|
}
|
|
8673
9423
|
/**
|
|
@@ -8693,9 +9443,9 @@ var CadenzaService = class {
|
|
|
8693
9443
|
* @return {void}
|
|
8694
9444
|
*/
|
|
8695
9445
|
static createPostgresActor(name, schema, description = "", options = {}) {
|
|
8696
|
-
if (isBrowser) {
|
|
9446
|
+
if (isBrowser || options.isFrontend) {
|
|
8697
9447
|
console.warn(
|
|
8698
|
-
"PostgresActor creation is not supported in
|
|
9448
|
+
"PostgresActor creation is not supported in frontend mode."
|
|
8699
9449
|
);
|
|
8700
9450
|
return;
|
|
8701
9451
|
}
|
|
@@ -8740,9 +9490,9 @@ var CadenzaService = class {
|
|
|
8740
9490
|
* Creates a dedicated database service by composing a PostgresActor and a Cadenza service.
|
|
8741
9491
|
*/
|
|
8742
9492
|
static createDatabaseService(name, schema, description = "", options = {}) {
|
|
8743
|
-
if (isBrowser) {
|
|
9493
|
+
if (isBrowser || options.isFrontend) {
|
|
8744
9494
|
console.warn(
|
|
8745
|
-
"Database service creation is not supported in
|
|
9495
|
+
"Database service creation is not supported in frontend mode. Use the CadenzaDB service instead."
|
|
8746
9496
|
);
|
|
8747
9497
|
return;
|
|
8748
9498
|
}
|
|
@@ -8837,7 +9587,7 @@ var CadenzaService = class {
|
|
|
8837
9587
|
retryCount: 3,
|
|
8838
9588
|
databaseType: "postgres",
|
|
8839
9589
|
databaseName: (0, import_lodash_es2.snakeCase)(name),
|
|
8840
|
-
poolSize:
|
|
9590
|
+
poolSize: readIntegerEnv("DATABASE_POOL_SIZE", 10),
|
|
8841
9591
|
ownerServiceName: options.ownerServiceName ?? this.serviceRegistry?.serviceName ?? null,
|
|
8842
9592
|
...options
|
|
8843
9593
|
};
|
|
@@ -8848,18 +9598,16 @@ var CadenzaService = class {
|
|
|
8848
9598
|
useSocket: true,
|
|
8849
9599
|
displayName: void 0,
|
|
8850
9600
|
isMeta: false,
|
|
8851
|
-
port:
|
|
8852
|
-
securityProfile:
|
|
8853
|
-
networkMode:
|
|
9601
|
+
port: readIntegerEnv("HTTP_PORT", 3e3),
|
|
9602
|
+
securityProfile: readStringEnv("SECURITY_PROFILE") ?? "medium",
|
|
9603
|
+
networkMode: readStringEnv("NETWORK_MODE") ?? "dev",
|
|
8854
9604
|
retryCount: 3,
|
|
8855
9605
|
cadenzaDB: {
|
|
8856
|
-
connect: true
|
|
8857
|
-
address: process.env.CADENZA_DB_ADDRESS ?? "localhost",
|
|
8858
|
-
port: parseInt(process.env.CADENZA_DB_PORT ?? "5000")
|
|
9606
|
+
connect: true
|
|
8859
9607
|
},
|
|
8860
9608
|
databaseType: "postgres",
|
|
8861
9609
|
databaseName: (0, import_lodash_es2.snakeCase)(name),
|
|
8862
|
-
poolSize:
|
|
9610
|
+
poolSize: readIntegerEnv("DATABASE_POOL_SIZE", 10),
|
|
8863
9611
|
isDatabase: true,
|
|
8864
9612
|
ownerServiceName: options.ownerServiceName ?? name,
|
|
8865
9613
|
...options
|
|
@@ -9307,19 +10055,291 @@ var CadenzaService = class {
|
|
|
9307
10055
|
}
|
|
9308
10056
|
static reset() {
|
|
9309
10057
|
import_core4.default.reset();
|
|
9310
|
-
this.serviceRegistry
|
|
10058
|
+
this.serviceRegistry?.reset();
|
|
10059
|
+
this.isBootstrapped = false;
|
|
10060
|
+
this.serviceCreated = false;
|
|
10061
|
+
this.warnedInvalidMetaIntentResponderKeys = /* @__PURE__ */ new Set();
|
|
10062
|
+
this.hydratedInquiryResults = /* @__PURE__ */ new Map();
|
|
10063
|
+
this.frontendSyncScheduled = false;
|
|
9311
10064
|
}
|
|
9312
10065
|
};
|
|
9313
10066
|
CadenzaService.isBootstrapped = false;
|
|
9314
10067
|
CadenzaService.serviceCreated = false;
|
|
9315
10068
|
CadenzaService.warnedInvalidMetaIntentResponderKeys = /* @__PURE__ */ new Set();
|
|
10069
|
+
CadenzaService.hydratedInquiryResults = /* @__PURE__ */ new Map();
|
|
10070
|
+
CadenzaService.frontendSyncScheduled = false;
|
|
9316
10071
|
|
|
9317
10072
|
// src/index.ts
|
|
9318
10073
|
var import_core5 = require("@cadenza.io/core");
|
|
10074
|
+
|
|
10075
|
+
// src/ssr/createSSRInquiryBridge.ts
|
|
10076
|
+
var import_uuid4 = require("uuid");
|
|
10077
|
+
function ensureFetch() {
|
|
10078
|
+
if (typeof globalThis.fetch !== "function") {
|
|
10079
|
+
throw new Error("SSR inquiry bridge requires global fetch support.");
|
|
10080
|
+
}
|
|
10081
|
+
return globalThis.fetch.bind(globalThis);
|
|
10082
|
+
}
|
|
10083
|
+
function normalizeArrayResponse(value, keys) {
|
|
10084
|
+
for (const key of keys) {
|
|
10085
|
+
if (Array.isArray(value?.[key])) {
|
|
10086
|
+
return value[key];
|
|
10087
|
+
}
|
|
10088
|
+
}
|
|
10089
|
+
if (Array.isArray(value?.rows)) {
|
|
10090
|
+
return value.rows;
|
|
10091
|
+
}
|
|
10092
|
+
if (Array.isArray(value?.data)) {
|
|
10093
|
+
return value.data;
|
|
10094
|
+
}
|
|
10095
|
+
return [];
|
|
10096
|
+
}
|
|
10097
|
+
function normalizeIntentMap(raw) {
|
|
10098
|
+
const intentName = String(raw.intentName ?? raw.intent_name ?? "").trim();
|
|
10099
|
+
const serviceName = String(raw.serviceName ?? raw.service_name ?? "").trim();
|
|
10100
|
+
const taskName = String(raw.taskName ?? raw.task_name ?? "").trim();
|
|
10101
|
+
const taskVersion = Math.max(
|
|
10102
|
+
1,
|
|
10103
|
+
Math.trunc(Number(raw.taskVersion ?? raw.task_version ?? 1) || 1)
|
|
10104
|
+
);
|
|
10105
|
+
if (!intentName || !serviceName || !taskName) {
|
|
10106
|
+
return null;
|
|
10107
|
+
}
|
|
10108
|
+
return {
|
|
10109
|
+
intentName,
|
|
10110
|
+
serviceName,
|
|
10111
|
+
taskName,
|
|
10112
|
+
taskVersion,
|
|
10113
|
+
deleted: Boolean(raw.deleted)
|
|
10114
|
+
};
|
|
10115
|
+
}
|
|
10116
|
+
function buildInquiryMeta(inquiry, startedAt, statuses) {
|
|
10117
|
+
const counts = summarizeResponderStatuses(statuses);
|
|
10118
|
+
return {
|
|
10119
|
+
inquiry,
|
|
10120
|
+
isMetaInquiry: isMetaIntentName(inquiry),
|
|
10121
|
+
totalResponders: statuses.length,
|
|
10122
|
+
eligibleResponders: statuses.length,
|
|
10123
|
+
filteredOutResponders: 0,
|
|
10124
|
+
responded: counts.responded,
|
|
10125
|
+
failed: counts.failed,
|
|
10126
|
+
timedOut: counts.timedOut,
|
|
10127
|
+
pending: counts.pending,
|
|
10128
|
+
durationMs: Date.now() - startedAt,
|
|
10129
|
+
responders: statuses
|
|
10130
|
+
};
|
|
10131
|
+
}
|
|
10132
|
+
function createSSRInquiryBridge(options = {}) {
|
|
10133
|
+
const bootstrapEndpoint = resolveBootstrapEndpoint({
|
|
10134
|
+
runtime: "server",
|
|
10135
|
+
bootstrap: options.bootstrap,
|
|
10136
|
+
cadenzaDB: options.cadenzaDB
|
|
10137
|
+
});
|
|
10138
|
+
const fetchImplementation = ensureFetch();
|
|
10139
|
+
const initialInquiryResults = {};
|
|
10140
|
+
const postDelegation = async (targetUrl, remoteRoutineName, context, timeoutMs) => {
|
|
10141
|
+
const signal = AbortSignal.timeout(timeoutMs);
|
|
10142
|
+
const response = await fetchImplementation(`${targetUrl}/delegation`, {
|
|
10143
|
+
method: "POST",
|
|
10144
|
+
headers: {
|
|
10145
|
+
"Content-Type": "application/json"
|
|
10146
|
+
},
|
|
10147
|
+
body: JSON.stringify({
|
|
10148
|
+
...context,
|
|
10149
|
+
__remoteRoutineName: remoteRoutineName,
|
|
10150
|
+
__metadata: {
|
|
10151
|
+
...context.__metadata ?? {},
|
|
10152
|
+
__deputyExecId: (0, import_uuid4.v4)()
|
|
10153
|
+
}
|
|
10154
|
+
}),
|
|
10155
|
+
signal
|
|
10156
|
+
});
|
|
10157
|
+
return await response.json();
|
|
10158
|
+
};
|
|
10159
|
+
const queryTable = async (tableName, queryData, timeoutMs) => {
|
|
10160
|
+
const response = await postDelegation(
|
|
10161
|
+
bootstrapEndpoint.url,
|
|
10162
|
+
`Query ${tableName}`,
|
|
10163
|
+
{ queryData },
|
|
10164
|
+
timeoutMs
|
|
10165
|
+
);
|
|
10166
|
+
return normalizeArrayResponse(response, [
|
|
10167
|
+
`${tableName}Rows`,
|
|
10168
|
+
`${tableName}s`,
|
|
10169
|
+
tableName,
|
|
10170
|
+
tableName.replace(/_([a-z])/g, (_match, char) => char.toUpperCase())
|
|
10171
|
+
]);
|
|
10172
|
+
};
|
|
10173
|
+
return {
|
|
10174
|
+
async inquire(inquiry, context = {}, inquiryOptions = {}) {
|
|
10175
|
+
const startedAt = Date.now();
|
|
10176
|
+
const overallTimeoutMs = inquiryOptions.overallTimeoutMs ?? inquiryOptions.timeout ?? 3e4;
|
|
10177
|
+
const perResponderTimeoutMs = inquiryOptions.perResponderTimeoutMs ?? overallTimeoutMs;
|
|
10178
|
+
const intentMaps = (await queryTable(
|
|
10179
|
+
"intent_to_task_map",
|
|
10180
|
+
{
|
|
10181
|
+
filter: {
|
|
10182
|
+
intent_name: inquiry
|
|
10183
|
+
}
|
|
10184
|
+
},
|
|
10185
|
+
overallTimeoutMs
|
|
10186
|
+
)).map(normalizeIntentMap).filter(
|
|
10187
|
+
(item) => !!item && item.intentName === inquiry && !item.deleted
|
|
10188
|
+
);
|
|
10189
|
+
if (intentMaps.length === 0) {
|
|
10190
|
+
return {
|
|
10191
|
+
__inquiryMeta: buildInquiryMeta(inquiry, startedAt, [])
|
|
10192
|
+
};
|
|
10193
|
+
}
|
|
10194
|
+
const relevantServiceNames = Array.from(
|
|
10195
|
+
new Set(intentMaps.map((item) => item.serviceName))
|
|
10196
|
+
);
|
|
10197
|
+
const rawServiceInstances = await queryTable(
|
|
10198
|
+
"service_instance",
|
|
10199
|
+
{
|
|
10200
|
+
filter: {
|
|
10201
|
+
service_name: relevantServiceNames
|
|
10202
|
+
}
|
|
10203
|
+
},
|
|
10204
|
+
overallTimeoutMs
|
|
10205
|
+
);
|
|
10206
|
+
const rawServiceTransports = await queryTable(
|
|
10207
|
+
"service_instance_transport",
|
|
10208
|
+
{
|
|
10209
|
+
filter: {
|
|
10210
|
+
deleted: false
|
|
10211
|
+
}
|
|
10212
|
+
},
|
|
10213
|
+
overallTimeoutMs
|
|
10214
|
+
);
|
|
10215
|
+
const transportsByInstance = /* @__PURE__ */ new Map();
|
|
10216
|
+
for (const transport of rawServiceTransports) {
|
|
10217
|
+
const serviceInstanceId = String(
|
|
10218
|
+
transport.serviceInstanceId ?? transport.service_instance_id ?? ""
|
|
10219
|
+
).trim();
|
|
10220
|
+
if (!serviceInstanceId) {
|
|
10221
|
+
continue;
|
|
10222
|
+
}
|
|
10223
|
+
if (!transportsByInstance.has(serviceInstanceId)) {
|
|
10224
|
+
transportsByInstance.set(serviceInstanceId, []);
|
|
10225
|
+
}
|
|
10226
|
+
transportsByInstance.get(serviceInstanceId).push(transport);
|
|
10227
|
+
}
|
|
10228
|
+
const serviceInstances = rawServiceInstances.map(
|
|
10229
|
+
(instance) => normalizeServiceInstanceDescriptor({
|
|
10230
|
+
...instance,
|
|
10231
|
+
transports: transportsByInstance.get(String(instance.uuid ?? "").trim()) ?? []
|
|
10232
|
+
})
|
|
10233
|
+
).filter(
|
|
10234
|
+
(item) => !!item && relevantServiceNames.includes(item.serviceName) && item.isActive && !item.isNonResponsive && !item.isBlocked
|
|
10235
|
+
).sort((left, right) => {
|
|
10236
|
+
if (left.serviceName !== right.serviceName) {
|
|
10237
|
+
return left.serviceName.localeCompare(right.serviceName);
|
|
10238
|
+
}
|
|
10239
|
+
if (left.isPrimary !== right.isPrimary) {
|
|
10240
|
+
return left.isPrimary ? -1 : 1;
|
|
10241
|
+
}
|
|
10242
|
+
return (left.numberOfRunningGraphs ?? 0) - (right.numberOfRunningGraphs ?? 0);
|
|
10243
|
+
});
|
|
10244
|
+
const statuses = intentMaps.map((map) => ({
|
|
10245
|
+
isRemote: true,
|
|
10246
|
+
serviceName: map.serviceName,
|
|
10247
|
+
taskName: map.taskName,
|
|
10248
|
+
taskVersion: map.taskVersion,
|
|
10249
|
+
localTaskName: `SSR inquiry via ${map.serviceName} (${map.taskName} v${map.taskVersion})`,
|
|
10250
|
+
status: "timed_out",
|
|
10251
|
+
durationMs: 0
|
|
10252
|
+
}));
|
|
10253
|
+
const fulfilledContexts = await Promise.all(
|
|
10254
|
+
intentMaps.map(async (map, index) => {
|
|
10255
|
+
const status = statuses[index];
|
|
10256
|
+
const startedAtForResponder = Date.now();
|
|
10257
|
+
const selectedInstance = serviceInstances.find(
|
|
10258
|
+
(instance) => instance.serviceName === map.serviceName
|
|
10259
|
+
);
|
|
10260
|
+
if (!selectedInstance) {
|
|
10261
|
+
status.status = "failed";
|
|
10262
|
+
status.error = `No active instances for ${map.serviceName}`;
|
|
10263
|
+
status.durationMs = Date.now() - startedAtForResponder;
|
|
10264
|
+
return null;
|
|
10265
|
+
}
|
|
10266
|
+
const targetTransport = selectTransportForRole(
|
|
10267
|
+
selectedInstance.transports,
|
|
10268
|
+
"internal",
|
|
10269
|
+
"rest"
|
|
10270
|
+
);
|
|
10271
|
+
if (!targetTransport) {
|
|
10272
|
+
status.status = "failed";
|
|
10273
|
+
status.error = `No internal transport for ${selectedInstance.serviceName}/${selectedInstance.uuid}`;
|
|
10274
|
+
status.durationMs = Date.now() - startedAtForResponder;
|
|
10275
|
+
return null;
|
|
10276
|
+
}
|
|
10277
|
+
const targetUrl = targetTransport.origin;
|
|
10278
|
+
try {
|
|
10279
|
+
const result = await postDelegation(
|
|
10280
|
+
targetUrl,
|
|
10281
|
+
map.taskName,
|
|
10282
|
+
context,
|
|
10283
|
+
perResponderTimeoutMs
|
|
10284
|
+
);
|
|
10285
|
+
status.durationMs = Date.now() - startedAtForResponder;
|
|
10286
|
+
if (result?.errored || result?.failed) {
|
|
10287
|
+
status.status = "failed";
|
|
10288
|
+
status.error = String(
|
|
10289
|
+
result?.__error ?? result?.error ?? "Remote inquiry failed"
|
|
10290
|
+
);
|
|
10291
|
+
return null;
|
|
10292
|
+
}
|
|
10293
|
+
status.status = "fulfilled";
|
|
10294
|
+
return result;
|
|
10295
|
+
} catch (error) {
|
|
10296
|
+
status.durationMs = Date.now() - startedAtForResponder;
|
|
10297
|
+
if (error instanceof Error && (error.name === "AbortError" || /timed out/i.test(error.message))) {
|
|
10298
|
+
status.status = "timed_out";
|
|
10299
|
+
status.error = error.message;
|
|
10300
|
+
return null;
|
|
10301
|
+
}
|
|
10302
|
+
status.status = "failed";
|
|
10303
|
+
status.error = error instanceof Error ? error.message : String(error);
|
|
10304
|
+
return null;
|
|
10305
|
+
}
|
|
10306
|
+
})
|
|
10307
|
+
);
|
|
10308
|
+
const mergedContext = mergeInquiryContexts(
|
|
10309
|
+
fulfilledContexts.filter(
|
|
10310
|
+
(item) => item !== null
|
|
10311
|
+
)
|
|
10312
|
+
);
|
|
10313
|
+
const responseContext = {
|
|
10314
|
+
...mergedContext,
|
|
10315
|
+
__inquiryMeta: buildInquiryMeta(inquiry, startedAt, statuses)
|
|
10316
|
+
};
|
|
10317
|
+
if (inquiryOptions.hydrationKey) {
|
|
10318
|
+
initialInquiryResults[inquiryOptions.hydrationKey] = responseContext;
|
|
10319
|
+
}
|
|
10320
|
+
if (inquiryOptions.requireComplete && statuses.some((status) => status.status !== "fulfilled")) {
|
|
10321
|
+
throw {
|
|
10322
|
+
...responseContext,
|
|
10323
|
+
__error: `Inquiry '${inquiry}' did not complete successfully`,
|
|
10324
|
+
errored: true
|
|
10325
|
+
};
|
|
10326
|
+
}
|
|
10327
|
+
return responseContext;
|
|
10328
|
+
},
|
|
10329
|
+
dehydrate() {
|
|
10330
|
+
return {
|
|
10331
|
+
initialInquiryResults: { ...initialInquiryResults }
|
|
10332
|
+
};
|
|
10333
|
+
}
|
|
10334
|
+
};
|
|
10335
|
+
}
|
|
10336
|
+
|
|
10337
|
+
// src/index.ts
|
|
9319
10338
|
var index_default = CadenzaService;
|
|
9320
10339
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9321
10340
|
0 && (module.exports = {
|
|
9322
10341
|
Actor,
|
|
10342
|
+
DatabaseController,
|
|
9323
10343
|
DatabaseTask,
|
|
9324
10344
|
DebounceTask,
|
|
9325
10345
|
DeputyTask,
|
|
@@ -9331,6 +10351,7 @@ var index_default = CadenzaService;
|
|
|
9331
10351
|
SignalController,
|
|
9332
10352
|
SignalTransmissionTask,
|
|
9333
10353
|
SocketController,
|
|
9334
|
-
Task
|
|
10354
|
+
Task,
|
|
10355
|
+
createSSRInquiryBridge
|
|
9335
10356
|
});
|
|
9336
10357
|
//# sourceMappingURL=index.js.map
|