@cadenza.io/service 2.12.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 +53 -1
- 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 +211 -33
- package/dist/index.d.ts +211 -33
- package/dist/index.js +1744 -538
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1738 -534
- 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
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
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
|
+
};
|
|
3191
|
+
const createHttpServer = async (ctx2) => {
|
|
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}`;
|
|
4996
|
+
const transportId = String(
|
|
4997
|
+
input.serviceTransportId ?? input.transportId ?? ""
|
|
4998
|
+
).trim();
|
|
4999
|
+
return transportId || void 0;
|
|
4535
5000
|
}
|
|
4536
|
-
|
|
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);
|
|
4545
|
-
}
|
|
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,
|
|
@@ -4848,8 +5305,132 @@ var SignalController = class _SignalController {
|
|
|
4848
5305
|
}
|
|
4849
5306
|
};
|
|
4850
5307
|
|
|
4851
|
-
// src/graph/controllers/
|
|
5308
|
+
// src/graph/controllers/registerActorSessionPersistence.ts
|
|
4852
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
|
+
}
|
|
5432
|
+
|
|
5433
|
+
// src/graph/controllers/GraphMetadataController.ts
|
|
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 {
|
|
@@ -5244,6 +5709,9 @@ function normalizeIntentToken(value) {
|
|
|
5244
5709
|
}
|
|
5245
5710
|
return normalized;
|
|
5246
5711
|
}
|
|
5712
|
+
function buildPostgresActorName(name) {
|
|
5713
|
+
return `${String(name ?? "").trim()}PostgresActor`;
|
|
5714
|
+
}
|
|
5247
5715
|
function validateIntentName(intentName) {
|
|
5248
5716
|
if (!intentName || typeof intentName !== "string") {
|
|
5249
5717
|
throw new Error("Intent name must be a non-empty string");
|
|
@@ -5381,7 +5849,8 @@ function resolveDataRows(data) {
|
|
|
5381
5849
|
}
|
|
5382
5850
|
var DatabaseController = class _DatabaseController {
|
|
5383
5851
|
constructor() {
|
|
5384
|
-
this.
|
|
5852
|
+
this.registrationsByActorName = /* @__PURE__ */ new Map();
|
|
5853
|
+
this.registrationsByActorToken = /* @__PURE__ */ new Map();
|
|
5385
5854
|
this.adminDbClient = new import_pg.Pool({
|
|
5386
5855
|
connectionString: process.env.DATABASE_ADDRESS ?? "",
|
|
5387
5856
|
database: "postgres",
|
|
@@ -5392,15 +5861,11 @@ var DatabaseController = class _DatabaseController {
|
|
|
5392
5861
|
CadenzaService.createMetaTask(
|
|
5393
5862
|
"Route PostgresActor setup requests",
|
|
5394
5863
|
(ctx) => {
|
|
5395
|
-
const
|
|
5396
|
-
if (!serviceName) {
|
|
5397
|
-
return ctx;
|
|
5398
|
-
}
|
|
5399
|
-
const registration = this.registrationsByService.get(serviceName);
|
|
5864
|
+
const registration = this.resolveRegistration(ctx);
|
|
5400
5865
|
if (!registration) {
|
|
5401
5866
|
return ctx;
|
|
5402
5867
|
}
|
|
5403
|
-
|
|
5868
|
+
this.requestPostgresActorSetup(registration, ctx);
|
|
5404
5869
|
return ctx;
|
|
5405
5870
|
},
|
|
5406
5871
|
"Routes generic database init requests to actor-scoped setup signal.",
|
|
@@ -5412,23 +5877,25 @@ var DatabaseController = class _DatabaseController {
|
|
|
5412
5877
|
return this._instance;
|
|
5413
5878
|
}
|
|
5414
5879
|
reset() {
|
|
5415
|
-
for (const registration of this.
|
|
5880
|
+
for (const registration of this.registrationsByActorName.values()) {
|
|
5416
5881
|
const runtimeState = registration.actor.getRuntimeState(registration.actorKey);
|
|
5417
5882
|
if (runtimeState?.pool) {
|
|
5418
5883
|
runtimeState.pool.end().catch(() => void 0);
|
|
5419
5884
|
}
|
|
5420
5885
|
}
|
|
5421
|
-
this.
|
|
5886
|
+
this.registrationsByActorName.clear();
|
|
5887
|
+
this.registrationsByActorToken.clear();
|
|
5422
5888
|
this.adminDbClient.end().catch(() => void 0);
|
|
5423
5889
|
}
|
|
5424
|
-
createPostgresActor(
|
|
5425
|
-
const
|
|
5890
|
+
createPostgresActor(name, schema, description, options) {
|
|
5891
|
+
const actorName = buildPostgresActorName(name);
|
|
5892
|
+
const existing = this.registrationsByActorName.get(actorName);
|
|
5426
5893
|
if (existing) {
|
|
5427
5894
|
return existing;
|
|
5428
5895
|
}
|
|
5429
|
-
const actorName = `${serviceName}PostgresActor`;
|
|
5430
5896
|
const actorToken = normalizeIntentToken(actorName);
|
|
5431
|
-
const actorKey = String(options.databaseName ?? (0, import_lodash_es.snakeCase)(
|
|
5897
|
+
const actorKey = String(options.databaseName ?? (0, import_lodash_es.snakeCase)(name));
|
|
5898
|
+
const ownerServiceName = options.ownerServiceName ?? CadenzaService.serviceRegistry?.serviceName ?? null;
|
|
5432
5899
|
const optionTimeout = typeof options.timeoutMs === "number" ? Number(options.timeoutMs) : Number(options.timeout);
|
|
5433
5900
|
const safetyPolicy = {
|
|
5434
5901
|
statementTimeoutMs: normalizePositiveInteger(
|
|
@@ -5446,7 +5913,7 @@ var DatabaseController = class _DatabaseController {
|
|
|
5446
5913
|
const actor = CadenzaService.createActor(
|
|
5447
5914
|
{
|
|
5448
5915
|
name: actorName,
|
|
5449
|
-
description: "Specialized PostgresActor owning pool runtime state and schema-driven DB task generation.",
|
|
5916
|
+
description: description || "Specialized PostgresActor owning pool runtime state and schema-driven DB task generation.",
|
|
5450
5917
|
defaultKey: actorKey,
|
|
5451
5918
|
keyResolver: (input) => typeof input.databaseName === "string" ? input.databaseName : void 0,
|
|
5452
5919
|
loadPolicy: "eager",
|
|
@@ -5454,7 +5921,7 @@ var DatabaseController = class _DatabaseController {
|
|
|
5454
5921
|
initState: {
|
|
5455
5922
|
actorName,
|
|
5456
5923
|
actorToken,
|
|
5457
|
-
|
|
5924
|
+
ownerServiceName,
|
|
5458
5925
|
databaseName: actorKey,
|
|
5459
5926
|
status: "idle",
|
|
5460
5927
|
schemaVersion: Number(schema.version ?? 1),
|
|
@@ -5469,23 +5936,99 @@ var DatabaseController = class _DatabaseController {
|
|
|
5469
5936
|
{ isMeta: Boolean(options.isMeta) }
|
|
5470
5937
|
);
|
|
5471
5938
|
const registration = {
|
|
5472
|
-
|
|
5939
|
+
ownerServiceName,
|
|
5473
5940
|
databaseName: actorKey,
|
|
5474
5941
|
actorName,
|
|
5475
5942
|
actorToken,
|
|
5476
5943
|
actorKey,
|
|
5944
|
+
setupSignal: `meta.postgres_actor.setup_requested.${actorToken}`,
|
|
5945
|
+
setupDoneSignal: `meta.postgres_actor.setup_done.${actorToken}`,
|
|
5946
|
+
setupFailedSignal: `meta.postgres_actor.setup_failed.${actorToken}`,
|
|
5477
5947
|
actor,
|
|
5478
5948
|
schema,
|
|
5949
|
+
description,
|
|
5479
5950
|
options,
|
|
5480
5951
|
tasksGenerated: false,
|
|
5481
5952
|
intentNames: /* @__PURE__ */ new Set()
|
|
5482
5953
|
};
|
|
5483
|
-
this.
|
|
5954
|
+
this.registrationsByActorName.set(actorName, registration);
|
|
5955
|
+
this.registrationsByActorToken.set(actorToken, registration);
|
|
5484
5956
|
this.registerSetupTask(registration);
|
|
5485
5957
|
return registration;
|
|
5486
5958
|
}
|
|
5959
|
+
requestPostgresActorSetup(registrationOrName, ctx = {}) {
|
|
5960
|
+
const registration = typeof registrationOrName === "string" ? this.resolveRegistration({
|
|
5961
|
+
actorName: registrationOrName
|
|
5962
|
+
}) : registrationOrName;
|
|
5963
|
+
if (!registration) {
|
|
5964
|
+
return void 0;
|
|
5965
|
+
}
|
|
5966
|
+
const payload = {
|
|
5967
|
+
...ctx,
|
|
5968
|
+
actorName: registration.actorName,
|
|
5969
|
+
actorToken: registration.actorToken,
|
|
5970
|
+
databaseName: registration.databaseName,
|
|
5971
|
+
ownerServiceName: registration.ownerServiceName,
|
|
5972
|
+
options: {
|
|
5973
|
+
...ctx.options ?? {},
|
|
5974
|
+
actorName: registration.actorName,
|
|
5975
|
+
actorToken: registration.actorToken,
|
|
5976
|
+
ownerServiceName: registration.ownerServiceName,
|
|
5977
|
+
databaseName: registration.databaseName
|
|
5978
|
+
}
|
|
5979
|
+
};
|
|
5980
|
+
const runtimeState = registration.actor.getRuntimeState(registration.actorKey);
|
|
5981
|
+
if (runtimeState?.ready) {
|
|
5982
|
+
this.emitSetupDone(registration, payload);
|
|
5983
|
+
return registration;
|
|
5984
|
+
}
|
|
5985
|
+
CadenzaService.emit(registration.setupSignal, payload);
|
|
5986
|
+
return registration;
|
|
5987
|
+
}
|
|
5988
|
+
resolveRegistration(ctx) {
|
|
5989
|
+
const rawActorToken = String(
|
|
5990
|
+
ctx.options?.actorToken ?? ctx.actorToken ?? ""
|
|
5991
|
+
).trim();
|
|
5992
|
+
if (rawActorToken) {
|
|
5993
|
+
const actorToken = normalizeIntentToken(rawActorToken);
|
|
5994
|
+
const registration = this.registrationsByActorToken.get(actorToken);
|
|
5995
|
+
if (registration) {
|
|
5996
|
+
return registration;
|
|
5997
|
+
}
|
|
5998
|
+
}
|
|
5999
|
+
const rawActorName = String(
|
|
6000
|
+
ctx.options?.actorName ?? ctx.actorName ?? ctx.options?.postgresActorName ?? ctx.postgresActorName ?? ""
|
|
6001
|
+
).trim();
|
|
6002
|
+
if (rawActorName) {
|
|
6003
|
+
const registration = this.registrationsByActorName.get(rawActorName) ?? this.registrationsByActorName.get(buildPostgresActorName(rawActorName));
|
|
6004
|
+
if (registration) {
|
|
6005
|
+
return registration;
|
|
6006
|
+
}
|
|
6007
|
+
}
|
|
6008
|
+
const legacyServiceName = String(
|
|
6009
|
+
ctx.options?.serviceName ?? ctx.serviceName ?? ""
|
|
6010
|
+
).trim();
|
|
6011
|
+
if (legacyServiceName) {
|
|
6012
|
+
return this.registrationsByActorName.get(
|
|
6013
|
+
buildPostgresActorName(legacyServiceName)
|
|
6014
|
+
);
|
|
6015
|
+
}
|
|
6016
|
+
return void 0;
|
|
6017
|
+
}
|
|
6018
|
+
emitSetupDone(registration, payload) {
|
|
6019
|
+
const resolvedPayload = {
|
|
6020
|
+
...payload,
|
|
6021
|
+
actorName: registration.actorName,
|
|
6022
|
+
actorToken: registration.actorToken,
|
|
6023
|
+
databaseName: registration.databaseName,
|
|
6024
|
+
ownerServiceName: registration.ownerServiceName,
|
|
6025
|
+
__success: true
|
|
6026
|
+
};
|
|
6027
|
+
CadenzaService.emit(registration.setupDoneSignal, resolvedPayload);
|
|
6028
|
+
CadenzaService.emit("meta.postgres_actor.setup_done", resolvedPayload);
|
|
6029
|
+
CadenzaService.emit("meta.database.setup_done", resolvedPayload);
|
|
6030
|
+
}
|
|
5487
6031
|
registerSetupTask(registration) {
|
|
5488
|
-
const setupSignal = `meta.postgres_actor.setup_requested.${registration.actorToken}`;
|
|
5489
6032
|
CadenzaService.createMetaTask(
|
|
5490
6033
|
`Setup ${registration.actorName}`,
|
|
5491
6034
|
registration.actor.task(
|
|
@@ -5545,17 +6088,15 @@ var DatabaseController = class _DatabaseController {
|
|
|
5545
6088
|
lastError: null,
|
|
5546
6089
|
tables: Object.keys(registration.schema.tables ?? {})
|
|
5547
6090
|
});
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
databaseName: registration.databaseName,
|
|
5551
|
-
actorName: registration.actorName,
|
|
5552
|
-
__success: true
|
|
6091
|
+
this.emitSetupDone(registration, {
|
|
6092
|
+
...input
|
|
5553
6093
|
});
|
|
5554
6094
|
return {
|
|
5555
6095
|
...input,
|
|
5556
6096
|
__success: true,
|
|
5557
6097
|
actorName: registration.actorName,
|
|
5558
|
-
databaseName: registration.databaseName
|
|
6098
|
+
databaseName: registration.databaseName,
|
|
6099
|
+
ownerServiceName: registration.ownerServiceName
|
|
5559
6100
|
};
|
|
5560
6101
|
} catch (error) {
|
|
5561
6102
|
const message = errorMessage(error);
|
|
@@ -5579,7 +6120,11 @@ var DatabaseController = class _DatabaseController {
|
|
|
5579
6120
|
),
|
|
5580
6121
|
"Initializes PostgresActor runtime pool, applies schema, and generates CRUD tasks/intents.",
|
|
5581
6122
|
{ isMeta: true }
|
|
5582
|
-
).doOn(setupSignal)
|
|
6123
|
+
).doOn(registration.setupSignal).emitsOnFail(
|
|
6124
|
+
registration.setupFailedSignal,
|
|
6125
|
+
"meta.postgres_actor.setup_failed",
|
|
6126
|
+
"meta.database.setup_failed"
|
|
6127
|
+
);
|
|
5583
6128
|
}
|
|
5584
6129
|
createTargetPool(databaseName, statementTimeoutMs) {
|
|
5585
6130
|
const connectionString = this.buildDatabaseConnectionString(databaseName);
|
|
@@ -7755,6 +8300,165 @@ var GraphSyncController = class _GraphSyncController {
|
|
|
7755
8300
|
}
|
|
7756
8301
|
};
|
|
7757
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
|
+
|
|
7758
8462
|
// src/Cadenza.ts
|
|
7759
8463
|
var CadenzaService = class {
|
|
7760
8464
|
/**
|
|
@@ -7773,11 +8477,60 @@ var CadenzaService = class {
|
|
|
7773
8477
|
this.metaRunner = import_core4.default.metaRunner;
|
|
7774
8478
|
this.registry = import_core4.default.registry;
|
|
7775
8479
|
this.serviceRegistry = ServiceRegistry.instance;
|
|
7776
|
-
SignalController.instance;
|
|
7777
8480
|
RestController.instance;
|
|
7778
8481
|
SocketController.instance;
|
|
7779
8482
|
console.log("BOOTSTRAPPED");
|
|
7780
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
|
+
}
|
|
7781
8534
|
/**
|
|
7782
8535
|
* Validates the provided service name based on specific rules.
|
|
7783
8536
|
*
|
|
@@ -7890,6 +8643,12 @@ var CadenzaService = class {
|
|
|
7890
8643
|
}
|
|
7891
8644
|
static async inquire(inquiry, context, options = {}) {
|
|
7892
8645
|
this.bootstrap();
|
|
8646
|
+
const hydratedResult = this.consumeHydratedInquiryResult(
|
|
8647
|
+
options.hydrationKey
|
|
8648
|
+
);
|
|
8649
|
+
if (hydratedResult !== void 0) {
|
|
8650
|
+
return hydratedResult;
|
|
8651
|
+
}
|
|
7893
8652
|
const observer = this.inquiryBroker?.inquiryObservers.get(inquiry);
|
|
7894
8653
|
const allResponders = observer ? Array.from(observer.tasks).map((task) => ({
|
|
7895
8654
|
task,
|
|
@@ -8494,58 +9253,97 @@ var CadenzaService = class {
|
|
|
8494
9253
|
const serviceId = options.customServiceId ?? (0, import_uuid3.v4)();
|
|
8495
9254
|
this.serviceRegistry.serviceName = serviceName;
|
|
8496
9255
|
this.serviceRegistry.serviceInstanceId = serviceId;
|
|
9256
|
+
this.setHydrationResults(options.hydration);
|
|
9257
|
+
const explicitFrontendMode = options.isFrontend;
|
|
8497
9258
|
options = {
|
|
8498
9259
|
loadBalance: true,
|
|
8499
9260
|
useSocket: true,
|
|
8500
9261
|
displayName: void 0,
|
|
8501
9262
|
isMeta: false,
|
|
8502
|
-
port:
|
|
8503
|
-
securityProfile:
|
|
8504
|
-
networkMode:
|
|
9263
|
+
port: readIntegerEnv("HTTP_PORT", 3e3),
|
|
9264
|
+
securityProfile: readStringEnv("SECURITY_PROFILE") ?? "medium",
|
|
9265
|
+
networkMode: readStringEnv("NETWORK_MODE") ?? "dev",
|
|
8505
9266
|
retryCount: 3,
|
|
8506
9267
|
cadenzaDB: {
|
|
8507
|
-
connect: true
|
|
8508
|
-
address: process.env.CADENZA_DB_ADDRESS ?? "localhost",
|
|
8509
|
-
port: parseInt(process.env.CADENZA_DB_PORT ?? "5000")
|
|
9268
|
+
connect: true
|
|
8510
9269
|
},
|
|
8511
|
-
relatedServices:
|
|
8512
|
-
|
|
8513
|
-
) : [],
|
|
8514
|
-
isFrontend: isBrowser,
|
|
9270
|
+
relatedServices: readListEnv("RELATED_SERVICES"),
|
|
9271
|
+
isFrontend: typeof explicitFrontendMode === "boolean" ? explicitFrontendMode : isBrowser,
|
|
8515
9272
|
...options
|
|
8516
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
|
+
}
|
|
8517
9296
|
if (options.cadenzaDB?.connect) {
|
|
8518
9297
|
this.emit("meta.initializing_service", {
|
|
8519
9298
|
// Seed the CadenzaDB
|
|
8520
9299
|
serviceInstance: {
|
|
8521
9300
|
uuid: "cadenza-db",
|
|
8522
9301
|
serviceName: "CadenzaDB",
|
|
8523
|
-
address: options.cadenzaDB?.address,
|
|
8524
|
-
port: options.cadenzaDB?.port,
|
|
8525
|
-
exposed: options.networkMode !== "dev",
|
|
8526
9302
|
numberOfRunningGraphs: 0,
|
|
8527
9303
|
isActive: true,
|
|
8528
9304
|
// Assume it is deployed
|
|
8529
9305
|
isNonResponsive: false,
|
|
8530
9306
|
isBlocked: false,
|
|
8531
|
-
health: {}
|
|
9307
|
+
health: {},
|
|
9308
|
+
isFrontend: false,
|
|
9309
|
+
transports: resolvedBootstrapEndpoint ? [
|
|
9310
|
+
this.createBootstrapTransport(
|
|
9311
|
+
"cadenza-db",
|
|
9312
|
+
isFrontend ? "public" : "internal",
|
|
9313
|
+
resolvedBootstrapEndpoint
|
|
9314
|
+
)
|
|
9315
|
+
] : []
|
|
8532
9316
|
}
|
|
8533
9317
|
});
|
|
8534
9318
|
}
|
|
8535
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
|
+
});
|
|
8536
9325
|
this.emit("meta.initializing_service", {
|
|
8537
9326
|
serviceInstance: {
|
|
8538
9327
|
uuid: service[0],
|
|
8539
9328
|
serviceName: service[1],
|
|
8540
|
-
address: service[2].split(":")[0],
|
|
8541
|
-
port: service[2].split(":")[1] ?? 3e3,
|
|
8542
|
-
exposed: options.networkMode !== "dev",
|
|
8543
9329
|
numberOfRunningGraphs: 0,
|
|
8544
9330
|
isActive: true,
|
|
8545
9331
|
// Assume it is deployed
|
|
8546
9332
|
isNonResponsive: false,
|
|
8547
9333
|
isBlocked: false,
|
|
8548
|
-
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
|
+
] : []
|
|
8549
9347
|
}
|
|
8550
9348
|
});
|
|
8551
9349
|
});
|
|
@@ -8566,7 +9364,9 @@ var CadenzaService = class {
|
|
|
8566
9364
|
__networkMode: options.networkMode,
|
|
8567
9365
|
__retryCount: options.retryCount,
|
|
8568
9366
|
__cadenzaDBConnect: options.cadenzaDB?.connect,
|
|
8569
|
-
__isDatabase: options.isDatabase
|
|
9367
|
+
__isDatabase: options.isDatabase,
|
|
9368
|
+
__isFrontend: isFrontend,
|
|
9369
|
+
__declaredTransports: declaredTransports
|
|
8570
9370
|
};
|
|
8571
9371
|
if (options.cadenzaDB?.connect) {
|
|
8572
9372
|
this.createEphemeralMetaTask("Create service", async (context, emit) => {
|
|
@@ -8582,12 +9382,42 @@ var CadenzaService = class {
|
|
|
8582
9382
|
}).doOn("meta.rest.handshake");
|
|
8583
9383
|
}
|
|
8584
9384
|
this.createMetaTask("Handle service setup completion", () => {
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
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
|
+
}
|
|
8588
9393
|
this.log("Service created.");
|
|
8589
9394
|
return true;
|
|
8590
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
|
+
}
|
|
8591
9421
|
this.serviceCreated = true;
|
|
8592
9422
|
}
|
|
8593
9423
|
/**
|
|
@@ -8603,87 +9433,52 @@ var CadenzaService = class {
|
|
|
8603
9433
|
this.createCadenzaService(serviceName, description, options);
|
|
8604
9434
|
}
|
|
8605
9435
|
/**
|
|
8606
|
-
* Creates and initializes a PostgresActor
|
|
8607
|
-
* This is
|
|
9436
|
+
* Creates and initializes a specialized PostgresActor.
|
|
9437
|
+
* This is actor-only and does not create or register a network service.
|
|
8608
9438
|
*
|
|
8609
|
-
* @param {string} name - Logical
|
|
9439
|
+
* @param {string} name - Logical PostgresActor name.
|
|
8610
9440
|
* @param {DatabaseSchemaDefinition} schema - Database schema definition.
|
|
8611
|
-
* @param {string} [description=""] - Optional human-readable description.
|
|
8612
|
-
* @param {ServerOptions & DatabaseOptions} [options={}] -
|
|
9441
|
+
* @param {string} [description=""] - Optional human-readable actor description.
|
|
9442
|
+
* @param {ServerOptions & DatabaseOptions} [options={}] - Actor/database runtime options.
|
|
8613
9443
|
* @return {void}
|
|
8614
9444
|
*/
|
|
8615
9445
|
static createPostgresActor(name, schema, description = "", options = {}) {
|
|
8616
|
-
if (isBrowser) {
|
|
9446
|
+
if (isBrowser || options.isFrontend) {
|
|
8617
9447
|
console.warn(
|
|
8618
|
-
"
|
|
9448
|
+
"PostgresActor creation is not supported in frontend mode."
|
|
8619
9449
|
);
|
|
8620
9450
|
return;
|
|
8621
9451
|
}
|
|
8622
|
-
if (this.serviceCreated) return;
|
|
8623
9452
|
this.bootstrap();
|
|
8624
|
-
this.
|
|
9453
|
+
this.validateName(name);
|
|
8625
9454
|
const databaseController = DatabaseController.instance;
|
|
8626
|
-
|
|
8627
|
-
loadBalance: true,
|
|
8628
|
-
useSocket: true,
|
|
8629
|
-
displayName: void 0,
|
|
8630
|
-
isMeta: false,
|
|
8631
|
-
port: parseInt(process.env.HTTP_PORT ?? "3000"),
|
|
8632
|
-
securityProfile: process.env.SECURITY_PROFILE ?? "medium",
|
|
8633
|
-
networkMode: process.env.NETWORK_MODE ?? "dev",
|
|
8634
|
-
retryCount: 3,
|
|
8635
|
-
cadenzaDB: {
|
|
8636
|
-
connect: true,
|
|
8637
|
-
address: process.env.CADENZA_DB_ADDRESS ?? "localhost",
|
|
8638
|
-
port: parseInt(process.env.CADENZA_DB_PORT ?? "5000")
|
|
8639
|
-
},
|
|
8640
|
-
databaseType: "postgres",
|
|
8641
|
-
databaseName: (0, import_lodash_es2.snakeCase)(name),
|
|
8642
|
-
poolSize: parseInt(process.env.DATABASE_POOL_SIZE ?? "10"),
|
|
8643
|
-
isDatabase: true,
|
|
8644
|
-
...options
|
|
8645
|
-
};
|
|
9455
|
+
const normalizedOptions = this.normalizePostgresActorOptions(name, options);
|
|
8646
9456
|
const registration = databaseController.createPostgresActor(
|
|
8647
9457
|
name,
|
|
8648
9458
|
schema,
|
|
8649
|
-
|
|
9459
|
+
description,
|
|
9460
|
+
normalizedOptions
|
|
8650
9461
|
);
|
|
8651
9462
|
console.log("Creating PostgresActor", {
|
|
8652
|
-
|
|
9463
|
+
name,
|
|
8653
9464
|
actorName: registration.actorName,
|
|
8654
|
-
|
|
9465
|
+
ownerServiceName: normalizedOptions.ownerServiceName ?? null,
|
|
9466
|
+
options: normalizedOptions
|
|
8655
9467
|
});
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
9468
|
+
databaseController.requestPostgresActorSetup(registration, {
|
|
9469
|
+
actorName: registration.actorName,
|
|
9470
|
+
actorToken: registration.actorToken,
|
|
9471
|
+
databaseName: normalizedOptions.databaseName,
|
|
9472
|
+
ownerServiceName: normalizedOptions.ownerServiceName ?? null
|
|
8660
9473
|
});
|
|
8661
|
-
this.createMetaTask("Set database connection", () => {
|
|
8662
|
-
this.createMetaTask("Insert database service bridge", (_, emit) => {
|
|
8663
|
-
emit("global.meta.created_database_service", {
|
|
8664
|
-
data: {
|
|
8665
|
-
service_name: name,
|
|
8666
|
-
description,
|
|
8667
|
-
schema,
|
|
8668
|
-
is_meta: options.isMeta
|
|
8669
|
-
}
|
|
8670
|
-
});
|
|
8671
|
-
this.log("Database service created", {
|
|
8672
|
-
name,
|
|
8673
|
-
isMeta: options.isMeta,
|
|
8674
|
-
actorName: registration.actorName
|
|
8675
|
-
});
|
|
8676
|
-
}).doOn("meta.service_registry.service_inserted");
|
|
8677
|
-
this.createCadenzaService(name, description, options);
|
|
8678
|
-
}).doOn("meta.database.setup_done");
|
|
8679
9474
|
}
|
|
8680
9475
|
/**
|
|
8681
|
-
* Creates a meta PostgresActor
|
|
9476
|
+
* Creates a meta PostgresActor.
|
|
8682
9477
|
*
|
|
8683
|
-
* @param {string} name - Logical
|
|
9478
|
+
* @param {string} name - Logical PostgresActor name.
|
|
8684
9479
|
* @param {DatabaseSchemaDefinition} schema - Database schema definition.
|
|
8685
9480
|
* @param {string} [description=""] - Optional description.
|
|
8686
|
-
* @param {ServerOptions & DatabaseOptions} [options={}] - Optional
|
|
9481
|
+
* @param {ServerOptions & DatabaseOptions} [options={}] - Optional actor/database options.
|
|
8687
9482
|
* @return {void}
|
|
8688
9483
|
*/
|
|
8689
9484
|
static createMetaPostgresActor(name, schema, description = "", options = {}) {
|
|
@@ -8692,10 +9487,84 @@ var CadenzaService = class {
|
|
|
8692
9487
|
this.createPostgresActor(name, schema, description, options);
|
|
8693
9488
|
}
|
|
8694
9489
|
/**
|
|
8695
|
-
*
|
|
9490
|
+
* Creates a dedicated database service by composing a PostgresActor and a Cadenza service.
|
|
8696
9491
|
*/
|
|
8697
9492
|
static createDatabaseService(name, schema, description = "", options = {}) {
|
|
8698
|
-
|
|
9493
|
+
if (isBrowser || options.isFrontend) {
|
|
9494
|
+
console.warn(
|
|
9495
|
+
"Database service creation is not supported in frontend mode. Use the CadenzaDB service instead."
|
|
9496
|
+
);
|
|
9497
|
+
return;
|
|
9498
|
+
}
|
|
9499
|
+
if (this.serviceCreated) return;
|
|
9500
|
+
this.bootstrap();
|
|
9501
|
+
this.validateName(name);
|
|
9502
|
+
this.validateServiceName(name);
|
|
9503
|
+
const databaseController = DatabaseController.instance;
|
|
9504
|
+
const actorOptions = this.normalizePostgresActorOptions(name, {
|
|
9505
|
+
...options,
|
|
9506
|
+
ownerServiceName: options.ownerServiceName ?? name
|
|
9507
|
+
});
|
|
9508
|
+
const serviceOptions = this.normalizeDatabaseServiceOptions(name, {
|
|
9509
|
+
...options,
|
|
9510
|
+
ownerServiceName: actorOptions.ownerServiceName
|
|
9511
|
+
});
|
|
9512
|
+
const registration = databaseController.createPostgresActor(
|
|
9513
|
+
name,
|
|
9514
|
+
schema,
|
|
9515
|
+
description,
|
|
9516
|
+
actorOptions
|
|
9517
|
+
);
|
|
9518
|
+
this.registerDatabaseServiceBridgeTask(
|
|
9519
|
+
name,
|
|
9520
|
+
description,
|
|
9521
|
+
schema,
|
|
9522
|
+
Boolean(serviceOptions.isMeta),
|
|
9523
|
+
registration.actorName
|
|
9524
|
+
);
|
|
9525
|
+
const createServiceTaskName = `Create database service ${name} after ${registration.actorName} setup`;
|
|
9526
|
+
if (!this.get(createServiceTaskName)) {
|
|
9527
|
+
this.createMetaTask(
|
|
9528
|
+
createServiceTaskName,
|
|
9529
|
+
() => {
|
|
9530
|
+
this.createCadenzaService(name, description, serviceOptions);
|
|
9531
|
+
return true;
|
|
9532
|
+
},
|
|
9533
|
+
"Creates the networked database service after PostgresActor setup completes."
|
|
9534
|
+
).doOn(registration.setupDoneSignal);
|
|
9535
|
+
}
|
|
9536
|
+
const setupFailureTaskName = `Handle database service ${name} bootstrap failure`;
|
|
9537
|
+
if (!this.get(setupFailureTaskName)) {
|
|
9538
|
+
this.createMetaTask(
|
|
9539
|
+
setupFailureTaskName,
|
|
9540
|
+
(ctx) => {
|
|
9541
|
+
this.log(
|
|
9542
|
+
"Database service bootstrap failed before service creation.",
|
|
9543
|
+
{
|
|
9544
|
+
serviceName: name,
|
|
9545
|
+
actorName: registration.actorName,
|
|
9546
|
+
databaseName: registration.databaseName,
|
|
9547
|
+
error: ctx.__error
|
|
9548
|
+
},
|
|
9549
|
+
"error"
|
|
9550
|
+
);
|
|
9551
|
+
return true;
|
|
9552
|
+
},
|
|
9553
|
+
"Logs PostgresActor setup failures for database service bootstrap."
|
|
9554
|
+
).doOn(registration.setupFailedSignal);
|
|
9555
|
+
}
|
|
9556
|
+
console.log("Creating database service wrapper", {
|
|
9557
|
+
serviceName: name,
|
|
9558
|
+
actorName: registration.actorName,
|
|
9559
|
+
actorOptions,
|
|
9560
|
+
serviceOptions
|
|
9561
|
+
});
|
|
9562
|
+
databaseController.requestPostgresActorSetup(registration, {
|
|
9563
|
+
actorName: registration.actorName,
|
|
9564
|
+
actorToken: registration.actorToken,
|
|
9565
|
+
databaseName: actorOptions.databaseName,
|
|
9566
|
+
ownerServiceName: actorOptions.ownerServiceName ?? name
|
|
9567
|
+
});
|
|
8699
9568
|
}
|
|
8700
9569
|
/**
|
|
8701
9570
|
* Creates a meta database service with the specified configuration.
|
|
@@ -8707,7 +9576,71 @@ var CadenzaService = class {
|
|
|
8707
9576
|
* @return {void} - This method does not return a value.
|
|
8708
9577
|
*/
|
|
8709
9578
|
static createMetaDatabaseService(name, schema, description = "", options = {}) {
|
|
8710
|
-
this.
|
|
9579
|
+
this.createDatabaseService(name, schema, description, {
|
|
9580
|
+
...options,
|
|
9581
|
+
isMeta: true
|
|
9582
|
+
});
|
|
9583
|
+
}
|
|
9584
|
+
static normalizePostgresActorOptions(name, options = {}) {
|
|
9585
|
+
return {
|
|
9586
|
+
isMeta: false,
|
|
9587
|
+
retryCount: 3,
|
|
9588
|
+
databaseType: "postgres",
|
|
9589
|
+
databaseName: (0, import_lodash_es2.snakeCase)(name),
|
|
9590
|
+
poolSize: readIntegerEnv("DATABASE_POOL_SIZE", 10),
|
|
9591
|
+
ownerServiceName: options.ownerServiceName ?? this.serviceRegistry?.serviceName ?? null,
|
|
9592
|
+
...options
|
|
9593
|
+
};
|
|
9594
|
+
}
|
|
9595
|
+
static normalizeDatabaseServiceOptions(name, options = {}) {
|
|
9596
|
+
return {
|
|
9597
|
+
loadBalance: true,
|
|
9598
|
+
useSocket: true,
|
|
9599
|
+
displayName: void 0,
|
|
9600
|
+
isMeta: false,
|
|
9601
|
+
port: readIntegerEnv("HTTP_PORT", 3e3),
|
|
9602
|
+
securityProfile: readStringEnv("SECURITY_PROFILE") ?? "medium",
|
|
9603
|
+
networkMode: readStringEnv("NETWORK_MODE") ?? "dev",
|
|
9604
|
+
retryCount: 3,
|
|
9605
|
+
cadenzaDB: {
|
|
9606
|
+
connect: true
|
|
9607
|
+
},
|
|
9608
|
+
databaseType: "postgres",
|
|
9609
|
+
databaseName: (0, import_lodash_es2.snakeCase)(name),
|
|
9610
|
+
poolSize: readIntegerEnv("DATABASE_POOL_SIZE", 10),
|
|
9611
|
+
isDatabase: true,
|
|
9612
|
+
ownerServiceName: options.ownerServiceName ?? name,
|
|
9613
|
+
...options
|
|
9614
|
+
};
|
|
9615
|
+
}
|
|
9616
|
+
static registerDatabaseServiceBridgeTask(serviceName, description, schema, isMeta, actorName) {
|
|
9617
|
+
const taskName = `Insert database service bridge ${serviceName}`;
|
|
9618
|
+
if (this.get(taskName)) {
|
|
9619
|
+
return;
|
|
9620
|
+
}
|
|
9621
|
+
this.createMetaTask(
|
|
9622
|
+
taskName,
|
|
9623
|
+
(ctx, emit) => {
|
|
9624
|
+
if (ctx.__serviceName && ctx.__serviceName !== serviceName) {
|
|
9625
|
+
return false;
|
|
9626
|
+
}
|
|
9627
|
+
emit("global.meta.created_database_service", {
|
|
9628
|
+
data: {
|
|
9629
|
+
service_name: serviceName,
|
|
9630
|
+
description,
|
|
9631
|
+
schema,
|
|
9632
|
+
is_meta: isMeta
|
|
9633
|
+
}
|
|
9634
|
+
});
|
|
9635
|
+
this.log("Database service created", {
|
|
9636
|
+
name: serviceName,
|
|
9637
|
+
isMeta,
|
|
9638
|
+
actorName
|
|
9639
|
+
});
|
|
9640
|
+
return true;
|
|
9641
|
+
},
|
|
9642
|
+
"Bridges database service creation into the global metadata signal."
|
|
9643
|
+
).doOn("meta.service_registry.service_inserted");
|
|
8711
9644
|
}
|
|
8712
9645
|
static createActor(spec, options = {}) {
|
|
8713
9646
|
this.bootstrap();
|
|
@@ -9060,14 +9993,14 @@ var CadenzaService = class {
|
|
|
9060
9993
|
return import_core4.default.createEphemeralTask(name, func, description, options);
|
|
9061
9994
|
}
|
|
9062
9995
|
/**
|
|
9063
|
-
* Creates an ephemeral meta
|
|
9996
|
+
* Creates an ephemeral meta-task with the specified name, function, description, and options.
|
|
9064
9997
|
* See {@link createEphemeralTask} and {@link createMetaTask} for more details.
|
|
9065
9998
|
*
|
|
9066
9999
|
* @param {string} name - The name of the task to be created.
|
|
9067
10000
|
* @param {TaskFunction} func - The function to be executed as part of the task.
|
|
9068
10001
|
* @param {string} [description] - An optional description of the task.
|
|
9069
10002
|
* @param {TaskOptions & EphemeralTaskOptions} [options={}] - Additional options for configuring the task.
|
|
9070
|
-
* @return {EphemeralTask} The created ephemeral meta
|
|
10003
|
+
* @return {EphemeralTask} The created ephemeral meta-task.
|
|
9071
10004
|
*/
|
|
9072
10005
|
static createEphemeralMetaTask(name, func, description, options = {}) {
|
|
9073
10006
|
this.bootstrap();
|
|
@@ -9122,19 +10055,291 @@ var CadenzaService = class {
|
|
|
9122
10055
|
}
|
|
9123
10056
|
static reset() {
|
|
9124
10057
|
import_core4.default.reset();
|
|
9125
|
-
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;
|
|
9126
10064
|
}
|
|
9127
10065
|
};
|
|
9128
10066
|
CadenzaService.isBootstrapped = false;
|
|
9129
10067
|
CadenzaService.serviceCreated = false;
|
|
9130
10068
|
CadenzaService.warnedInvalidMetaIntentResponderKeys = /* @__PURE__ */ new Set();
|
|
10069
|
+
CadenzaService.hydratedInquiryResults = /* @__PURE__ */ new Map();
|
|
10070
|
+
CadenzaService.frontendSyncScheduled = false;
|
|
9131
10071
|
|
|
9132
10072
|
// src/index.ts
|
|
9133
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
|
|
9134
10338
|
var index_default = CadenzaService;
|
|
9135
10339
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9136
10340
|
0 && (module.exports = {
|
|
9137
10341
|
Actor,
|
|
10342
|
+
DatabaseController,
|
|
9138
10343
|
DatabaseTask,
|
|
9139
10344
|
DebounceTask,
|
|
9140
10345
|
DeputyTask,
|
|
@@ -9146,6 +10351,7 @@ var index_default = CadenzaService;
|
|
|
9146
10351
|
SignalController,
|
|
9147
10352
|
SignalTransmissionTask,
|
|
9148
10353
|
SocketController,
|
|
9149
|
-
Task
|
|
10354
|
+
Task,
|
|
10355
|
+
createSSRInquiryBridge
|
|
9150
10356
|
});
|
|
9151
10357
|
//# sourceMappingURL=index.js.map
|