@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.mjs
CHANGED
|
@@ -38,7 +38,7 @@ var DeputyTask = class extends Task {
|
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
if (context.__metadata.__skipRemoteExecution) {
|
|
41
|
-
resolve(
|
|
41
|
+
resolve(context);
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
const processId = uuid();
|
|
@@ -141,6 +141,8 @@ var DeputyTask = class extends Task {
|
|
|
141
141
|
__executionTraceId: metadata.__executionTraceId ?? null,
|
|
142
142
|
__metadata: {
|
|
143
143
|
...metadata,
|
|
144
|
+
__skipRemoteExecution: metadata.__skipRemoteExecution ?? ctx.__skipRemoteExecution ?? false,
|
|
145
|
+
__blockRemoteExecution: metadata.__blockRemoteExecution ?? ctx.__blockRemoteExecution ?? false,
|
|
144
146
|
__deputyTaskName: this.name
|
|
145
147
|
},
|
|
146
148
|
...ctx
|
|
@@ -219,6 +221,7 @@ var DatabaseTask = class extends DeputyTask {
|
|
|
219
221
|
const dynamicQueryData = ctx.queryData ?? {};
|
|
220
222
|
delete ctx.queryData;
|
|
221
223
|
const deputyContext = {
|
|
224
|
+
...ctx,
|
|
222
225
|
__localTaskName: this.name,
|
|
223
226
|
__localTaskVersion: this.version,
|
|
224
227
|
__localServiceName: CadenzaService.serviceRegistry.serviceName,
|
|
@@ -229,6 +232,8 @@ var DatabaseTask = class extends DeputyTask {
|
|
|
229
232
|
__localRoutineExecId: metadata.__routineExecId ?? metadata.__metadata?.__routineExecId,
|
|
230
233
|
__metadata: {
|
|
231
234
|
...metadata,
|
|
235
|
+
__skipRemoteExecution: metadata.__skipRemoteExecution ?? ctx.__skipRemoteExecution ?? false,
|
|
236
|
+
__blockRemoteExecution: metadata.__blockRemoteExecution ?? ctx.__blockRemoteExecution ?? false,
|
|
232
237
|
__deputyTaskName: this.name
|
|
233
238
|
},
|
|
234
239
|
queryData: {
|
|
@@ -315,6 +320,167 @@ function summarizeResponderStatuses(statuses) {
|
|
|
315
320
|
return { responded, failed, timedOut, pending };
|
|
316
321
|
}
|
|
317
322
|
|
|
323
|
+
// src/utils/transport.ts
|
|
324
|
+
var DEFAULT_PROTOCOLS = ["rest", "socket"];
|
|
325
|
+
function normalizeString(value) {
|
|
326
|
+
return typeof value === "string" ? value.trim() : "";
|
|
327
|
+
}
|
|
328
|
+
function normalizeTransportProtocols(value) {
|
|
329
|
+
const rawValues = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : [];
|
|
330
|
+
const normalized = rawValues.map((entry) => normalizeString(entry)).filter(
|
|
331
|
+
(entry) => entry === "rest" || entry === "socket"
|
|
332
|
+
);
|
|
333
|
+
return Array.from(new Set(normalized));
|
|
334
|
+
}
|
|
335
|
+
function normalizeTransportOrigin(origin) {
|
|
336
|
+
const raw = normalizeString(origin);
|
|
337
|
+
if (!raw) {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
let parsed;
|
|
341
|
+
try {
|
|
342
|
+
parsed = new URL(raw);
|
|
343
|
+
} catch {
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
if (parsed.pathname && parsed.pathname !== "/") {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
if (parsed.search || parsed.hash) {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
return parsed.origin;
|
|
356
|
+
}
|
|
357
|
+
function normalizeSecurityProfile(value) {
|
|
358
|
+
const normalized = normalizeString(value);
|
|
359
|
+
if (normalized === "low" || normalized === "medium" || normalized === "high") {
|
|
360
|
+
return normalized;
|
|
361
|
+
}
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
function normalizeServiceTransportConfig(value) {
|
|
365
|
+
const raw = value ?? {};
|
|
366
|
+
const role = normalizeString(raw.role);
|
|
367
|
+
const origin = normalizeTransportOrigin(raw.origin);
|
|
368
|
+
const protocols = normalizeTransportProtocols(raw.protocols);
|
|
369
|
+
if (!origin) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
if (role !== "internal" && role !== "public") {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
return {
|
|
376
|
+
role,
|
|
377
|
+
origin,
|
|
378
|
+
protocols: protocols.length > 0 ? protocols : [...DEFAULT_PROTOCOLS],
|
|
379
|
+
securityProfile: normalizeSecurityProfile(raw.securityProfile),
|
|
380
|
+
authStrategy: normalizeString(raw.authStrategy) || null
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function normalizeServiceTransportDescriptor(value) {
|
|
384
|
+
const raw = value ?? {};
|
|
385
|
+
const uuid5 = normalizeString(raw.uuid);
|
|
386
|
+
const serviceInstanceId = normalizeString(
|
|
387
|
+
raw.serviceInstanceId ?? raw.service_instance_id
|
|
388
|
+
);
|
|
389
|
+
const config = normalizeServiceTransportConfig(raw);
|
|
390
|
+
if (!uuid5 || !serviceInstanceId || !config) {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
uuid: uuid5,
|
|
395
|
+
serviceInstanceId,
|
|
396
|
+
role: config.role,
|
|
397
|
+
origin: config.origin,
|
|
398
|
+
protocols: config.protocols ?? [...DEFAULT_PROTOCOLS],
|
|
399
|
+
securityProfile: config.securityProfile ?? null,
|
|
400
|
+
authStrategy: config.authStrategy ?? null,
|
|
401
|
+
deleted: Boolean(raw.deleted),
|
|
402
|
+
clientCreated: Boolean(raw.clientCreated ?? raw.client_created ?? false)
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
function transportSupportsProtocol(transport, protocol) {
|
|
406
|
+
return !!transport && transport.protocols.includes(protocol);
|
|
407
|
+
}
|
|
408
|
+
function selectTransportForRole(transports, role, protocol) {
|
|
409
|
+
const filtered = transports.filter(
|
|
410
|
+
(transport) => !transport.deleted && transport.role === role && (!protocol || transportSupportsProtocol(transport, protocol))
|
|
411
|
+
);
|
|
412
|
+
return filtered[0];
|
|
413
|
+
}
|
|
414
|
+
function buildTransportClientKey(transport) {
|
|
415
|
+
return transport.uuid;
|
|
416
|
+
}
|
|
417
|
+
function parseTransportOrigin(origin) {
|
|
418
|
+
const normalized = normalizeTransportOrigin(origin);
|
|
419
|
+
if (!normalized) {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
const parsed = new URL(normalized);
|
|
423
|
+
const protocol = parsed.protocol === "https:" ? "https" : "http";
|
|
424
|
+
const port = parsed.port ? Number(parsed.port) : protocol === "https" ? 443 : 80;
|
|
425
|
+
return {
|
|
426
|
+
protocol,
|
|
427
|
+
hostname: parsed.hostname,
|
|
428
|
+
port
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// src/utils/serviceInstance.ts
|
|
433
|
+
function normalizeString2(value) {
|
|
434
|
+
return typeof value === "string" ? value.trim() : "";
|
|
435
|
+
}
|
|
436
|
+
function normalizeTransportArray(value, serviceInstanceId) {
|
|
437
|
+
if (!Array.isArray(value)) {
|
|
438
|
+
return [];
|
|
439
|
+
}
|
|
440
|
+
return value.map(
|
|
441
|
+
(entry) => normalizeServiceTransportDescriptor({
|
|
442
|
+
...entry ?? {},
|
|
443
|
+
service_instance_id: entry?.service_instance_id ?? entry?.serviceInstanceId ?? serviceInstanceId
|
|
444
|
+
})
|
|
445
|
+
).filter((transport) => !!transport).sort((left, right) => left.origin.localeCompare(right.origin));
|
|
446
|
+
}
|
|
447
|
+
function normalizeServiceInstanceDescriptor(value) {
|
|
448
|
+
const raw = value ?? {};
|
|
449
|
+
const uuid5 = normalizeString2(raw.uuid);
|
|
450
|
+
const serviceName = normalizeString2(raw.serviceName ?? raw.service_name);
|
|
451
|
+
if (!uuid5 || !serviceName) {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
const transports = normalizeTransportArray(raw.transports, uuid5);
|
|
455
|
+
return {
|
|
456
|
+
uuid: uuid5,
|
|
457
|
+
serviceName,
|
|
458
|
+
numberOfRunningGraphs: Math.max(
|
|
459
|
+
0,
|
|
460
|
+
Math.trunc(
|
|
461
|
+
Number(raw.numberOfRunningGraphs ?? raw.number_of_running_graphs ?? 0) || 0
|
|
462
|
+
)
|
|
463
|
+
),
|
|
464
|
+
isPrimary: Boolean(raw.isPrimary ?? raw.is_primary ?? false),
|
|
465
|
+
isActive: Boolean(raw.isActive ?? raw.is_active ?? true),
|
|
466
|
+
isNonResponsive: Boolean(
|
|
467
|
+
raw.isNonResponsive ?? raw.is_non_responsive ?? false
|
|
468
|
+
),
|
|
469
|
+
isBlocked: Boolean(raw.isBlocked ?? raw.is_blocked ?? false),
|
|
470
|
+
runtimeState: raw.runtimeState === "healthy" || raw.runtimeState === "degraded" || raw.runtimeState === "overloaded" || raw.runtimeState === "unavailable" ? raw.runtimeState : void 0,
|
|
471
|
+
acceptingWork: typeof raw.acceptingWork === "boolean" ? raw.acceptingWork : void 0,
|
|
472
|
+
reportedAt: typeof raw.reportedAt === "string" ? raw.reportedAt : typeof raw.reported_at === "string" ? raw.reported_at : void 0,
|
|
473
|
+
health: raw.health ?? {},
|
|
474
|
+
isFrontend: Boolean(raw.isFrontend ?? raw.is_frontend ?? false),
|
|
475
|
+
isDatabase: Boolean(raw.isDatabase ?? raw.is_database ?? false),
|
|
476
|
+
transports,
|
|
477
|
+
clientCreatedTransportIds: Array.isArray(raw.clientCreatedTransportIds) ? raw.clientCreatedTransportIds.map((entry) => normalizeString2(entry)).filter((entry) => entry.length > 0) : void 0
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
function getRouteableTransport(instance, role, protocol) {
|
|
481
|
+
return selectTransportForRole(instance.transports ?? [], role, protocol);
|
|
482
|
+
}
|
|
483
|
+
|
|
318
484
|
// src/utils/readiness.ts
|
|
319
485
|
function evaluateDependencyReadiness(input) {
|
|
320
486
|
const missedHeartbeats = Math.max(
|
|
@@ -561,6 +727,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
561
727
|
this.numberOfRunningGraphs = 0;
|
|
562
728
|
this.useSocket = false;
|
|
563
729
|
this.retryCount = 3;
|
|
730
|
+
this.isFrontend = false;
|
|
564
731
|
CadenzaService.defineIntent({
|
|
565
732
|
name: META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT,
|
|
566
733
|
description: "Gather transport diagnostics across all services and communication clients.",
|
|
@@ -708,57 +875,60 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
708
875
|
this.handleInstanceUpdateTask = CadenzaService.createMetaTask(
|
|
709
876
|
"Handle Instance Update",
|
|
710
877
|
(ctx, emit) => {
|
|
711
|
-
const serviceInstance =
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
if (!serviceInstance
|
|
878
|
+
const serviceInstance = normalizeServiceInstanceDescriptor(
|
|
879
|
+
ctx.serviceInstance ?? ctx.data ?? ctx.queryData?.data ?? (ctx.__serviceInstanceId || ctx.serviceInstanceId ? {
|
|
880
|
+
uuid: ctx.__serviceInstanceId ?? ctx.serviceInstanceId,
|
|
881
|
+
serviceName: ctx.__serviceName ?? ctx.serviceName,
|
|
882
|
+
isFrontend: !!ctx.isFrontend,
|
|
883
|
+
isActive: typeof ctx.isActive === "boolean" ? ctx.isActive : typeof ctx.__active === "boolean" ? ctx.__active : true,
|
|
884
|
+
isNonResponsive: !!ctx.isNonResponsive,
|
|
885
|
+
isBlocked: !!ctx.isBlocked,
|
|
886
|
+
health: ctx.health ?? ctx.__health ?? {},
|
|
887
|
+
numberOfRunningGraphs: ctx.numberOfRunningGraphs ?? ctx.__numberOfRunningGraphs ?? 0,
|
|
888
|
+
isPrimary: false,
|
|
889
|
+
transports: ctx.transports ?? []
|
|
890
|
+
} : void 0)
|
|
891
|
+
);
|
|
892
|
+
if (!serviceInstance) {
|
|
726
893
|
return false;
|
|
727
894
|
}
|
|
728
|
-
const
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
isFrontend,
|
|
735
|
-
deleted
|
|
736
|
-
} = serviceInstance;
|
|
737
|
-
if (uuid4 === this.serviceInstanceId) return;
|
|
895
|
+
const uuid5 = serviceInstance.uuid;
|
|
896
|
+
const serviceName = serviceInstance.serviceName;
|
|
897
|
+
const deleted = Boolean(
|
|
898
|
+
ctx.deleted ?? ctx.serviceInstance?.deleted ?? ctx.data?.deleted
|
|
899
|
+
);
|
|
900
|
+
if (uuid5 === this.serviceInstanceId) return;
|
|
738
901
|
if (deleted) {
|
|
739
|
-
const
|
|
740
|
-
|
|
902
|
+
const existingInstance = this.instances.get(serviceName)?.find((instance) => instance.uuid === uuid5);
|
|
903
|
+
const indexToDelete = this.instances.get(serviceName)?.findIndex((i) => i.uuid === uuid5) ?? -1;
|
|
904
|
+
if (indexToDelete >= 0 && existingInstance) {
|
|
741
905
|
this.instances.get(serviceName)?.splice(indexToDelete, 1);
|
|
906
|
+
for (const transport of existingInstance.transports) {
|
|
907
|
+
const transportKey = buildTransportClientKey(transport);
|
|
908
|
+
emit(`meta.socket_shutdown_requested:${transportKey}`, {});
|
|
909
|
+
emit(`meta.fetch.destroy_requested:${transportKey}`, {});
|
|
910
|
+
}
|
|
742
911
|
}
|
|
743
912
|
if (this.instances.get(serviceName)?.length === 0) {
|
|
744
913
|
this.instances.delete(serviceName);
|
|
745
|
-
} else if (this.instances.get(serviceName)?.filter((i) => i.address === address && i.port === port).length === 0) {
|
|
746
|
-
emit(`meta.socket_shutdown_requested:${address}_${port}`, {});
|
|
747
|
-
emit(`meta.fetch.destroy_requested:${address}_${port}`, {});
|
|
748
914
|
}
|
|
749
|
-
this.unregisterDependee(
|
|
915
|
+
this.unregisterDependee(uuid5, serviceName);
|
|
750
916
|
return;
|
|
751
917
|
}
|
|
752
918
|
if (!this.instances.has(serviceName))
|
|
753
919
|
this.instances.set(serviceName, []);
|
|
754
920
|
const instances = this.instances.get(serviceName);
|
|
755
|
-
const existing = instances.find((i) => i.uuid ===
|
|
921
|
+
const existing = instances.find((i) => i.uuid === uuid5);
|
|
756
922
|
if (existing) {
|
|
757
|
-
Object.assign(existing,
|
|
923
|
+
Object.assign(existing, {
|
|
924
|
+
...serviceInstance,
|
|
925
|
+
transports: serviceInstance.transports.length > 0 ? serviceInstance.transports : existing.transports,
|
|
926
|
+
clientCreatedTransportIds: existing.clientCreatedTransportIds ?? []
|
|
927
|
+
});
|
|
758
928
|
} else {
|
|
759
929
|
instances.push(serviceInstance);
|
|
760
930
|
}
|
|
761
|
-
const trackedInstance = existing ?? instances.find((instance) => instance.uuid ===
|
|
931
|
+
const trackedInstance = existing ?? instances.find((instance) => instance.uuid === uuid5);
|
|
762
932
|
if (trackedInstance) {
|
|
763
933
|
const snapshot = this.resolveRuntimeStatusSnapshot(
|
|
764
934
|
trackedInstance.numberOfRunningGraphs ?? 0,
|
|
@@ -773,31 +943,44 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
773
943
|
if (this.serviceName === serviceName) {
|
|
774
944
|
return false;
|
|
775
945
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
946
|
+
const trackedTransport = this.getRouteableTransport(
|
|
947
|
+
trackedInstance,
|
|
948
|
+
this.useSocket ? "socket" : "rest"
|
|
949
|
+
);
|
|
950
|
+
if (!serviceInstance.isFrontend && (this.deputies.has(serviceName) || this.remoteIntents.has(serviceName)) || this.remoteSignals.has(serviceName)) {
|
|
951
|
+
const communicationTypes = Array.from(
|
|
952
|
+
new Set(
|
|
953
|
+
this.deputies.get(serviceName)?.map((d) => d.communicationType) ?? []
|
|
954
|
+
)
|
|
779
955
|
);
|
|
780
|
-
if (!
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
956
|
+
if (!communicationTypes.includes("signal") && this.remoteSignals.has(serviceName)) {
|
|
957
|
+
communicationTypes.push("signal");
|
|
958
|
+
}
|
|
959
|
+
if (trackedTransport) {
|
|
960
|
+
const clientCreated = this.hasTransportClientCreated(
|
|
961
|
+
trackedInstance,
|
|
962
|
+
trackedTransport.uuid
|
|
785
963
|
);
|
|
786
|
-
if (!
|
|
787
|
-
|
|
964
|
+
if (!clientCreated) {
|
|
965
|
+
emit("meta.service_registry.dependee_registered", {
|
|
966
|
+
serviceName,
|
|
967
|
+
serviceInstanceId: uuid5,
|
|
968
|
+
serviceTransportId: trackedTransport.uuid,
|
|
969
|
+
serviceOrigin: trackedTransport.origin,
|
|
970
|
+
transportProtocols: trackedTransport.protocols,
|
|
971
|
+
communicationTypes
|
|
972
|
+
});
|
|
973
|
+
this.markTransportClientCreated(
|
|
974
|
+
trackedInstance,
|
|
975
|
+
trackedTransport.uuid
|
|
976
|
+
);
|
|
788
977
|
}
|
|
789
|
-
|
|
978
|
+
} else {
|
|
979
|
+
emit("meta.service_registry.routeable_transport_missing", {
|
|
790
980
|
serviceName,
|
|
791
|
-
serviceInstanceId:
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
protocol: exposed ? "https" : "http",
|
|
795
|
-
communicationTypes
|
|
796
|
-
});
|
|
797
|
-
instances?.filter(
|
|
798
|
-
(i) => i.address === address && i.port === port && i.isActive
|
|
799
|
-
).forEach((i) => {
|
|
800
|
-
i.clientCreated = true;
|
|
981
|
+
serviceInstanceId: uuid5,
|
|
982
|
+
requiredRole: this.getRoutingTransportRole(),
|
|
983
|
+
isFrontend: this.isFrontend
|
|
801
984
|
});
|
|
802
985
|
}
|
|
803
986
|
}
|
|
@@ -815,6 +998,81 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
815
998
|
"meta.socket_shutdown_requested",
|
|
816
999
|
"meta.fetch.destroy_requested"
|
|
817
1000
|
);
|
|
1001
|
+
this.handleTransportUpdateTask = CadenzaService.createMetaTask(
|
|
1002
|
+
"Handle Transport Update",
|
|
1003
|
+
(ctx, emit) => {
|
|
1004
|
+
const transport = normalizeServiceTransportDescriptor(
|
|
1005
|
+
ctx.serviceTransport ?? ctx.data ?? ctx.queryData?.data ?? ctx
|
|
1006
|
+
);
|
|
1007
|
+
if (!transport) {
|
|
1008
|
+
return false;
|
|
1009
|
+
}
|
|
1010
|
+
let ownerInstance;
|
|
1011
|
+
for (const instances of this.instances.values()) {
|
|
1012
|
+
ownerInstance = instances.find(
|
|
1013
|
+
(instance) => instance.uuid === transport.serviceInstanceId
|
|
1014
|
+
);
|
|
1015
|
+
if (ownerInstance) {
|
|
1016
|
+
break;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
if (!ownerInstance) {
|
|
1020
|
+
return false;
|
|
1021
|
+
}
|
|
1022
|
+
if (transport.deleted) {
|
|
1023
|
+
ownerInstance.transports = ownerInstance.transports.filter(
|
|
1024
|
+
(existingTransport2) => existingTransport2.uuid !== transport.uuid
|
|
1025
|
+
);
|
|
1026
|
+
const transportKey = buildTransportClientKey(transport);
|
|
1027
|
+
emit(`meta.socket_shutdown_requested:${transportKey}`, {});
|
|
1028
|
+
emit(`meta.fetch.destroy_requested:${transportKey}`, {});
|
|
1029
|
+
return true;
|
|
1030
|
+
}
|
|
1031
|
+
const existingTransport = this.getTransportById(ownerInstance, transport.uuid);
|
|
1032
|
+
if (existingTransport) {
|
|
1033
|
+
Object.assign(existingTransport, transport);
|
|
1034
|
+
} else {
|
|
1035
|
+
ownerInstance.transports.push(transport);
|
|
1036
|
+
}
|
|
1037
|
+
if (ownerInstance.uuid === this.serviceInstanceId) {
|
|
1038
|
+
return true;
|
|
1039
|
+
}
|
|
1040
|
+
const hasRemoteInterest = (!ownerInstance.isFrontend && (this.deputies.has(ownerInstance.serviceName) || this.remoteIntents.has(ownerInstance.serviceName)) || this.remoteSignals.has(ownerInstance.serviceName)) && transport.role === this.getRoutingTransportRole();
|
|
1041
|
+
if (!hasRemoteInterest) {
|
|
1042
|
+
return true;
|
|
1043
|
+
}
|
|
1044
|
+
if (!this.hasTransportClientCreated(ownerInstance, transport.uuid)) {
|
|
1045
|
+
const communicationTypes = Array.from(
|
|
1046
|
+
new Set(
|
|
1047
|
+
this.deputies.get(ownerInstance.serviceName)?.map((descriptor) => descriptor.communicationType) ?? []
|
|
1048
|
+
)
|
|
1049
|
+
);
|
|
1050
|
+
if (!communicationTypes.includes("signal") && this.remoteSignals.has(ownerInstance.serviceName)) {
|
|
1051
|
+
communicationTypes.push("signal");
|
|
1052
|
+
}
|
|
1053
|
+
emit("meta.service_registry.dependee_registered", {
|
|
1054
|
+
serviceName: ownerInstance.serviceName,
|
|
1055
|
+
serviceInstanceId: ownerInstance.uuid,
|
|
1056
|
+
serviceTransportId: transport.uuid,
|
|
1057
|
+
serviceOrigin: transport.origin,
|
|
1058
|
+
transportProtocols: transport.protocols,
|
|
1059
|
+
communicationTypes
|
|
1060
|
+
});
|
|
1061
|
+
this.markTransportClientCreated(ownerInstance, transport.uuid);
|
|
1062
|
+
}
|
|
1063
|
+
return true;
|
|
1064
|
+
},
|
|
1065
|
+
"Handles service transport updates independently from instance rows."
|
|
1066
|
+
).doOn(
|
|
1067
|
+
"global.meta.service_instance_transport.inserted",
|
|
1068
|
+
"global.meta.service_instance_transport.updated",
|
|
1069
|
+
"meta.service_instance_transport.inserted",
|
|
1070
|
+
"meta.service_instance_transport.updated"
|
|
1071
|
+
).attachSignal(
|
|
1072
|
+
"meta.service_registry.dependee_registered",
|
|
1073
|
+
"meta.socket_shutdown_requested",
|
|
1074
|
+
"meta.fetch.destroy_requested"
|
|
1075
|
+
);
|
|
818
1076
|
CadenzaService.createMetaTask(
|
|
819
1077
|
"Track dependee registration",
|
|
820
1078
|
(ctx) => {
|
|
@@ -910,17 +1168,25 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
910
1168
|
this.handleServiceNotRespondingTask = CadenzaService.createMetaTask(
|
|
911
1169
|
"Handle service not responding",
|
|
912
1170
|
(ctx, emit) => {
|
|
913
|
-
const { serviceName,
|
|
1171
|
+
const { serviceName, serviceInstanceId, serviceTransportId } = ctx;
|
|
914
1172
|
const serviceInstances = this.instances.get(serviceName);
|
|
915
|
-
const instances = serviceInstances?.filter(
|
|
916
|
-
(
|
|
917
|
-
|
|
1173
|
+
const instances = serviceInstances?.filter((instance) => {
|
|
1174
|
+
if (serviceInstanceId && instance.uuid === serviceInstanceId) {
|
|
1175
|
+
return true;
|
|
1176
|
+
}
|
|
1177
|
+
if (serviceTransportId) {
|
|
1178
|
+
return instance.transports.some(
|
|
1179
|
+
(transport) => transport.uuid === serviceTransportId
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1182
|
+
return false;
|
|
1183
|
+
});
|
|
918
1184
|
CadenzaService.log(
|
|
919
1185
|
"Service not responding.",
|
|
920
1186
|
{
|
|
921
1187
|
serviceName,
|
|
922
|
-
|
|
923
|
-
|
|
1188
|
+
serviceInstanceId,
|
|
1189
|
+
serviceTransportId,
|
|
924
1190
|
instances
|
|
925
1191
|
},
|
|
926
1192
|
"warning",
|
|
@@ -961,7 +1227,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
961
1227
|
this.handleServiceHandshakeTask = CadenzaService.createMetaTask(
|
|
962
1228
|
"Handle service handshake",
|
|
963
1229
|
(ctx, emit) => {
|
|
964
|
-
const { serviceName, serviceInstanceId
|
|
1230
|
+
const { serviceName, serviceInstanceId } = ctx;
|
|
965
1231
|
const serviceInstances = this.instances.get(serviceName);
|
|
966
1232
|
const instance = serviceInstances?.find(
|
|
967
1233
|
(i) => i.uuid === serviceInstanceId
|
|
@@ -989,26 +1255,6 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
989
1255
|
uuid: instance.uuid
|
|
990
1256
|
}
|
|
991
1257
|
});
|
|
992
|
-
const instancesToDelete = serviceInstances?.filter(
|
|
993
|
-
(i) => i.uuid !== serviceInstanceId && i.address === serviceAddress && i.port === servicePort
|
|
994
|
-
);
|
|
995
|
-
for (const i of instancesToDelete ?? []) {
|
|
996
|
-
const indexToDelete = this.instances.get(serviceName)?.indexOf(i) ?? -1;
|
|
997
|
-
if (indexToDelete >= 0) {
|
|
998
|
-
this.instances.get(serviceName)?.splice(indexToDelete, 1);
|
|
999
|
-
}
|
|
1000
|
-
this.unregisterDependee(i.uuid, serviceName);
|
|
1001
|
-
emit("global.meta.service_registry.deleted", {
|
|
1002
|
-
data: {
|
|
1003
|
-
isActive: false,
|
|
1004
|
-
isNonResponsive: false,
|
|
1005
|
-
deleted: true
|
|
1006
|
-
},
|
|
1007
|
-
filter: {
|
|
1008
|
-
uuid: i.uuid
|
|
1009
|
-
}
|
|
1010
|
-
});
|
|
1011
|
-
}
|
|
1012
1258
|
return true;
|
|
1013
1259
|
},
|
|
1014
1260
|
"Handles service handshake"
|
|
@@ -1027,16 +1273,13 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1027
1273
|
return false;
|
|
1028
1274
|
}
|
|
1029
1275
|
let applied = this.applyRuntimeStatusReport(report);
|
|
1030
|
-
if (!applied && report.
|
|
1276
|
+
if (!applied && report.transportId && report.transportOrigin) {
|
|
1031
1277
|
if (!this.instances.has(report.serviceName)) {
|
|
1032
1278
|
this.instances.set(report.serviceName, []);
|
|
1033
1279
|
}
|
|
1034
1280
|
this.instances.get(report.serviceName).push({
|
|
1035
1281
|
uuid: report.serviceInstanceId,
|
|
1036
1282
|
serviceName: report.serviceName,
|
|
1037
|
-
address: report.serviceAddress,
|
|
1038
|
-
port: report.servicePort,
|
|
1039
|
-
exposed: !!report.exposed,
|
|
1040
1283
|
isFrontend: !!report.isFrontend,
|
|
1041
1284
|
isActive: report.isActive,
|
|
1042
1285
|
isNonResponsive: report.isNonResponsive,
|
|
@@ -1046,7 +1289,18 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1046
1289
|
acceptingWork: report.acceptingWork,
|
|
1047
1290
|
reportedAt: report.reportedAt,
|
|
1048
1291
|
health: report.health ?? {},
|
|
1049
|
-
isPrimary: false
|
|
1292
|
+
isPrimary: false,
|
|
1293
|
+
transports: [
|
|
1294
|
+
{
|
|
1295
|
+
uuid: report.transportId,
|
|
1296
|
+
serviceInstanceId: report.serviceInstanceId,
|
|
1297
|
+
role: this.getRoutingTransportRole(),
|
|
1298
|
+
origin: report.transportOrigin,
|
|
1299
|
+
protocols: report.transportProtocols && report.transportProtocols.length > 0 ? report.transportProtocols : ["rest", "socket"],
|
|
1300
|
+
securityProfile: null,
|
|
1301
|
+
authStrategy: null
|
|
1302
|
+
}
|
|
1303
|
+
]
|
|
1050
1304
|
});
|
|
1051
1305
|
applied = true;
|
|
1052
1306
|
}
|
|
@@ -1087,21 +1341,9 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1087
1341
|
deleted: !!m.deleted
|
|
1088
1342
|
})
|
|
1089
1343
|
);
|
|
1090
|
-
const serviceInstances = (inquiryResult.serviceInstances ?? []).filter(
|
|
1091
|
-
(instance) =>
|
|
1092
|
-
)
|
|
1093
|
-
uuid: instance.uuid,
|
|
1094
|
-
address: instance.address,
|
|
1095
|
-
port: instance.port,
|
|
1096
|
-
serviceName: instance.serviceName,
|
|
1097
|
-
isActive: !!instance.isActive,
|
|
1098
|
-
isNonResponsive: !!instance.isNonResponsive,
|
|
1099
|
-
isBlocked: !!instance.isBlocked,
|
|
1100
|
-
health: instance.health ?? {},
|
|
1101
|
-
exposed: !!instance.exposed,
|
|
1102
|
-
created: instance.created,
|
|
1103
|
-
isFrontend: !!instance.isFrontend
|
|
1104
|
-
}));
|
|
1344
|
+
const serviceInstances = (inquiryResult.serviceInstances ?? []).map((instance) => normalizeServiceInstanceDescriptor(instance)).filter(
|
|
1345
|
+
(instance) => !!instance && !!instance.isActive && !instance.isNonResponsive && !instance.isBlocked
|
|
1346
|
+
);
|
|
1105
1347
|
return {
|
|
1106
1348
|
...ctx,
|
|
1107
1349
|
signalToTaskMaps,
|
|
@@ -1188,7 +1430,19 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1188
1430
|
const { __serviceName, __triedInstances, __retries, __broadcast } = context;
|
|
1189
1431
|
let retries = __retries ?? 0;
|
|
1190
1432
|
let triedInstances = __triedInstances ?? [];
|
|
1191
|
-
const
|
|
1433
|
+
const preferredRole = this.getRoutingTransportRole();
|
|
1434
|
+
const instances = this.instances.get(__serviceName)?.filter((instance) => {
|
|
1435
|
+
if (!instance.isActive || instance.isNonResponsive || instance.isBlocked) {
|
|
1436
|
+
return false;
|
|
1437
|
+
}
|
|
1438
|
+
return Boolean(
|
|
1439
|
+
this.getRouteableTransport(
|
|
1440
|
+
instance,
|
|
1441
|
+
this.useSocket ? "socket" : "rest",
|
|
1442
|
+
preferredRole
|
|
1443
|
+
) ?? this.getRouteableTransport(instance, "rest", preferredRole)
|
|
1444
|
+
);
|
|
1445
|
+
}).sort((a, b) => {
|
|
1192
1446
|
const leftStatus = this.resolveRuntimeStatusSnapshot(
|
|
1193
1447
|
a.numberOfRunningGraphs ?? 0,
|
|
1194
1448
|
a.isActive,
|
|
@@ -1209,9 +1463,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1209
1463
|
});
|
|
1210
1464
|
if (!instances || instances.length === 0 || retries > this.retryCount) {
|
|
1211
1465
|
context.errored = true;
|
|
1212
|
-
context.__error = `No
|
|
1213
|
-
__serviceName
|
|
1214
|
-
)}`;
|
|
1466
|
+
context.__error = this.isFrontend && preferredRole === "public" ? `No public transport available for ${__serviceName}.` : `No routeable ${preferredRole} transport available for ${__serviceName}. Retries: ${retries}.`;
|
|
1215
1467
|
emit(
|
|
1216
1468
|
`meta.service_registry.load_balance_failed:${context.__metadata.__deputyExecId}`,
|
|
1217
1469
|
context
|
|
@@ -1220,10 +1472,21 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1220
1472
|
}
|
|
1221
1473
|
if (__broadcast || instances[0].isFrontend) {
|
|
1222
1474
|
for (const instance of instances) {
|
|
1223
|
-
const
|
|
1475
|
+
const selectedTransport2 = this.getRouteableTransport(instance, "socket", preferredRole) ?? this.getRouteableTransport(instance, "rest", preferredRole);
|
|
1476
|
+
if (!selectedTransport2) {
|
|
1477
|
+
continue;
|
|
1478
|
+
}
|
|
1479
|
+
const transportKey = buildTransportClientKey(selectedTransport2);
|
|
1224
1480
|
emit(
|
|
1225
|
-
|
|
1226
|
-
|
|
1481
|
+
`${this.useSocket && transportSupportsProtocol(selectedTransport2, "socket") ? "meta.service_registry.selected_instance_for_socket" : "meta.service_registry.selected_instance_for_fetch"}:${transportKey}`,
|
|
1482
|
+
{
|
|
1483
|
+
...context,
|
|
1484
|
+
__instance: instance.uuid,
|
|
1485
|
+
__transportId: selectedTransport2.uuid,
|
|
1486
|
+
__transportOrigin: selectedTransport2.origin,
|
|
1487
|
+
__transportProtocols: selectedTransport2.protocols,
|
|
1488
|
+
__fetchId: transportKey
|
|
1489
|
+
}
|
|
1227
1490
|
);
|
|
1228
1491
|
}
|
|
1229
1492
|
return context;
|
|
@@ -1246,12 +1509,25 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1246
1509
|
if (retries > 0) {
|
|
1247
1510
|
selected = instancesToTry[Math.floor(Math.random() * instancesToTry.length)];
|
|
1248
1511
|
}
|
|
1512
|
+
const selectedTransport = this.getRouteableTransport(selected, "socket", preferredRole) ?? this.getRouteableTransport(selected, "rest", preferredRole);
|
|
1513
|
+
if (!selectedTransport) {
|
|
1514
|
+
context.errored = true;
|
|
1515
|
+
context.__error = `No routeable ${preferredRole} transport available for ${selected.serviceName}/${selected.uuid}.`;
|
|
1516
|
+
emit(
|
|
1517
|
+
`meta.service_registry.load_balance_failed:${context.__metadata.__deputyExecId}`,
|
|
1518
|
+
context
|
|
1519
|
+
);
|
|
1520
|
+
return context;
|
|
1521
|
+
}
|
|
1249
1522
|
context.__instance = selected.uuid;
|
|
1250
|
-
context.
|
|
1523
|
+
context.__transportId = selectedTransport.uuid;
|
|
1524
|
+
context.__transportOrigin = selectedTransport.origin;
|
|
1525
|
+
context.__transportProtocols = selectedTransport.protocols;
|
|
1526
|
+
context.__fetchId = buildTransportClientKey(selectedTransport);
|
|
1251
1527
|
context.__triedInstances = triedInstances;
|
|
1252
1528
|
context.__triedInstances.push(selected.uuid);
|
|
1253
1529
|
context.__retries = retries;
|
|
1254
|
-
if (this.useSocket) {
|
|
1530
|
+
if (this.useSocket && transportSupportsProtocol(selectedTransport, "socket")) {
|
|
1255
1531
|
emit(
|
|
1256
1532
|
`meta.service_registry.selected_instance_for_socket:${context.__fetchId}`,
|
|
1257
1533
|
context
|
|
@@ -1443,9 +1719,9 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1443
1719
|
__active: report.isActive,
|
|
1444
1720
|
serviceName: report.serviceName,
|
|
1445
1721
|
serviceInstanceId: report.serviceInstanceId,
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1722
|
+
transportId: report.transportId,
|
|
1723
|
+
transportOrigin: report.transportOrigin,
|
|
1724
|
+
transportProtocols: report.transportProtocols,
|
|
1449
1725
|
isFrontend: report.isFrontend,
|
|
1450
1726
|
reportedAt: report.reportedAt,
|
|
1451
1727
|
numberOfRunningGraphs: report.numberOfRunningGraphs,
|
|
@@ -1488,12 +1764,17 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1488
1764
|
continue;
|
|
1489
1765
|
}
|
|
1490
1766
|
this.runtimeStatusFallbackInFlightByInstance.add(serviceInstanceId);
|
|
1767
|
+
const transport = this.getRouteableTransport(
|
|
1768
|
+
instance,
|
|
1769
|
+
this.useSocket ? "socket" : "rest"
|
|
1770
|
+
);
|
|
1491
1771
|
emit("meta.service_registry.runtime_status_fallback_requested", {
|
|
1492
1772
|
...ctx,
|
|
1493
1773
|
serviceName,
|
|
1494
1774
|
serviceInstanceId,
|
|
1495
|
-
|
|
1496
|
-
|
|
1775
|
+
serviceTransportId: transport?.uuid,
|
|
1776
|
+
serviceOrigin: transport?.origin,
|
|
1777
|
+
transportProtocols: transport?.protocols
|
|
1497
1778
|
});
|
|
1498
1779
|
}
|
|
1499
1780
|
}
|
|
@@ -1527,6 +1808,10 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1527
1808
|
};
|
|
1528
1809
|
} catch (error) {
|
|
1529
1810
|
const instance = this.getInstance(serviceName, serviceInstanceId);
|
|
1811
|
+
const transport = instance ? this.getRouteableTransport(
|
|
1812
|
+
instance,
|
|
1813
|
+
this.useSocket ? "socket" : "rest"
|
|
1814
|
+
) : void 0;
|
|
1530
1815
|
const message = error instanceof Error ? error.message : String(error);
|
|
1531
1816
|
CadenzaService.log(
|
|
1532
1817
|
"Runtime status fallback inquiry failed.",
|
|
@@ -1541,8 +1826,9 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1541
1826
|
...ctx,
|
|
1542
1827
|
serviceName,
|
|
1543
1828
|
serviceInstanceId,
|
|
1544
|
-
|
|
1545
|
-
|
|
1829
|
+
serviceTransportId: transport?.uuid ?? ctx.serviceTransportId,
|
|
1830
|
+
serviceOrigin: transport?.origin ?? ctx.serviceOrigin,
|
|
1831
|
+
transportProtocols: transport?.protocols ?? ctx.transportProtocols,
|
|
1546
1832
|
__error: message,
|
|
1547
1833
|
errored: true
|
|
1548
1834
|
});
|
|
@@ -1655,85 +1941,185 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1655
1941
|
inputSchema: {
|
|
1656
1942
|
type: "object",
|
|
1657
1943
|
properties: {
|
|
1658
|
-
|
|
1659
|
-
type: "
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1944
|
+
data: {
|
|
1945
|
+
type: "object",
|
|
1946
|
+
properties: {
|
|
1947
|
+
uuid: {
|
|
1948
|
+
type: "string"
|
|
1949
|
+
},
|
|
1950
|
+
process_pid: {
|
|
1951
|
+
type: "number"
|
|
1952
|
+
},
|
|
1953
|
+
is_primary: {
|
|
1954
|
+
type: "boolean"
|
|
1955
|
+
},
|
|
1956
|
+
service_name: {
|
|
1957
|
+
type: "string"
|
|
1958
|
+
},
|
|
1959
|
+
is_active: {
|
|
1960
|
+
type: "boolean"
|
|
1961
|
+
},
|
|
1962
|
+
is_frontend: {
|
|
1963
|
+
type: "boolean"
|
|
1964
|
+
},
|
|
1965
|
+
is_database: {
|
|
1966
|
+
type: "boolean"
|
|
1967
|
+
},
|
|
1968
|
+
is_non_responsive: {
|
|
1969
|
+
type: "boolean"
|
|
1970
|
+
},
|
|
1971
|
+
is_blocked: {
|
|
1972
|
+
type: "boolean"
|
|
1973
|
+
},
|
|
1974
|
+
health: {
|
|
1975
|
+
type: "object"
|
|
1976
|
+
}
|
|
1977
|
+
},
|
|
1978
|
+
required: ["uuid", "process_pid", "service_name"]
|
|
1687
1979
|
}
|
|
1688
1980
|
},
|
|
1689
|
-
required: [
|
|
1690
|
-
"id",
|
|
1691
|
-
"address",
|
|
1692
|
-
"port",
|
|
1693
|
-
"process_pid",
|
|
1694
|
-
"service_name",
|
|
1695
|
-
"exposed"
|
|
1696
|
-
]
|
|
1981
|
+
required: ["data"]
|
|
1697
1982
|
},
|
|
1698
|
-
// validateInputContext: true,
|
|
1699
1983
|
outputSchema: {
|
|
1700
1984
|
type: "object",
|
|
1701
1985
|
properties: {
|
|
1702
|
-
|
|
1986
|
+
uuid: {
|
|
1703
1987
|
type: "string"
|
|
1704
1988
|
}
|
|
1705
1989
|
},
|
|
1706
|
-
required: ["
|
|
1990
|
+
required: ["uuid"]
|
|
1707
1991
|
},
|
|
1708
|
-
// validateOutputContext: true,
|
|
1709
1992
|
retryCount: 5,
|
|
1710
1993
|
retryDelay: 1e3
|
|
1711
1994
|
}
|
|
1712
|
-
).doOn("
|
|
1995
|
+
).doOn("meta.service_registry.instance_registration_requested").then(
|
|
1713
1996
|
CadenzaService.createMetaTask(
|
|
1714
1997
|
"Setup service",
|
|
1715
1998
|
(ctx) => {
|
|
1716
|
-
const {
|
|
1717
|
-
|
|
1999
|
+
const {
|
|
2000
|
+
serviceInstance,
|
|
2001
|
+
data,
|
|
2002
|
+
queryData,
|
|
2003
|
+
__useSocket,
|
|
2004
|
+
__retryCount,
|
|
2005
|
+
__isFrontend
|
|
2006
|
+
} = ctx;
|
|
2007
|
+
const normalizedLocalInstance = normalizeServiceInstanceDescriptor({
|
|
2008
|
+
...serviceInstance ?? data ?? queryData?.data ?? {},
|
|
2009
|
+
transports: ctx.transportData ?? []
|
|
2010
|
+
});
|
|
2011
|
+
if (!normalizedLocalInstance?.uuid || !normalizedLocalInstance.serviceName) {
|
|
2012
|
+
return false;
|
|
2013
|
+
}
|
|
2014
|
+
this.serviceInstanceId = normalizedLocalInstance.uuid;
|
|
1718
2015
|
this.instances.set(
|
|
1719
|
-
|
|
1720
|
-
[{ ...
|
|
2016
|
+
normalizedLocalInstance.serviceName,
|
|
2017
|
+
[{ ...normalizedLocalInstance }]
|
|
1721
2018
|
);
|
|
1722
2019
|
this.useSocket = __useSocket;
|
|
1723
2020
|
this.retryCount = __retryCount;
|
|
2021
|
+
this.isFrontend = typeof __isFrontend === "boolean" ? __isFrontend : !!normalizedLocalInstance.isFrontend;
|
|
1724
2022
|
console.log("SETUP SERVICE", this.serviceInstanceId);
|
|
1725
2023
|
return true;
|
|
1726
2024
|
},
|
|
1727
2025
|
"Sets service instance id after insertion"
|
|
1728
|
-
).emits("meta.service_registry.instance_inserted")
|
|
2026
|
+
).emits("meta.service_registry.instance_inserted").then(
|
|
2027
|
+
CadenzaService.createMetaTask(
|
|
2028
|
+
"Prepare service transport inserts",
|
|
2029
|
+
function* (ctx, emit) {
|
|
2030
|
+
const transportData = Array.isArray(ctx.transportData) ? ctx.transportData : [];
|
|
2031
|
+
for (const transport of transportData) {
|
|
2032
|
+
const transportContext = {
|
|
2033
|
+
...ctx,
|
|
2034
|
+
data: {
|
|
2035
|
+
...transport,
|
|
2036
|
+
service_instance_id: transport.service_instance_id ?? ctx.__serviceInstanceId
|
|
2037
|
+
}
|
|
2038
|
+
};
|
|
2039
|
+
emit(
|
|
2040
|
+
"meta.service_registry.transport_registration_requested",
|
|
2041
|
+
transportContext
|
|
2042
|
+
);
|
|
2043
|
+
yield transportContext;
|
|
2044
|
+
}
|
|
2045
|
+
},
|
|
2046
|
+
"Splits declared service transports into individual insert payloads."
|
|
2047
|
+
).attachSignal("meta.service_registry.transport_registration_requested")
|
|
2048
|
+
)
|
|
1729
2049
|
);
|
|
2050
|
+
this.insertServiceTransportTask = CadenzaService.createCadenzaDBInsertTask(
|
|
2051
|
+
"service_instance_transport",
|
|
2052
|
+
{
|
|
2053
|
+
onConflict: {
|
|
2054
|
+
target: ["service_instance_id", "role", "origin"],
|
|
2055
|
+
action: {
|
|
2056
|
+
do: "update",
|
|
2057
|
+
set: {
|
|
2058
|
+
protocols: "excluded",
|
|
2059
|
+
security_profile: "excluded",
|
|
2060
|
+
auth_strategy: "excluded",
|
|
2061
|
+
deleted: "false"
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
},
|
|
2066
|
+
{
|
|
2067
|
+
inputSchema: {
|
|
2068
|
+
type: "object",
|
|
2069
|
+
properties: {
|
|
2070
|
+
data: {
|
|
2071
|
+
type: "object",
|
|
2072
|
+
properties: {
|
|
2073
|
+
uuid: {
|
|
2074
|
+
type: "string"
|
|
2075
|
+
},
|
|
2076
|
+
service_instance_id: {
|
|
2077
|
+
type: "string"
|
|
2078
|
+
},
|
|
2079
|
+
role: {
|
|
2080
|
+
type: "string"
|
|
2081
|
+
},
|
|
2082
|
+
origin: {
|
|
2083
|
+
type: "string"
|
|
2084
|
+
},
|
|
2085
|
+
protocols: {
|
|
2086
|
+
type: "array",
|
|
2087
|
+
items: {
|
|
2088
|
+
type: "string"
|
|
2089
|
+
}
|
|
2090
|
+
},
|
|
2091
|
+
security_profile: {
|
|
2092
|
+
type: "string"
|
|
2093
|
+
},
|
|
2094
|
+
auth_strategy: {
|
|
2095
|
+
type: "string"
|
|
2096
|
+
}
|
|
2097
|
+
},
|
|
2098
|
+
required: ["uuid", "service_instance_id", "role", "origin"]
|
|
2099
|
+
}
|
|
2100
|
+
},
|
|
2101
|
+
required: ["data"]
|
|
2102
|
+
},
|
|
2103
|
+
outputSchema: {
|
|
2104
|
+
type: "object",
|
|
2105
|
+
properties: {
|
|
2106
|
+
uuid: {
|
|
2107
|
+
type: "string"
|
|
2108
|
+
}
|
|
2109
|
+
},
|
|
2110
|
+
required: ["uuid"]
|
|
2111
|
+
},
|
|
2112
|
+
retryCount: 5,
|
|
2113
|
+
retryDelay: 1e3
|
|
2114
|
+
}
|
|
2115
|
+
).doOn("meta.service_registry.transport_registration_requested").emits("meta.service_registry.transport_registered").emitsOnFail("meta.service_registry.transport_registration_failed");
|
|
1730
2116
|
CadenzaService.createMetaTask(
|
|
1731
2117
|
"Handle service creation",
|
|
1732
2118
|
(ctx) => {
|
|
1733
2119
|
if (!ctx.__cadenzaDBConnect) {
|
|
1734
2120
|
ctx.__skipRemoteExecution = true;
|
|
1735
2121
|
}
|
|
1736
|
-
if (isBrowser) {
|
|
2122
|
+
if (isBrowser || ctx.__isFrontend) {
|
|
1737
2123
|
CadenzaService.createMetaTask("Prepare for signal sync", () => {
|
|
1738
2124
|
return {};
|
|
1739
2125
|
}).then(
|
|
@@ -1766,28 +2152,24 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1766
2152
|
for (const service of services) {
|
|
1767
2153
|
const instances = this.instances.get(service).filter((i) => i.isActive);
|
|
1768
2154
|
for (const instance of instances) {
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
const clientCreated = instances?.some(
|
|
1773
|
-
(i) => i.address === address && i.port === port && i.clientCreated && i.isActive
|
|
2155
|
+
const transport = this.getRouteableTransport(
|
|
2156
|
+
instance,
|
|
2157
|
+
this.useSocket ? "socket" : "rest"
|
|
1774
2158
|
);
|
|
1775
|
-
if (!
|
|
2159
|
+
if (!transport) {
|
|
2160
|
+
continue;
|
|
2161
|
+
}
|
|
2162
|
+
if (!this.hasTransportClientCreated(instance, transport.uuid)) {
|
|
1776
2163
|
emit("meta.service_registry.dependee_registered", {
|
|
1777
2164
|
serviceName: service,
|
|
1778
2165
|
serviceInstanceId: instance.uuid,
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
2166
|
+
serviceTransportId: transport.uuid,
|
|
2167
|
+
serviceOrigin: transport.origin,
|
|
2168
|
+
transportProtocols: transport.protocols,
|
|
1782
2169
|
communicationTypes: ["signal"]
|
|
1783
2170
|
});
|
|
2171
|
+
this.markTransportClientCreated(instance, transport.uuid);
|
|
1784
2172
|
}
|
|
1785
|
-
instance.clientCreated = true;
|
|
1786
|
-
instances.forEach((i) => {
|
|
1787
|
-
if (i.address === address && i.port === port) {
|
|
1788
|
-
i.clientCreated = true;
|
|
1789
|
-
}
|
|
1790
|
-
});
|
|
1791
2173
|
}
|
|
1792
2174
|
}
|
|
1793
2175
|
return {};
|
|
@@ -1926,6 +2308,33 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
1926
2308
|
}
|
|
1927
2309
|
return this.getInstance(this.serviceName, this.serviceInstanceId);
|
|
1928
2310
|
}
|
|
2311
|
+
getRoutingTransportRole() {
|
|
2312
|
+
return this.isFrontend ? "public" : "internal";
|
|
2313
|
+
}
|
|
2314
|
+
getTransportById(instance, transportId) {
|
|
2315
|
+
return instance.transports.find((transport) => transport.uuid === transportId);
|
|
2316
|
+
}
|
|
2317
|
+
getRouteableTransport(instance, protocol, role = this.getRoutingTransportRole()) {
|
|
2318
|
+
return getRouteableTransport(instance, role, protocol);
|
|
2319
|
+
}
|
|
2320
|
+
getTransportClientKey(instance, protocol, role = this.getRoutingTransportRole()) {
|
|
2321
|
+
const transport = this.getRouteableTransport(instance, protocol, role);
|
|
2322
|
+
if (!transport) {
|
|
2323
|
+
return null;
|
|
2324
|
+
}
|
|
2325
|
+
return buildTransportClientKey(transport);
|
|
2326
|
+
}
|
|
2327
|
+
hasTransportClientCreated(instance, transportId) {
|
|
2328
|
+
return (instance.clientCreatedTransportIds ?? []).includes(transportId);
|
|
2329
|
+
}
|
|
2330
|
+
markTransportClientCreated(instance, transportId) {
|
|
2331
|
+
if (!instance.clientCreatedTransportIds) {
|
|
2332
|
+
instance.clientCreatedTransportIds = [];
|
|
2333
|
+
}
|
|
2334
|
+
if (!instance.clientCreatedTransportIds.includes(transportId)) {
|
|
2335
|
+
instance.clientCreatedTransportIds.push(transportId);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
1929
2338
|
registerDependee(serviceName, serviceInstanceId, options = {}) {
|
|
1930
2339
|
if (!serviceName || !serviceInstanceId) {
|
|
1931
2340
|
return;
|
|
@@ -2003,7 +2412,13 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2003
2412
|
if (!serviceName || !serviceInstanceId) {
|
|
2004
2413
|
return null;
|
|
2005
2414
|
}
|
|
2006
|
-
const
|
|
2415
|
+
const transportId = ctx.transportId ?? ctx.serviceTransportId ?? ctx.serviceTransport?.uuid ?? void 0;
|
|
2416
|
+
const transportOrigin = ctx.transportOrigin ?? ctx.serviceOrigin ?? ctx.serviceTransport?.origin ?? void 0;
|
|
2417
|
+
const transportProtocols = Array.isArray(
|
|
2418
|
+
ctx.transportProtocols ?? ctx.serviceTransport?.protocols
|
|
2419
|
+
) ? (ctx.transportProtocols ?? ctx.serviceTransport?.protocols).map((entry) => String(entry)).filter(
|
|
2420
|
+
(entry) => entry === "rest" || entry === "socket"
|
|
2421
|
+
) : void 0;
|
|
2007
2422
|
const numberOfRunningGraphs = Math.max(
|
|
2008
2423
|
0,
|
|
2009
2424
|
Math.trunc(
|
|
@@ -2022,9 +2437,9 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2022
2437
|
return {
|
|
2023
2438
|
serviceName,
|
|
2024
2439
|
serviceInstanceId,
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2440
|
+
transportId: typeof transportId === "string" && transportId.trim().length > 0 ? transportId : void 0,
|
|
2441
|
+
transportOrigin: typeof transportOrigin === "string" && transportOrigin.trim().length > 0 ? transportOrigin : void 0,
|
|
2442
|
+
transportProtocols: transportProtocols && transportProtocols.length > 0 ? Array.from(new Set(transportProtocols)) : void 0,
|
|
2028
2443
|
isFrontend: typeof ctx.isFrontend === "boolean" ? ctx.isFrontend : typeof ctx.serviceInstance?.isFrontend === "boolean" ? ctx.serviceInstance.isFrontend : void 0,
|
|
2029
2444
|
reportedAt: ctx.reportedAt ?? (typeof ctx.__reportedAt === "string" ? ctx.__reportedAt : void 0) ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
2030
2445
|
state: ctx.state === "healthy" || ctx.state === "degraded" || ctx.state === "overloaded" || ctx.state === "unavailable" ? ctx.state : resolved.state,
|
|
@@ -2041,14 +2456,23 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2041
2456
|
if (!instance) {
|
|
2042
2457
|
return false;
|
|
2043
2458
|
}
|
|
2044
|
-
if (report.
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2459
|
+
if (report.transportId && report.transportOrigin) {
|
|
2460
|
+
const protocols = report.transportProtocols && report.transportProtocols.length > 0 ? report.transportProtocols : ["rest", "socket"];
|
|
2461
|
+
const existingTransport = this.getTransportById(instance, report.transportId);
|
|
2462
|
+
if (existingTransport) {
|
|
2463
|
+
existingTransport.origin = report.transportOrigin;
|
|
2464
|
+
existingTransport.protocols = protocols;
|
|
2465
|
+
} else {
|
|
2466
|
+
instance.transports.push({
|
|
2467
|
+
uuid: report.transportId,
|
|
2468
|
+
serviceInstanceId: report.serviceInstanceId,
|
|
2469
|
+
role: this.getRoutingTransportRole(),
|
|
2470
|
+
origin: report.transportOrigin,
|
|
2471
|
+
protocols,
|
|
2472
|
+
securityProfile: null,
|
|
2473
|
+
authStrategy: null
|
|
2474
|
+
});
|
|
2475
|
+
}
|
|
2052
2476
|
}
|
|
2053
2477
|
if (typeof report.isFrontend === "boolean") {
|
|
2054
2478
|
instance.isFrontend = report.isFrontend;
|
|
@@ -2091,9 +2515,21 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2091
2515
|
const report = {
|
|
2092
2516
|
serviceName: this.serviceName,
|
|
2093
2517
|
serviceInstanceId: this.serviceInstanceId,
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2518
|
+
transportId: this.getRouteableTransport(
|
|
2519
|
+
localInstance,
|
|
2520
|
+
this.useSocket ? "socket" : "rest",
|
|
2521
|
+
"internal"
|
|
2522
|
+
)?.uuid ?? void 0,
|
|
2523
|
+
transportOrigin: this.getRouteableTransport(
|
|
2524
|
+
localInstance,
|
|
2525
|
+
this.useSocket ? "socket" : "rest",
|
|
2526
|
+
"internal"
|
|
2527
|
+
)?.origin ?? void 0,
|
|
2528
|
+
transportProtocols: this.getRouteableTransport(
|
|
2529
|
+
localInstance,
|
|
2530
|
+
this.useSocket ? "socket" : "rest",
|
|
2531
|
+
"internal"
|
|
2532
|
+
)?.protocols ?? void 0,
|
|
2097
2533
|
isFrontend: localInstance.isFrontend,
|
|
2098
2534
|
reportedAt,
|
|
2099
2535
|
state: snapshot.state,
|
|
@@ -2308,6 +2744,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
2308
2744
|
this.numberOfRunningGraphs = 0;
|
|
2309
2745
|
this.runtimeStatusHeartbeatStarted = false;
|
|
2310
2746
|
this.lastRuntimeStatusSnapshot = null;
|
|
2747
|
+
this.isFrontend = false;
|
|
2311
2748
|
}
|
|
2312
2749
|
};
|
|
2313
2750
|
|
|
@@ -2479,13 +2916,10 @@ var RestController = class _RestController {
|
|
|
2479
2916
|
CadenzaService.createMetaTask(
|
|
2480
2917
|
"Setup Express app security",
|
|
2481
2918
|
(ctx, emit) => {
|
|
2482
|
-
if (isBrowser) {
|
|
2483
|
-
emit("meta.
|
|
2919
|
+
if (isBrowser || ctx.__isFrontend) {
|
|
2920
|
+
emit("meta.service_registry.instance_registration_requested", {
|
|
2484
2921
|
data: {
|
|
2485
2922
|
uuid: ctx.__serviceInstanceId,
|
|
2486
|
-
address: `browser:${ctx.__serviceInstanceId}`,
|
|
2487
|
-
port: 0,
|
|
2488
|
-
exposed: false,
|
|
2489
2923
|
process_pid: 1,
|
|
2490
2924
|
service_name: ctx.__serviceName,
|
|
2491
2925
|
is_frontend: true,
|
|
@@ -2494,6 +2928,7 @@ var RestController = class _RestController {
|
|
|
2494
2928
|
is_blocked: false,
|
|
2495
2929
|
health: {}
|
|
2496
2930
|
},
|
|
2931
|
+
transportData: [],
|
|
2497
2932
|
...ctx
|
|
2498
2933
|
});
|
|
2499
2934
|
return;
|
|
@@ -2566,7 +3001,7 @@ var RestController = class _RestController {
|
|
|
2566
3001
|
return { ...ctx, __app: app };
|
|
2567
3002
|
},
|
|
2568
3003
|
"Sets up the Express server according to the security profile"
|
|
2569
|
-
).attachSignal("meta.
|
|
3004
|
+
).attachSignal("meta.service_registry.instance_registration_requested").then(
|
|
2570
3005
|
CadenzaService.createMetaTask(
|
|
2571
3006
|
"Define RestServer",
|
|
2572
3007
|
(ctx) => {
|
|
@@ -2686,28 +3121,32 @@ var RestController = class _RestController {
|
|
|
2686
3121
|
CadenzaService.createMetaTask(
|
|
2687
3122
|
"Configure network",
|
|
2688
3123
|
async (ctx) => {
|
|
2689
|
-
let
|
|
2690
|
-
let
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
3124
|
+
let httpOrigin = null;
|
|
3125
|
+
let httpsOrigin = null;
|
|
3126
|
+
const resolveBoundAddress = (server) => {
|
|
3127
|
+
if (typeof server?.address() === "string") {
|
|
3128
|
+
return server.address();
|
|
3129
|
+
}
|
|
3130
|
+
if (server?.address()?.address === "::") {
|
|
3131
|
+
if (process.env.NODE_ENV === "development") {
|
|
3132
|
+
return "localhost";
|
|
3133
|
+
}
|
|
3134
|
+
if (process.env.IS_DOCKER === "true") {
|
|
3135
|
+
return process.env.CADENZA_SERVER_URL || "localhost";
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
return server?.address()?.address || "localhost";
|
|
3139
|
+
};
|
|
3140
|
+
const createHttpServer = async (ctx2) => {
|
|
3141
|
+
await new Promise((resolve) => {
|
|
2694
3142
|
const server = http.createServer(ctx2.__app);
|
|
2695
3143
|
ctx2.httpServer = server;
|
|
2696
3144
|
server.listen(ctx2.__port, () => {
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
} else if (process.env.IS_DOCKER === "true") {
|
|
2703
|
-
address = process.env.CADENZA_SERVER_URL || "localhost";
|
|
2704
|
-
}
|
|
2705
|
-
} else {
|
|
2706
|
-
address = server?.address()?.address || "undefined";
|
|
2707
|
-
}
|
|
2708
|
-
console.log(
|
|
2709
|
-
`Server is running on ${address}:${port}`
|
|
2710
|
-
);
|
|
3145
|
+
const addressInfo = server.address();
|
|
3146
|
+
const address = resolveBoundAddress(server);
|
|
3147
|
+
const port = typeof addressInfo === "object" && addressInfo ? addressInfo.port || ctx2.__port : ctx2.__port;
|
|
3148
|
+
httpOrigin = `http://${address}:${port}`;
|
|
3149
|
+
console.log(`Server is running on ${httpOrigin}`);
|
|
2711
3150
|
resolve(address);
|
|
2712
3151
|
});
|
|
2713
3152
|
CadenzaService.createMetaTask(
|
|
@@ -2733,22 +3172,12 @@ var RestController = class _RestController {
|
|
|
2733
3172
|
ctx2.__app
|
|
2734
3173
|
);
|
|
2735
3174
|
ctx2.httpsServer = httpsServer;
|
|
2736
|
-
ctx2.__port = 443;
|
|
2737
|
-
port = 443;
|
|
2738
3175
|
httpsServer.listen(443, () => {
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
}
|
|
2745
|
-
} else {
|
|
2746
|
-
address = httpsServer?.address()?.address || "";
|
|
2747
|
-
}
|
|
2748
|
-
exposed = true;
|
|
2749
|
-
console.log(
|
|
2750
|
-
`HTTPS Server is running on ${address}:443`
|
|
2751
|
-
);
|
|
3176
|
+
const addressInfo = httpsServer.address();
|
|
3177
|
+
const address = resolveBoundAddress(httpsServer);
|
|
3178
|
+
const port = typeof addressInfo === "object" && addressInfo ? addressInfo.port || 443 : 443;
|
|
3179
|
+
httpsOrigin = `https://${address}:${port}`;
|
|
3180
|
+
console.log(`HTTPS Server is running on ${httpsOrigin}`);
|
|
2752
3181
|
resolve(address);
|
|
2753
3182
|
});
|
|
2754
3183
|
CadenzaService.createMetaTask(
|
|
@@ -2768,11 +3197,34 @@ var RestController = class _RestController {
|
|
|
2768
3197
|
} else if (ctx.__networkMode === "auto") {
|
|
2769
3198
|
await createHttpServer(ctx);
|
|
2770
3199
|
}
|
|
3200
|
+
const declaredTransports = Array.isArray(ctx.__declaredTransports) ? ctx.__declaredTransports : [];
|
|
3201
|
+
const hasExplicitInternalTransport = declaredTransports.some(
|
|
3202
|
+
(transport) => transport.role === "internal"
|
|
3203
|
+
);
|
|
3204
|
+
const transportData = declaredTransports.map((transport) => ({
|
|
3205
|
+
uuid: transport.uuid,
|
|
3206
|
+
service_instance_id: ctx.__serviceInstanceId,
|
|
3207
|
+
role: transport.role,
|
|
3208
|
+
origin: transport.origin,
|
|
3209
|
+
protocols: transport.protocols ?? ["rest", "socket"],
|
|
3210
|
+
...transport.securityProfile ? { security_profile: transport.securityProfile } : {},
|
|
3211
|
+
...transport.authStrategy ? { auth_strategy: transport.authStrategy } : {}
|
|
3212
|
+
}));
|
|
3213
|
+
if (!hasExplicitInternalTransport) {
|
|
3214
|
+
const internalOrigin = httpOrigin ?? httpsOrigin;
|
|
3215
|
+
if (internalOrigin) {
|
|
3216
|
+
transportData.unshift({
|
|
3217
|
+
uuid: `${ctx.__serviceInstanceId}-internal-auto`,
|
|
3218
|
+
service_instance_id: ctx.__serviceInstanceId,
|
|
3219
|
+
role: "internal",
|
|
3220
|
+
origin: internalOrigin,
|
|
3221
|
+
protocols: ["rest", "socket"],
|
|
3222
|
+
...ctx.__securityProfile ? { security_profile: ctx.__securityProfile } : {}
|
|
3223
|
+
});
|
|
3224
|
+
}
|
|
3225
|
+
}
|
|
2771
3226
|
ctx.data = {
|
|
2772
3227
|
uuid: ctx.__serviceInstanceId,
|
|
2773
|
-
address,
|
|
2774
|
-
port,
|
|
2775
|
-
exposed,
|
|
2776
3228
|
process_pid: process.pid,
|
|
2777
3229
|
service_name: ctx.__serviceName,
|
|
2778
3230
|
is_active: true,
|
|
@@ -2781,7 +3233,12 @@ var RestController = class _RestController {
|
|
|
2781
3233
|
is_blocked: false,
|
|
2782
3234
|
health: {}
|
|
2783
3235
|
};
|
|
3236
|
+
ctx.transportData = transportData;
|
|
2784
3237
|
delete ctx.__app;
|
|
3238
|
+
CadenzaService.emit(
|
|
3239
|
+
"meta.service_registry.instance_registration_requested",
|
|
3240
|
+
ctx
|
|
3241
|
+
);
|
|
2785
3242
|
return ctx;
|
|
2786
3243
|
},
|
|
2787
3244
|
"Configures network mode"
|
|
@@ -2831,10 +3288,12 @@ var RestController = class _RestController {
|
|
|
2831
3288
|
CadenzaService.createMetaTask(
|
|
2832
3289
|
"Setup fetch client",
|
|
2833
3290
|
(ctx) => {
|
|
2834
|
-
const
|
|
2835
|
-
const
|
|
2836
|
-
const
|
|
2837
|
-
|
|
3291
|
+
const serviceName = String(ctx.serviceName ?? "");
|
|
3292
|
+
const URL2 = String(ctx.serviceOrigin ?? "");
|
|
3293
|
+
const fetchId = String(ctx.serviceTransportId ?? "");
|
|
3294
|
+
if (!serviceName || !URL2 || !fetchId) {
|
|
3295
|
+
return false;
|
|
3296
|
+
}
|
|
2838
3297
|
const fetchDiagnostics = this.ensureFetchClientDiagnostics(
|
|
2839
3298
|
fetchId,
|
|
2840
3299
|
serviceName,
|
|
@@ -3086,18 +3545,18 @@ var RestController = class _RestController {
|
|
|
3086
3545
|
serviceName,
|
|
3087
3546
|
serviceInstanceId,
|
|
3088
3547
|
communicationTypes,
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3548
|
+
serviceTransportId,
|
|
3549
|
+
serviceOrigin,
|
|
3550
|
+
transportProtocols
|
|
3092
3551
|
} = ctx;
|
|
3093
|
-
const fetchId =
|
|
3552
|
+
const fetchId = String(serviceTransportId ?? "");
|
|
3094
3553
|
emit(`meta.fetch.handshake_requested:${fetchId}`, {
|
|
3095
3554
|
serviceInstanceId,
|
|
3096
3555
|
serviceName,
|
|
3097
3556
|
communicationTypes,
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3557
|
+
serviceTransportId,
|
|
3558
|
+
serviceOrigin,
|
|
3559
|
+
transportProtocols,
|
|
3101
3560
|
handshakeData: {
|
|
3102
3561
|
instanceId: CadenzaService.serviceRegistry.serviceInstanceId,
|
|
3103
3562
|
serviceName: CadenzaService.serviceRegistry.serviceName
|
|
@@ -3280,7 +3739,6 @@ var RestController = class _RestController {
|
|
|
3280
3739
|
};
|
|
3281
3740
|
|
|
3282
3741
|
// src/network/SocketController.ts
|
|
3283
|
-
import { Server } from "socket.io";
|
|
3284
3742
|
import { RateLimiterMemory as RateLimiterMemory2 } from "rate-limiter-flexible";
|
|
3285
3743
|
import { io } from "socket.io-client";
|
|
3286
3744
|
|
|
@@ -3323,6 +3781,13 @@ var waitForSocketConnection = async (socket, timeoutMs, createError) => {
|
|
|
3323
3781
|
};
|
|
3324
3782
|
|
|
3325
3783
|
// src/network/SocketController.ts
|
|
3784
|
+
var dynamicImport = new Function(
|
|
3785
|
+
"specifier",
|
|
3786
|
+
"return import(specifier);"
|
|
3787
|
+
);
|
|
3788
|
+
async function importNodeModule(specifier) {
|
|
3789
|
+
return dynamicImport(specifier);
|
|
3790
|
+
}
|
|
3326
3791
|
var SocketController = class _SocketController {
|
|
3327
3792
|
constructor() {
|
|
3328
3793
|
this.diagnosticsErrorHistoryLimit = 100;
|
|
@@ -3347,9 +3812,9 @@ var SocketController = class _SocketController {
|
|
|
3347
3812
|
serviceInstanceId: "",
|
|
3348
3813
|
communicationTypes: [],
|
|
3349
3814
|
serviceName: "",
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3815
|
+
serviceTransportId: "",
|
|
3816
|
+
serviceOrigin: "",
|
|
3817
|
+
transportProtocols: [],
|
|
3353
3818
|
url: "",
|
|
3354
3819
|
socketId: null,
|
|
3355
3820
|
connected: false,
|
|
@@ -3522,7 +3987,7 @@ var SocketController = class _SocketController {
|
|
|
3522
3987
|
const setupSocketServerTask = CadenzaService.createMetaTask(
|
|
3523
3988
|
"Setup SocketServer",
|
|
3524
3989
|
this.socketServerActor.task(
|
|
3525
|
-
({ state, runtimeState, input, actor, setState, setRuntimeState, emit }) => {
|
|
3990
|
+
async ({ state, runtimeState, input, actor, setState, setRuntimeState, emit }) => {
|
|
3526
3991
|
const serverKey = this.resolveSocketServerKey(input) ?? actor.key ?? this.socketServerDefaultKey;
|
|
3527
3992
|
const shouldUseSocket = Boolean(input.__useSocket);
|
|
3528
3993
|
if (!shouldUseSocket) {
|
|
@@ -3541,7 +4006,9 @@ var SocketController = class _SocketController {
|
|
|
3541
4006
|
}
|
|
3542
4007
|
let runtimeHandle = runtimeState;
|
|
3543
4008
|
if (!runtimeHandle) {
|
|
3544
|
-
runtimeHandle = this.createSocketServerRuntimeHandleFromContext(
|
|
4009
|
+
runtimeHandle = await this.createSocketServerRuntimeHandleFromContext(
|
|
4010
|
+
input
|
|
4011
|
+
);
|
|
3545
4012
|
setRuntimeState(runtimeHandle);
|
|
3546
4013
|
}
|
|
3547
4014
|
const profile = String(input.__securityProfile ?? state.securityProfile ?? "medium");
|
|
@@ -3799,21 +4266,21 @@ var SocketController = class _SocketController {
|
|
|
3799
4266
|
if (input.serviceName !== void 0) {
|
|
3800
4267
|
next.serviceName = String(input.serviceName);
|
|
3801
4268
|
}
|
|
3802
|
-
if (input.
|
|
3803
|
-
next.
|
|
4269
|
+
if (input.serviceTransportId !== void 0) {
|
|
4270
|
+
next.serviceTransportId = String(input.serviceTransportId);
|
|
3804
4271
|
}
|
|
3805
4272
|
if (input.serviceInstanceId !== void 0) {
|
|
3806
4273
|
next.serviceInstanceId = String(input.serviceInstanceId);
|
|
3807
4274
|
}
|
|
3808
|
-
if (input.
|
|
3809
|
-
next.
|
|
4275
|
+
if (input.serviceOrigin !== void 0) {
|
|
4276
|
+
next.serviceOrigin = String(input.serviceOrigin);
|
|
4277
|
+
}
|
|
4278
|
+
if (input.transportProtocols !== void 0) {
|
|
4279
|
+
next.transportProtocols = Array.isArray(input.transportProtocols) ? input.transportProtocols.map((entry) => String(entry)) : [];
|
|
3810
4280
|
}
|
|
3811
4281
|
if (input.url !== void 0) {
|
|
3812
4282
|
next.url = String(input.url);
|
|
3813
4283
|
}
|
|
3814
|
-
if (input.servicePort !== void 0) {
|
|
3815
|
-
next.servicePort = Number(input.servicePort);
|
|
3816
|
-
}
|
|
3817
4284
|
if (input.fetchId !== void 0) {
|
|
3818
4285
|
next.fetchId = String(input.fetchId);
|
|
3819
4286
|
}
|
|
@@ -3857,25 +4324,24 @@ var SocketController = class _SocketController {
|
|
|
3857
4324
|
input.communicationTypes
|
|
3858
4325
|
);
|
|
3859
4326
|
const serviceName = String(input.serviceName ?? "");
|
|
3860
|
-
const
|
|
3861
|
-
const
|
|
3862
|
-
const
|
|
3863
|
-
if (!
|
|
4327
|
+
const serviceTransportId = String(input.serviceTransportId ?? "");
|
|
4328
|
+
const serviceOrigin = String(input.serviceOrigin ?? "");
|
|
4329
|
+
const parsedOrigin = parseTransportOrigin(serviceOrigin);
|
|
4330
|
+
if (!serviceTransportId || !serviceOrigin || !parsedOrigin) {
|
|
3864
4331
|
CadenzaService.log(
|
|
3865
|
-
"Socket client setup skipped due to missing
|
|
4332
|
+
"Socket client setup skipped due to missing transport origin",
|
|
3866
4333
|
{
|
|
3867
4334
|
serviceName,
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
protocol
|
|
4335
|
+
serviceTransportId,
|
|
4336
|
+
serviceOrigin
|
|
3871
4337
|
},
|
|
3872
4338
|
"warning"
|
|
3873
4339
|
);
|
|
3874
4340
|
return false;
|
|
3875
4341
|
}
|
|
3876
|
-
const socketProtocol = protocol === "https" ? "wss" : "ws";
|
|
3877
|
-
const url = `${socketProtocol}://${
|
|
3878
|
-
const fetchId =
|
|
4342
|
+
const socketProtocol = parsedOrigin.protocol === "https" ? "wss" : "ws";
|
|
4343
|
+
const url = `${socketProtocol}://${parsedOrigin.hostname}:${parsedOrigin.port}`;
|
|
4344
|
+
const fetchId = serviceTransportId;
|
|
3879
4345
|
const applySessionOperation = (operation, patch = {}) => {
|
|
3880
4346
|
CadenzaService.emit("meta.socket_client.session_operation_requested", {
|
|
3881
4347
|
fetchId,
|
|
@@ -3884,9 +4350,9 @@ var SocketController = class _SocketController {
|
|
|
3884
4350
|
serviceInstanceId,
|
|
3885
4351
|
communicationTypes,
|
|
3886
4352
|
serviceName,
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
4353
|
+
serviceTransportId,
|
|
4354
|
+
serviceOrigin,
|
|
4355
|
+
transportProtocols: input.transportProtocols,
|
|
3890
4356
|
url
|
|
3891
4357
|
});
|
|
3892
4358
|
};
|
|
@@ -3905,9 +4371,9 @@ var SocketController = class _SocketController {
|
|
|
3905
4371
|
serviceInstanceId,
|
|
3906
4372
|
communicationTypes,
|
|
3907
4373
|
serviceName,
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
4374
|
+
serviceTransportId,
|
|
4375
|
+
serviceOrigin,
|
|
4376
|
+
transportProtocols: Array.isArray(input.transportProtocols) ? input.transportProtocols.map((entry) => String(entry)) : [],
|
|
3911
4377
|
url,
|
|
3912
4378
|
destroyed: false,
|
|
3913
4379
|
updatedAt: Date.now()
|
|
@@ -4235,8 +4701,8 @@ var SocketController = class _SocketController {
|
|
|
4235
4701
|
);
|
|
4236
4702
|
CadenzaService.emit(`meta.socket_client.disconnected:${fetchId}`, {
|
|
4237
4703
|
serviceName,
|
|
4238
|
-
|
|
4239
|
-
|
|
4704
|
+
serviceTransportId,
|
|
4705
|
+
serviceOrigin
|
|
4240
4706
|
});
|
|
4241
4707
|
runtimeHandle.handshake = false;
|
|
4242
4708
|
});
|
|
@@ -4257,7 +4723,7 @@ var SocketController = class _SocketController {
|
|
|
4257
4723
|
{
|
|
4258
4724
|
serviceInstanceId: CadenzaService.serviceRegistry.serviceInstanceId,
|
|
4259
4725
|
serviceName: CadenzaService.serviceRegistry.serviceName,
|
|
4260
|
-
isFrontend: isBrowser,
|
|
4726
|
+
isFrontend: CadenzaService.serviceRegistry.isFrontend || isBrowser,
|
|
4261
4727
|
__status: "success"
|
|
4262
4728
|
},
|
|
4263
4729
|
1e4,
|
|
@@ -4435,9 +4901,9 @@ var SocketController = class _SocketController {
|
|
|
4435
4901
|
serviceInstanceId,
|
|
4436
4902
|
serviceName,
|
|
4437
4903
|
communicationTypes,
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4904
|
+
serviceTransportId,
|
|
4905
|
+
serviceOrigin,
|
|
4906
|
+
transportProtocols: input.transportProtocols,
|
|
4441
4907
|
handshakeData: {
|
|
4442
4908
|
instanceId: CadenzaService.serviceRegistry.serviceInstanceId,
|
|
4443
4909
|
serviceName: CadenzaService.serviceRegistry.serviceName
|
|
@@ -4476,31 +4942,20 @@ var SocketController = class _SocketController {
|
|
|
4476
4942
|
if (explicitFetchId) {
|
|
4477
4943
|
return explicitFetchId;
|
|
4478
4944
|
}
|
|
4479
|
-
const
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
return void 0;
|
|
4484
|
-
}
|
|
4485
|
-
return `${serviceAddress}_${port}`;
|
|
4945
|
+
const transportId = String(
|
|
4946
|
+
input.serviceTransportId ?? input.transportId ?? ""
|
|
4947
|
+
).trim();
|
|
4948
|
+
return transportId || void 0;
|
|
4486
4949
|
}
|
|
4487
|
-
|
|
4488
|
-
if (protocol === "https") {
|
|
4489
|
-
return 443;
|
|
4490
|
-
}
|
|
4491
|
-
const parsed = Number(rawPort);
|
|
4492
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
4493
|
-
return void 0;
|
|
4494
|
-
}
|
|
4495
|
-
return Math.trunc(parsed);
|
|
4496
|
-
}
|
|
4497
|
-
createSocketServerRuntimeHandleFromContext(context) {
|
|
4950
|
+
async createSocketServerRuntimeHandleFromContext(context) {
|
|
4498
4951
|
const baseServer = context.httpsServer ?? context.httpServer;
|
|
4499
4952
|
if (!baseServer) {
|
|
4500
4953
|
throw new Error(
|
|
4501
4954
|
"Socket server runtime setup requires either httpsServer or httpServer"
|
|
4502
4955
|
);
|
|
4503
4956
|
}
|
|
4957
|
+
const socketServerModule = await importNodeModule("socket.io");
|
|
4958
|
+
const Server = socketServerModule.Server;
|
|
4504
4959
|
const server = new Server(baseServer, {
|
|
4505
4960
|
pingInterval: 3e4,
|
|
4506
4961
|
pingTimeout: 2e4,
|
|
@@ -4799,8 +5254,132 @@ var SignalController = class _SignalController {
|
|
|
4799
5254
|
}
|
|
4800
5255
|
};
|
|
4801
5256
|
|
|
4802
|
-
// src/graph/controllers/
|
|
5257
|
+
// src/graph/controllers/registerActorSessionPersistence.ts
|
|
4803
5258
|
import { META_ACTOR_SESSION_STATE_PERSIST_INTENT } from "@cadenza.io/core";
|
|
5259
|
+
function registerActorSessionPersistenceTasks() {
|
|
5260
|
+
if (CadenzaService.get("Persist actor session state")) {
|
|
5261
|
+
return;
|
|
5262
|
+
}
|
|
5263
|
+
const actorSessionStateInsertTask = CadenzaService.get("dbInsertActorSessionState") ?? CadenzaService.get("Insert actor_session_state in CadenzaDB") ?? CadenzaService.createCadenzaDBInsertTask(
|
|
5264
|
+
"actor_session_state",
|
|
5265
|
+
{},
|
|
5266
|
+
{ concurrency: 100, isSubMeta: true }
|
|
5267
|
+
);
|
|
5268
|
+
const validateActorSessionStatePersistenceTask = CadenzaService.createMetaTask(
|
|
5269
|
+
"Validate actor session state persistence",
|
|
5270
|
+
(ctx) => {
|
|
5271
|
+
if (ctx.errored || ctx.failed || ctx.__success !== true) {
|
|
5272
|
+
throw new Error(
|
|
5273
|
+
String(
|
|
5274
|
+
ctx.__error ?? ctx.error ?? "actor_session_state persistence query failed"
|
|
5275
|
+
)
|
|
5276
|
+
);
|
|
5277
|
+
}
|
|
5278
|
+
const rowCount = Number(ctx.rowCount ?? 0);
|
|
5279
|
+
if (!Number.isFinite(rowCount) || rowCount <= 0) {
|
|
5280
|
+
throw new Error(
|
|
5281
|
+
"actor_session_state persistence did not affect any rows (possible stale durable_version)"
|
|
5282
|
+
);
|
|
5283
|
+
}
|
|
5284
|
+
return {
|
|
5285
|
+
__success: true,
|
|
5286
|
+
persisted: true,
|
|
5287
|
+
actor_name: ctx.actor_name,
|
|
5288
|
+
actor_version: ctx.actor_version,
|
|
5289
|
+
actor_key: ctx.actor_key,
|
|
5290
|
+
service_name: ctx.service_name,
|
|
5291
|
+
durable_version: ctx.durable_version
|
|
5292
|
+
};
|
|
5293
|
+
},
|
|
5294
|
+
"Enforces strict actor session persistence success contract.",
|
|
5295
|
+
{ isSubMeta: true, concurrency: 100 }
|
|
5296
|
+
);
|
|
5297
|
+
const insertAndValidateActorSessionStateTask = actorSessionStateInsertTask.then(
|
|
5298
|
+
validateActorSessionStatePersistenceTask
|
|
5299
|
+
);
|
|
5300
|
+
CadenzaService.createMetaTask(
|
|
5301
|
+
"Persist actor session state",
|
|
5302
|
+
(ctx) => {
|
|
5303
|
+
const actorName = typeof ctx.actor_name === "string" ? ctx.actor_name.trim() : "";
|
|
5304
|
+
const actorKey = typeof ctx.actor_key === "string" ? ctx.actor_key.trim() : "";
|
|
5305
|
+
const actorVersion = Number(ctx.actor_version ?? 1);
|
|
5306
|
+
const durableVersion = Number(ctx.durable_version);
|
|
5307
|
+
if (!actorName) {
|
|
5308
|
+
throw new Error("actor_name is required for actor session persistence");
|
|
5309
|
+
}
|
|
5310
|
+
if (!actorKey) {
|
|
5311
|
+
throw new Error("actor_key is required for actor session persistence");
|
|
5312
|
+
}
|
|
5313
|
+
if (!Number.isInteger(actorVersion) || actorVersion < 1) {
|
|
5314
|
+
throw new Error("actor_version must be a positive integer");
|
|
5315
|
+
}
|
|
5316
|
+
if (!Number.isInteger(durableVersion) || durableVersion < 0) {
|
|
5317
|
+
throw new Error("durable_version must be a non-negative integer");
|
|
5318
|
+
}
|
|
5319
|
+
if (typeof ctx.durable_state !== "object" || ctx.durable_state === null || Array.isArray(ctx.durable_state)) {
|
|
5320
|
+
throw new Error("durable_state must be a non-null object");
|
|
5321
|
+
}
|
|
5322
|
+
const serviceName = CadenzaService.serviceRegistry.serviceName;
|
|
5323
|
+
if (!serviceName) {
|
|
5324
|
+
throw new Error("service_name is not available for actor session persistence");
|
|
5325
|
+
}
|
|
5326
|
+
let expiresAt = null;
|
|
5327
|
+
if (ctx.expires_at !== void 0 && ctx.expires_at !== null) {
|
|
5328
|
+
if (ctx.expires_at instanceof Date) {
|
|
5329
|
+
expiresAt = ctx.expires_at.toISOString();
|
|
5330
|
+
} else if (typeof ctx.expires_at === "string" && ctx.expires_at.trim().length > 0) {
|
|
5331
|
+
expiresAt = ctx.expires_at;
|
|
5332
|
+
} else {
|
|
5333
|
+
throw new Error("expires_at must be null, Date, or non-empty string");
|
|
5334
|
+
}
|
|
5335
|
+
}
|
|
5336
|
+
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5337
|
+
return {
|
|
5338
|
+
...ctx,
|
|
5339
|
+
actor_name: actorName,
|
|
5340
|
+
actor_key: actorKey,
|
|
5341
|
+
actor_version: actorVersion,
|
|
5342
|
+
durable_version: durableVersion,
|
|
5343
|
+
expires_at: expiresAt,
|
|
5344
|
+
service_name: serviceName,
|
|
5345
|
+
queryData: {
|
|
5346
|
+
data: {
|
|
5347
|
+
actor_name: actorName,
|
|
5348
|
+
actor_version: actorVersion,
|
|
5349
|
+
actor_key: actorKey,
|
|
5350
|
+
service_name: serviceName,
|
|
5351
|
+
durable_state: ctx.durable_state,
|
|
5352
|
+
durable_version: durableVersion,
|
|
5353
|
+
expires_at: expiresAt,
|
|
5354
|
+
updated: updatedAt
|
|
5355
|
+
},
|
|
5356
|
+
onConflict: {
|
|
5357
|
+
target: [
|
|
5358
|
+
"actor_name",
|
|
5359
|
+
"actor_version",
|
|
5360
|
+
"actor_key",
|
|
5361
|
+
"service_name"
|
|
5362
|
+
],
|
|
5363
|
+
action: {
|
|
5364
|
+
do: "update",
|
|
5365
|
+
set: {
|
|
5366
|
+
durable_state: "excluded",
|
|
5367
|
+
durable_version: "excluded",
|
|
5368
|
+
expires_at: "excluded",
|
|
5369
|
+
updated: "excluded"
|
|
5370
|
+
},
|
|
5371
|
+
where: "actor_session_state.durable_version <= excluded.durable_version"
|
|
5372
|
+
}
|
|
5373
|
+
}
|
|
5374
|
+
}
|
|
5375
|
+
};
|
|
5376
|
+
},
|
|
5377
|
+
"Validates and prepares actor_session_state payload for strict write-through persistence.",
|
|
5378
|
+
{ isSubMeta: true, concurrency: 100 }
|
|
5379
|
+
).then(insertAndValidateActorSessionStateTask).respondsTo(META_ACTOR_SESSION_STATE_PERSIST_INTENT);
|
|
5380
|
+
}
|
|
5381
|
+
|
|
5382
|
+
// src/graph/controllers/GraphMetadataController.ts
|
|
4804
5383
|
var GraphMetadataController = class _GraphMetadataController {
|
|
4805
5384
|
static get instance() {
|
|
4806
5385
|
if (!this._instance) this._instance = new _GraphMetadataController();
|
|
@@ -5034,123 +5613,7 @@ var GraphMetadataController = class _GraphMetadataController {
|
|
|
5034
5613
|
}
|
|
5035
5614
|
};
|
|
5036
5615
|
}).doOn("meta.actor.task_associated").emits("global.meta.graph_metadata.actor_task_associated");
|
|
5037
|
-
|
|
5038
|
-
"actor_session_state",
|
|
5039
|
-
{},
|
|
5040
|
-
{ concurrency: 100, isSubMeta: true }
|
|
5041
|
-
);
|
|
5042
|
-
const validateActorSessionStatePersistenceTask = CadenzaService.createMetaTask(
|
|
5043
|
-
"Validate actor session state persistence",
|
|
5044
|
-
(ctx) => {
|
|
5045
|
-
if (ctx.errored || ctx.failed || ctx.__success !== true) {
|
|
5046
|
-
throw new Error(
|
|
5047
|
-
String(
|
|
5048
|
-
ctx.__error ?? ctx.error ?? "actor_session_state persistence query failed"
|
|
5049
|
-
)
|
|
5050
|
-
);
|
|
5051
|
-
}
|
|
5052
|
-
const rowCount = Number(ctx.rowCount ?? 0);
|
|
5053
|
-
if (!Number.isFinite(rowCount) || rowCount <= 0) {
|
|
5054
|
-
throw new Error(
|
|
5055
|
-
"actor_session_state persistence did not affect any rows (possible stale durable_version)"
|
|
5056
|
-
);
|
|
5057
|
-
}
|
|
5058
|
-
return {
|
|
5059
|
-
__success: true,
|
|
5060
|
-
persisted: true,
|
|
5061
|
-
actor_name: ctx.actor_name,
|
|
5062
|
-
actor_version: ctx.actor_version,
|
|
5063
|
-
actor_key: ctx.actor_key,
|
|
5064
|
-
service_name: ctx.service_name,
|
|
5065
|
-
durable_version: ctx.durable_version
|
|
5066
|
-
};
|
|
5067
|
-
},
|
|
5068
|
-
"Enforces strict actor session persistence success contract.",
|
|
5069
|
-
{ isSubMeta: true, concurrency: 100 }
|
|
5070
|
-
);
|
|
5071
|
-
const insertAndValidateActorSessionStateTask = actorSessionStateInsertTask.then(
|
|
5072
|
-
validateActorSessionStatePersistenceTask
|
|
5073
|
-
);
|
|
5074
|
-
CadenzaService.createMetaTask(
|
|
5075
|
-
"Persist actor session state",
|
|
5076
|
-
(ctx) => {
|
|
5077
|
-
const actorName = typeof ctx.actor_name === "string" ? ctx.actor_name.trim() : "";
|
|
5078
|
-
const actorKey = typeof ctx.actor_key === "string" ? ctx.actor_key.trim() : "";
|
|
5079
|
-
const actorVersion = Number(ctx.actor_version ?? 1);
|
|
5080
|
-
const durableVersion = Number(ctx.durable_version);
|
|
5081
|
-
if (!actorName) {
|
|
5082
|
-
throw new Error("actor_name is required for actor session persistence");
|
|
5083
|
-
}
|
|
5084
|
-
if (!actorKey) {
|
|
5085
|
-
throw new Error("actor_key is required for actor session persistence");
|
|
5086
|
-
}
|
|
5087
|
-
if (!Number.isInteger(actorVersion) || actorVersion < 1) {
|
|
5088
|
-
throw new Error("actor_version must be a positive integer");
|
|
5089
|
-
}
|
|
5090
|
-
if (!Number.isInteger(durableVersion) || durableVersion < 0) {
|
|
5091
|
-
throw new Error("durable_version must be a non-negative integer");
|
|
5092
|
-
}
|
|
5093
|
-
if (typeof ctx.durable_state !== "object" || ctx.durable_state === null || Array.isArray(ctx.durable_state)) {
|
|
5094
|
-
throw new Error("durable_state must be a non-null object");
|
|
5095
|
-
}
|
|
5096
|
-
const serviceName = CadenzaService.serviceRegistry.serviceName;
|
|
5097
|
-
if (!serviceName) {
|
|
5098
|
-
throw new Error("service_name is not available for actor session persistence");
|
|
5099
|
-
}
|
|
5100
|
-
let expiresAt = null;
|
|
5101
|
-
if (ctx.expires_at !== void 0 && ctx.expires_at !== null) {
|
|
5102
|
-
if (ctx.expires_at instanceof Date) {
|
|
5103
|
-
expiresAt = ctx.expires_at.toISOString();
|
|
5104
|
-
} else if (typeof ctx.expires_at === "string" && ctx.expires_at.trim().length > 0) {
|
|
5105
|
-
expiresAt = ctx.expires_at;
|
|
5106
|
-
} else {
|
|
5107
|
-
throw new Error("expires_at must be null, Date, or non-empty string");
|
|
5108
|
-
}
|
|
5109
|
-
}
|
|
5110
|
-
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5111
|
-
return {
|
|
5112
|
-
...ctx,
|
|
5113
|
-
actor_name: actorName,
|
|
5114
|
-
actor_key: actorKey,
|
|
5115
|
-
actor_version: actorVersion,
|
|
5116
|
-
durable_version: durableVersion,
|
|
5117
|
-
expires_at: expiresAt,
|
|
5118
|
-
service_name: serviceName,
|
|
5119
|
-
queryData: {
|
|
5120
|
-
data: {
|
|
5121
|
-
actor_name: actorName,
|
|
5122
|
-
actor_version: actorVersion,
|
|
5123
|
-
actor_key: actorKey,
|
|
5124
|
-
service_name: serviceName,
|
|
5125
|
-
durable_state: ctx.durable_state,
|
|
5126
|
-
durable_version: durableVersion,
|
|
5127
|
-
expires_at: expiresAt,
|
|
5128
|
-
updated: updatedAt
|
|
5129
|
-
},
|
|
5130
|
-
onConflict: {
|
|
5131
|
-
target: [
|
|
5132
|
-
"actor_name",
|
|
5133
|
-
"actor_version",
|
|
5134
|
-
"actor_key",
|
|
5135
|
-
"service_name"
|
|
5136
|
-
],
|
|
5137
|
-
action: {
|
|
5138
|
-
do: "update",
|
|
5139
|
-
set: {
|
|
5140
|
-
durable_state: "excluded",
|
|
5141
|
-
durable_version: "excluded",
|
|
5142
|
-
expires_at: "excluded",
|
|
5143
|
-
updated: "excluded"
|
|
5144
|
-
},
|
|
5145
|
-
where: "actor_session_state.durable_version <= excluded.durable_version"
|
|
5146
|
-
}
|
|
5147
|
-
}
|
|
5148
|
-
}
|
|
5149
|
-
};
|
|
5150
|
-
},
|
|
5151
|
-
"Validates and prepares actor_session_state payload for strict write-through persistence.",
|
|
5152
|
-
{ isSubMeta: true, concurrency: 100 }
|
|
5153
|
-
).then(insertAndValidateActorSessionStateTask).respondsTo(META_ACTOR_SESSION_STATE_PERSIST_INTENT);
|
|
5616
|
+
registerActorSessionPersistenceTasks();
|
|
5154
5617
|
CadenzaService.createMetaTask("Handle Intent Creation", (ctx) => {
|
|
5155
5618
|
const intentName = ctx.data?.name;
|
|
5156
5619
|
return {
|
|
@@ -5195,6 +5658,9 @@ function normalizeIntentToken(value) {
|
|
|
5195
5658
|
}
|
|
5196
5659
|
return normalized;
|
|
5197
5660
|
}
|
|
5661
|
+
function buildPostgresActorName(name) {
|
|
5662
|
+
return `${String(name ?? "").trim()}PostgresActor`;
|
|
5663
|
+
}
|
|
5198
5664
|
function validateIntentName(intentName) {
|
|
5199
5665
|
if (!intentName || typeof intentName !== "string") {
|
|
5200
5666
|
throw new Error("Intent name must be a non-empty string");
|
|
@@ -5332,7 +5798,8 @@ function resolveDataRows(data) {
|
|
|
5332
5798
|
}
|
|
5333
5799
|
var DatabaseController = class _DatabaseController {
|
|
5334
5800
|
constructor() {
|
|
5335
|
-
this.
|
|
5801
|
+
this.registrationsByActorName = /* @__PURE__ */ new Map();
|
|
5802
|
+
this.registrationsByActorToken = /* @__PURE__ */ new Map();
|
|
5336
5803
|
this.adminDbClient = new Pool({
|
|
5337
5804
|
connectionString: process.env.DATABASE_ADDRESS ?? "",
|
|
5338
5805
|
database: "postgres",
|
|
@@ -5343,15 +5810,11 @@ var DatabaseController = class _DatabaseController {
|
|
|
5343
5810
|
CadenzaService.createMetaTask(
|
|
5344
5811
|
"Route PostgresActor setup requests",
|
|
5345
5812
|
(ctx) => {
|
|
5346
|
-
const
|
|
5347
|
-
if (!serviceName) {
|
|
5348
|
-
return ctx;
|
|
5349
|
-
}
|
|
5350
|
-
const registration = this.registrationsByService.get(serviceName);
|
|
5813
|
+
const registration = this.resolveRegistration(ctx);
|
|
5351
5814
|
if (!registration) {
|
|
5352
5815
|
return ctx;
|
|
5353
5816
|
}
|
|
5354
|
-
|
|
5817
|
+
this.requestPostgresActorSetup(registration, ctx);
|
|
5355
5818
|
return ctx;
|
|
5356
5819
|
},
|
|
5357
5820
|
"Routes generic database init requests to actor-scoped setup signal.",
|
|
@@ -5363,23 +5826,25 @@ var DatabaseController = class _DatabaseController {
|
|
|
5363
5826
|
return this._instance;
|
|
5364
5827
|
}
|
|
5365
5828
|
reset() {
|
|
5366
|
-
for (const registration of this.
|
|
5829
|
+
for (const registration of this.registrationsByActorName.values()) {
|
|
5367
5830
|
const runtimeState = registration.actor.getRuntimeState(registration.actorKey);
|
|
5368
5831
|
if (runtimeState?.pool) {
|
|
5369
5832
|
runtimeState.pool.end().catch(() => void 0);
|
|
5370
5833
|
}
|
|
5371
5834
|
}
|
|
5372
|
-
this.
|
|
5835
|
+
this.registrationsByActorName.clear();
|
|
5836
|
+
this.registrationsByActorToken.clear();
|
|
5373
5837
|
this.adminDbClient.end().catch(() => void 0);
|
|
5374
5838
|
}
|
|
5375
|
-
createPostgresActor(
|
|
5376
|
-
const
|
|
5839
|
+
createPostgresActor(name, schema, description, options) {
|
|
5840
|
+
const actorName = buildPostgresActorName(name);
|
|
5841
|
+
const existing = this.registrationsByActorName.get(actorName);
|
|
5377
5842
|
if (existing) {
|
|
5378
5843
|
return existing;
|
|
5379
5844
|
}
|
|
5380
|
-
const actorName = `${serviceName}PostgresActor`;
|
|
5381
5845
|
const actorToken = normalizeIntentToken(actorName);
|
|
5382
|
-
const actorKey = String(options.databaseName ?? snakeCase(
|
|
5846
|
+
const actorKey = String(options.databaseName ?? snakeCase(name));
|
|
5847
|
+
const ownerServiceName = options.ownerServiceName ?? CadenzaService.serviceRegistry?.serviceName ?? null;
|
|
5383
5848
|
const optionTimeout = typeof options.timeoutMs === "number" ? Number(options.timeoutMs) : Number(options.timeout);
|
|
5384
5849
|
const safetyPolicy = {
|
|
5385
5850
|
statementTimeoutMs: normalizePositiveInteger(
|
|
@@ -5397,7 +5862,7 @@ var DatabaseController = class _DatabaseController {
|
|
|
5397
5862
|
const actor = CadenzaService.createActor(
|
|
5398
5863
|
{
|
|
5399
5864
|
name: actorName,
|
|
5400
|
-
description: "Specialized PostgresActor owning pool runtime state and schema-driven DB task generation.",
|
|
5865
|
+
description: description || "Specialized PostgresActor owning pool runtime state and schema-driven DB task generation.",
|
|
5401
5866
|
defaultKey: actorKey,
|
|
5402
5867
|
keyResolver: (input) => typeof input.databaseName === "string" ? input.databaseName : void 0,
|
|
5403
5868
|
loadPolicy: "eager",
|
|
@@ -5405,7 +5870,7 @@ var DatabaseController = class _DatabaseController {
|
|
|
5405
5870
|
initState: {
|
|
5406
5871
|
actorName,
|
|
5407
5872
|
actorToken,
|
|
5408
|
-
|
|
5873
|
+
ownerServiceName,
|
|
5409
5874
|
databaseName: actorKey,
|
|
5410
5875
|
status: "idle",
|
|
5411
5876
|
schemaVersion: Number(schema.version ?? 1),
|
|
@@ -5420,23 +5885,99 @@ var DatabaseController = class _DatabaseController {
|
|
|
5420
5885
|
{ isMeta: Boolean(options.isMeta) }
|
|
5421
5886
|
);
|
|
5422
5887
|
const registration = {
|
|
5423
|
-
|
|
5888
|
+
ownerServiceName,
|
|
5424
5889
|
databaseName: actorKey,
|
|
5425
5890
|
actorName,
|
|
5426
5891
|
actorToken,
|
|
5427
5892
|
actorKey,
|
|
5893
|
+
setupSignal: `meta.postgres_actor.setup_requested.${actorToken}`,
|
|
5894
|
+
setupDoneSignal: `meta.postgres_actor.setup_done.${actorToken}`,
|
|
5895
|
+
setupFailedSignal: `meta.postgres_actor.setup_failed.${actorToken}`,
|
|
5428
5896
|
actor,
|
|
5429
5897
|
schema,
|
|
5898
|
+
description,
|
|
5430
5899
|
options,
|
|
5431
5900
|
tasksGenerated: false,
|
|
5432
5901
|
intentNames: /* @__PURE__ */ new Set()
|
|
5433
5902
|
};
|
|
5434
|
-
this.
|
|
5903
|
+
this.registrationsByActorName.set(actorName, registration);
|
|
5904
|
+
this.registrationsByActorToken.set(actorToken, registration);
|
|
5435
5905
|
this.registerSetupTask(registration);
|
|
5436
5906
|
return registration;
|
|
5437
5907
|
}
|
|
5908
|
+
requestPostgresActorSetup(registrationOrName, ctx = {}) {
|
|
5909
|
+
const registration = typeof registrationOrName === "string" ? this.resolveRegistration({
|
|
5910
|
+
actorName: registrationOrName
|
|
5911
|
+
}) : registrationOrName;
|
|
5912
|
+
if (!registration) {
|
|
5913
|
+
return void 0;
|
|
5914
|
+
}
|
|
5915
|
+
const payload = {
|
|
5916
|
+
...ctx,
|
|
5917
|
+
actorName: registration.actorName,
|
|
5918
|
+
actorToken: registration.actorToken,
|
|
5919
|
+
databaseName: registration.databaseName,
|
|
5920
|
+
ownerServiceName: registration.ownerServiceName,
|
|
5921
|
+
options: {
|
|
5922
|
+
...ctx.options ?? {},
|
|
5923
|
+
actorName: registration.actorName,
|
|
5924
|
+
actorToken: registration.actorToken,
|
|
5925
|
+
ownerServiceName: registration.ownerServiceName,
|
|
5926
|
+
databaseName: registration.databaseName
|
|
5927
|
+
}
|
|
5928
|
+
};
|
|
5929
|
+
const runtimeState = registration.actor.getRuntimeState(registration.actorKey);
|
|
5930
|
+
if (runtimeState?.ready) {
|
|
5931
|
+
this.emitSetupDone(registration, payload);
|
|
5932
|
+
return registration;
|
|
5933
|
+
}
|
|
5934
|
+
CadenzaService.emit(registration.setupSignal, payload);
|
|
5935
|
+
return registration;
|
|
5936
|
+
}
|
|
5937
|
+
resolveRegistration(ctx) {
|
|
5938
|
+
const rawActorToken = String(
|
|
5939
|
+
ctx.options?.actorToken ?? ctx.actorToken ?? ""
|
|
5940
|
+
).trim();
|
|
5941
|
+
if (rawActorToken) {
|
|
5942
|
+
const actorToken = normalizeIntentToken(rawActorToken);
|
|
5943
|
+
const registration = this.registrationsByActorToken.get(actorToken);
|
|
5944
|
+
if (registration) {
|
|
5945
|
+
return registration;
|
|
5946
|
+
}
|
|
5947
|
+
}
|
|
5948
|
+
const rawActorName = String(
|
|
5949
|
+
ctx.options?.actorName ?? ctx.actorName ?? ctx.options?.postgresActorName ?? ctx.postgresActorName ?? ""
|
|
5950
|
+
).trim();
|
|
5951
|
+
if (rawActorName) {
|
|
5952
|
+
const registration = this.registrationsByActorName.get(rawActorName) ?? this.registrationsByActorName.get(buildPostgresActorName(rawActorName));
|
|
5953
|
+
if (registration) {
|
|
5954
|
+
return registration;
|
|
5955
|
+
}
|
|
5956
|
+
}
|
|
5957
|
+
const legacyServiceName = String(
|
|
5958
|
+
ctx.options?.serviceName ?? ctx.serviceName ?? ""
|
|
5959
|
+
).trim();
|
|
5960
|
+
if (legacyServiceName) {
|
|
5961
|
+
return this.registrationsByActorName.get(
|
|
5962
|
+
buildPostgresActorName(legacyServiceName)
|
|
5963
|
+
);
|
|
5964
|
+
}
|
|
5965
|
+
return void 0;
|
|
5966
|
+
}
|
|
5967
|
+
emitSetupDone(registration, payload) {
|
|
5968
|
+
const resolvedPayload = {
|
|
5969
|
+
...payload,
|
|
5970
|
+
actorName: registration.actorName,
|
|
5971
|
+
actorToken: registration.actorToken,
|
|
5972
|
+
databaseName: registration.databaseName,
|
|
5973
|
+
ownerServiceName: registration.ownerServiceName,
|
|
5974
|
+
__success: true
|
|
5975
|
+
};
|
|
5976
|
+
CadenzaService.emit(registration.setupDoneSignal, resolvedPayload);
|
|
5977
|
+
CadenzaService.emit("meta.postgres_actor.setup_done", resolvedPayload);
|
|
5978
|
+
CadenzaService.emit("meta.database.setup_done", resolvedPayload);
|
|
5979
|
+
}
|
|
5438
5980
|
registerSetupTask(registration) {
|
|
5439
|
-
const setupSignal = `meta.postgres_actor.setup_requested.${registration.actorToken}`;
|
|
5440
5981
|
CadenzaService.createMetaTask(
|
|
5441
5982
|
`Setup ${registration.actorName}`,
|
|
5442
5983
|
registration.actor.task(
|
|
@@ -5496,17 +6037,15 @@ var DatabaseController = class _DatabaseController {
|
|
|
5496
6037
|
lastError: null,
|
|
5497
6038
|
tables: Object.keys(registration.schema.tables ?? {})
|
|
5498
6039
|
});
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
databaseName: registration.databaseName,
|
|
5502
|
-
actorName: registration.actorName,
|
|
5503
|
-
__success: true
|
|
6040
|
+
this.emitSetupDone(registration, {
|
|
6041
|
+
...input
|
|
5504
6042
|
});
|
|
5505
6043
|
return {
|
|
5506
6044
|
...input,
|
|
5507
6045
|
__success: true,
|
|
5508
6046
|
actorName: registration.actorName,
|
|
5509
|
-
databaseName: registration.databaseName
|
|
6047
|
+
databaseName: registration.databaseName,
|
|
6048
|
+
ownerServiceName: registration.ownerServiceName
|
|
5510
6049
|
};
|
|
5511
6050
|
} catch (error) {
|
|
5512
6051
|
const message = errorMessage(error);
|
|
@@ -5530,7 +6069,11 @@ var DatabaseController = class _DatabaseController {
|
|
|
5530
6069
|
),
|
|
5531
6070
|
"Initializes PostgresActor runtime pool, applies schema, and generates CRUD tasks/intents.",
|
|
5532
6071
|
{ isMeta: true }
|
|
5533
|
-
).doOn(setupSignal)
|
|
6072
|
+
).doOn(registration.setupSignal).emitsOnFail(
|
|
6073
|
+
registration.setupFailedSignal,
|
|
6074
|
+
"meta.postgres_actor.setup_failed",
|
|
6075
|
+
"meta.database.setup_failed"
|
|
6076
|
+
);
|
|
5534
6077
|
}
|
|
5535
6078
|
createTargetPool(databaseName, statementTimeoutMs) {
|
|
5536
6079
|
const connectionString = this.buildDatabaseConnectionString(databaseName);
|
|
@@ -7706,6 +8249,165 @@ var GraphSyncController = class _GraphSyncController {
|
|
|
7706
8249
|
}
|
|
7707
8250
|
};
|
|
7708
8251
|
|
|
8252
|
+
// src/utils/bootstrap.ts
|
|
8253
|
+
var DEFAULT_BOOTSTRAP_GLOBAL_KEY = "__CADENZA_RUNTIME__";
|
|
8254
|
+
function normalizeString3(value) {
|
|
8255
|
+
if (typeof value !== "string") {
|
|
8256
|
+
return void 0;
|
|
8257
|
+
}
|
|
8258
|
+
const normalized = value.trim();
|
|
8259
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
8260
|
+
}
|
|
8261
|
+
function readEnvString(name) {
|
|
8262
|
+
if (typeof process === "undefined") {
|
|
8263
|
+
return void 0;
|
|
8264
|
+
}
|
|
8265
|
+
return normalizeString3(process.env?.[name]);
|
|
8266
|
+
}
|
|
8267
|
+
function readConfiguredPort(value) {
|
|
8268
|
+
if (value === void 0 || value === null || value === "") {
|
|
8269
|
+
return void 0;
|
|
8270
|
+
}
|
|
8271
|
+
const parsed = Number(value);
|
|
8272
|
+
if (!Number.isFinite(parsed)) {
|
|
8273
|
+
throw new Error(`Invalid port value: ${String(value)}`);
|
|
8274
|
+
}
|
|
8275
|
+
const normalized = Math.trunc(parsed);
|
|
8276
|
+
if (normalized <= 0) {
|
|
8277
|
+
throw new Error(`Port must be a positive integer: ${String(value)}`);
|
|
8278
|
+
}
|
|
8279
|
+
return normalized;
|
|
8280
|
+
}
|
|
8281
|
+
function buildBootstrapUrl(protocol, address, port) {
|
|
8282
|
+
return `${protocol}://${address}:${port}`;
|
|
8283
|
+
}
|
|
8284
|
+
function resolveInjectedBootstrapUrl(injectedGlobalKey) {
|
|
8285
|
+
if (typeof globalThis === "undefined") {
|
|
8286
|
+
return void 0;
|
|
8287
|
+
}
|
|
8288
|
+
const runtimeConfig = globalThis[injectedGlobalKey];
|
|
8289
|
+
return normalizeString3(runtimeConfig?.bootstrapUrl);
|
|
8290
|
+
}
|
|
8291
|
+
function resolveExplicitBootstrapValue(options) {
|
|
8292
|
+
const injectedGlobalKey = normalizeString3(options.bootstrap?.injectedGlobalKey) ?? DEFAULT_BOOTSTRAP_GLOBAL_KEY;
|
|
8293
|
+
const explicitBootstrapUrl = normalizeString3(options.bootstrap?.url);
|
|
8294
|
+
if (explicitBootstrapUrl) {
|
|
8295
|
+
return {
|
|
8296
|
+
value: explicitBootstrapUrl,
|
|
8297
|
+
port: readConfiguredPort(options.cadenzaDB?.port),
|
|
8298
|
+
injectedGlobalKey
|
|
8299
|
+
};
|
|
8300
|
+
}
|
|
8301
|
+
if (options.runtime === "browser") {
|
|
8302
|
+
const injected = resolveInjectedBootstrapUrl(injectedGlobalKey);
|
|
8303
|
+
if (injected) {
|
|
8304
|
+
return {
|
|
8305
|
+
value: injected,
|
|
8306
|
+
port: readConfiguredPort(options.cadenzaDB?.port),
|
|
8307
|
+
injectedGlobalKey
|
|
8308
|
+
};
|
|
8309
|
+
}
|
|
8310
|
+
}
|
|
8311
|
+
const explicitAddress = normalizeString3(options.cadenzaDB?.address);
|
|
8312
|
+
if (explicitAddress) {
|
|
8313
|
+
return {
|
|
8314
|
+
value: explicitAddress,
|
|
8315
|
+
port: readConfiguredPort(options.cadenzaDB?.port),
|
|
8316
|
+
injectedGlobalKey
|
|
8317
|
+
};
|
|
8318
|
+
}
|
|
8319
|
+
const envAddress = readEnvString("CADENZA_DB_ADDRESS");
|
|
8320
|
+
return {
|
|
8321
|
+
value: envAddress,
|
|
8322
|
+
port: readConfiguredPort(options.cadenzaDB?.port ?? readEnvString("CADENZA_DB_PORT")),
|
|
8323
|
+
injectedGlobalKey
|
|
8324
|
+
};
|
|
8325
|
+
}
|
|
8326
|
+
function readIntegerEnv(name, fallback) {
|
|
8327
|
+
const raw = readEnvString(name);
|
|
8328
|
+
if (!raw) {
|
|
8329
|
+
return fallback;
|
|
8330
|
+
}
|
|
8331
|
+
const parsed = Number(raw);
|
|
8332
|
+
if (!Number.isFinite(parsed)) {
|
|
8333
|
+
return fallback;
|
|
8334
|
+
}
|
|
8335
|
+
const normalized = Math.trunc(parsed);
|
|
8336
|
+
if (normalized <= 0) {
|
|
8337
|
+
return fallback;
|
|
8338
|
+
}
|
|
8339
|
+
return normalized;
|
|
8340
|
+
}
|
|
8341
|
+
function readStringEnv(name) {
|
|
8342
|
+
return readEnvString(name);
|
|
8343
|
+
}
|
|
8344
|
+
function readListEnv(name) {
|
|
8345
|
+
const raw = readEnvString(name);
|
|
8346
|
+
if (!raw) {
|
|
8347
|
+
return [];
|
|
8348
|
+
}
|
|
8349
|
+
return raw.split("|").map((entry) => entry.trim()).filter((entry) => entry.length > 0).map((entry) => entry.split(",").map((part) => part.trim()));
|
|
8350
|
+
}
|
|
8351
|
+
function resolveBootstrapEndpoint(options) {
|
|
8352
|
+
const { value, port: fallbackPort, injectedGlobalKey } = resolveExplicitBootstrapValue(options);
|
|
8353
|
+
if (!value) {
|
|
8354
|
+
throw new Error(
|
|
8355
|
+
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."
|
|
8356
|
+
);
|
|
8357
|
+
}
|
|
8358
|
+
const raw = value.trim();
|
|
8359
|
+
if (raw.length === 0) {
|
|
8360
|
+
throw new Error("Bootstrap URL cannot be empty");
|
|
8361
|
+
}
|
|
8362
|
+
if (raw.includes("://")) {
|
|
8363
|
+
const parsed2 = new URL(raw);
|
|
8364
|
+
const protocol2 = parsed2.protocol.replace(":", "");
|
|
8365
|
+
if (protocol2 !== "http" && protocol2 !== "https") {
|
|
8366
|
+
throw new Error(`Unsupported bootstrap protocol: ${parsed2.protocol}`);
|
|
8367
|
+
}
|
|
8368
|
+
if (parsed2.pathname && parsed2.pathname !== "/" && parsed2.pathname.trim().length > 0) {
|
|
8369
|
+
throw new Error(
|
|
8370
|
+
"Bootstrap URL must be an origin without a path component."
|
|
8371
|
+
);
|
|
8372
|
+
}
|
|
8373
|
+
const port2 = parsed2.port ? readConfiguredPort(parsed2.port) : fallbackPort;
|
|
8374
|
+
if (!port2) {
|
|
8375
|
+
throw new Error(
|
|
8376
|
+
"Bootstrap URL must include a port or CADENZA_DB_PORT must be provided."
|
|
8377
|
+
);
|
|
8378
|
+
}
|
|
8379
|
+
return {
|
|
8380
|
+
url: buildBootstrapUrl(protocol2, parsed2.hostname, port2),
|
|
8381
|
+
protocol: protocol2,
|
|
8382
|
+
address: parsed2.hostname,
|
|
8383
|
+
port: port2,
|
|
8384
|
+
exposed: protocol2 === "https",
|
|
8385
|
+
injectedGlobalKey
|
|
8386
|
+
};
|
|
8387
|
+
}
|
|
8388
|
+
if (raw.includes("/") || raw.includes("?") || raw.includes("#")) {
|
|
8389
|
+
throw new Error(
|
|
8390
|
+
"Bootstrap address without protocol must not include a path, query, or hash."
|
|
8391
|
+
);
|
|
8392
|
+
}
|
|
8393
|
+
const parsed = new URL(`http://${raw}`);
|
|
8394
|
+
const protocol = "http";
|
|
8395
|
+
const port = parsed.port ? readConfiguredPort(parsed.port) : fallbackPort;
|
|
8396
|
+
if (!port) {
|
|
8397
|
+
throw new Error(
|
|
8398
|
+
"Bootstrap address must include a port or CADENZA_DB_PORT must be provided."
|
|
8399
|
+
);
|
|
8400
|
+
}
|
|
8401
|
+
return {
|
|
8402
|
+
url: buildBootstrapUrl(protocol, parsed.hostname, port),
|
|
8403
|
+
protocol,
|
|
8404
|
+
address: parsed.hostname,
|
|
8405
|
+
port,
|
|
8406
|
+
exposed: false,
|
|
8407
|
+
injectedGlobalKey
|
|
8408
|
+
};
|
|
8409
|
+
}
|
|
8410
|
+
|
|
7709
8411
|
// src/Cadenza.ts
|
|
7710
8412
|
var CadenzaService = class {
|
|
7711
8413
|
/**
|
|
@@ -7724,11 +8426,60 @@ var CadenzaService = class {
|
|
|
7724
8426
|
this.metaRunner = Cadenza.metaRunner;
|
|
7725
8427
|
this.registry = Cadenza.registry;
|
|
7726
8428
|
this.serviceRegistry = ServiceRegistry.instance;
|
|
7727
|
-
SignalController.instance;
|
|
7728
8429
|
RestController.instance;
|
|
7729
8430
|
SocketController.instance;
|
|
7730
8431
|
console.log("BOOTSTRAPPED");
|
|
7731
8432
|
}
|
|
8433
|
+
static ensureTransportControllers(isFrontend) {
|
|
8434
|
+
if (!isFrontend) {
|
|
8435
|
+
SignalController.instance;
|
|
8436
|
+
}
|
|
8437
|
+
}
|
|
8438
|
+
static setHydrationResults(hydration) {
|
|
8439
|
+
this.hydratedInquiryResults = /* @__PURE__ */ new Map();
|
|
8440
|
+
const initialInquiryResults = hydration?.initialInquiryResults ?? {};
|
|
8441
|
+
for (const [key, value] of Object.entries(initialInquiryResults)) {
|
|
8442
|
+
this.hydratedInquiryResults.set(key, value);
|
|
8443
|
+
}
|
|
8444
|
+
}
|
|
8445
|
+
static consumeHydratedInquiryResult(hydrationKey) {
|
|
8446
|
+
if (!hydrationKey) {
|
|
8447
|
+
return void 0;
|
|
8448
|
+
}
|
|
8449
|
+
const result = this.hydratedInquiryResults.get(hydrationKey);
|
|
8450
|
+
if (result === void 0) {
|
|
8451
|
+
return void 0;
|
|
8452
|
+
}
|
|
8453
|
+
this.hydratedInquiryResults.delete(hydrationKey);
|
|
8454
|
+
return result;
|
|
8455
|
+
}
|
|
8456
|
+
static ensureFrontendSyncLoop() {
|
|
8457
|
+
if (this.frontendSyncScheduled) {
|
|
8458
|
+
return;
|
|
8459
|
+
}
|
|
8460
|
+
this.frontendSyncScheduled = true;
|
|
8461
|
+
Cadenza.interval("meta.sync_requested", { __syncing: false }, 18e4);
|
|
8462
|
+
Cadenza.schedule("meta.sync_requested", { __syncing: false }, 250);
|
|
8463
|
+
}
|
|
8464
|
+
static normalizeDeclaredTransports(transports, serviceId) {
|
|
8465
|
+
return (transports ?? []).map((transport) => normalizeServiceTransportConfig(transport)).filter(
|
|
8466
|
+
(transport) => !!transport
|
|
8467
|
+
).map((transport, index) => ({
|
|
8468
|
+
...transport,
|
|
8469
|
+
uuid: `${serviceId}-transport-${index + 1}`
|
|
8470
|
+
}));
|
|
8471
|
+
}
|
|
8472
|
+
static createBootstrapTransport(serviceInstanceId, role, endpoint) {
|
|
8473
|
+
return {
|
|
8474
|
+
uuid: `${serviceInstanceId}-${role}-bootstrap`,
|
|
8475
|
+
service_instance_id: serviceInstanceId,
|
|
8476
|
+
role,
|
|
8477
|
+
origin: endpoint.url,
|
|
8478
|
+
protocols: ["rest", "socket"],
|
|
8479
|
+
security_profile: null,
|
|
8480
|
+
auth_strategy: null
|
|
8481
|
+
};
|
|
8482
|
+
}
|
|
7732
8483
|
/**
|
|
7733
8484
|
* Validates the provided service name based on specific rules.
|
|
7734
8485
|
*
|
|
@@ -7841,6 +8592,12 @@ var CadenzaService = class {
|
|
|
7841
8592
|
}
|
|
7842
8593
|
static async inquire(inquiry, context, options = {}) {
|
|
7843
8594
|
this.bootstrap();
|
|
8595
|
+
const hydratedResult = this.consumeHydratedInquiryResult(
|
|
8596
|
+
options.hydrationKey
|
|
8597
|
+
);
|
|
8598
|
+
if (hydratedResult !== void 0) {
|
|
8599
|
+
return hydratedResult;
|
|
8600
|
+
}
|
|
7844
8601
|
const observer = this.inquiryBroker?.inquiryObservers.get(inquiry);
|
|
7845
8602
|
const allResponders = observer ? Array.from(observer.tasks).map((task) => ({
|
|
7846
8603
|
task,
|
|
@@ -8445,58 +9202,97 @@ var CadenzaService = class {
|
|
|
8445
9202
|
const serviceId = options.customServiceId ?? uuid3();
|
|
8446
9203
|
this.serviceRegistry.serviceName = serviceName;
|
|
8447
9204
|
this.serviceRegistry.serviceInstanceId = serviceId;
|
|
9205
|
+
this.setHydrationResults(options.hydration);
|
|
9206
|
+
const explicitFrontendMode = options.isFrontend;
|
|
8448
9207
|
options = {
|
|
8449
9208
|
loadBalance: true,
|
|
8450
9209
|
useSocket: true,
|
|
8451
9210
|
displayName: void 0,
|
|
8452
9211
|
isMeta: false,
|
|
8453
|
-
port:
|
|
8454
|
-
securityProfile:
|
|
8455
|
-
networkMode:
|
|
9212
|
+
port: readIntegerEnv("HTTP_PORT", 3e3),
|
|
9213
|
+
securityProfile: readStringEnv("SECURITY_PROFILE") ?? "medium",
|
|
9214
|
+
networkMode: readStringEnv("NETWORK_MODE") ?? "dev",
|
|
8456
9215
|
retryCount: 3,
|
|
8457
9216
|
cadenzaDB: {
|
|
8458
|
-
connect: true
|
|
8459
|
-
address: process.env.CADENZA_DB_ADDRESS ?? "localhost",
|
|
8460
|
-
port: parseInt(process.env.CADENZA_DB_PORT ?? "5000")
|
|
9217
|
+
connect: true
|
|
8461
9218
|
},
|
|
8462
|
-
relatedServices:
|
|
8463
|
-
|
|
8464
|
-
) : [],
|
|
8465
|
-
isFrontend: isBrowser,
|
|
9219
|
+
relatedServices: readListEnv("RELATED_SERVICES"),
|
|
9220
|
+
isFrontend: typeof explicitFrontendMode === "boolean" ? explicitFrontendMode : isBrowser,
|
|
8466
9221
|
...options
|
|
8467
9222
|
};
|
|
9223
|
+
const isFrontend = !!options.isFrontend;
|
|
9224
|
+
const declaredTransports = this.normalizeDeclaredTransports(
|
|
9225
|
+
options.transports,
|
|
9226
|
+
serviceId
|
|
9227
|
+
);
|
|
9228
|
+
this.serviceRegistry.isFrontend = isFrontend;
|
|
9229
|
+
this.serviceRegistry.useSocket = !!options.useSocket;
|
|
9230
|
+
this.serviceRegistry.retryCount = options.retryCount ?? 3;
|
|
9231
|
+
this.ensureTransportControllers(isFrontend);
|
|
9232
|
+
const resolvedBootstrapEndpoint = options.cadenzaDB?.connect ? resolveBootstrapEndpoint({
|
|
9233
|
+
runtime: isFrontend ? "browser" : "server",
|
|
9234
|
+
bootstrap: options.bootstrap,
|
|
9235
|
+
cadenzaDB: options.cadenzaDB
|
|
9236
|
+
}) : void 0;
|
|
9237
|
+
if (resolvedBootstrapEndpoint) {
|
|
9238
|
+
options.cadenzaDB = {
|
|
9239
|
+
...options.cadenzaDB,
|
|
9240
|
+
connect: true,
|
|
9241
|
+
address: resolvedBootstrapEndpoint.address,
|
|
9242
|
+
port: resolvedBootstrapEndpoint.port
|
|
9243
|
+
};
|
|
9244
|
+
}
|
|
8468
9245
|
if (options.cadenzaDB?.connect) {
|
|
8469
9246
|
this.emit("meta.initializing_service", {
|
|
8470
9247
|
// Seed the CadenzaDB
|
|
8471
9248
|
serviceInstance: {
|
|
8472
9249
|
uuid: "cadenza-db",
|
|
8473
9250
|
serviceName: "CadenzaDB",
|
|
8474
|
-
address: options.cadenzaDB?.address,
|
|
8475
|
-
port: options.cadenzaDB?.port,
|
|
8476
|
-
exposed: options.networkMode !== "dev",
|
|
8477
9251
|
numberOfRunningGraphs: 0,
|
|
8478
9252
|
isActive: true,
|
|
8479
9253
|
// Assume it is deployed
|
|
8480
9254
|
isNonResponsive: false,
|
|
8481
9255
|
isBlocked: false,
|
|
8482
|
-
health: {}
|
|
9256
|
+
health: {},
|
|
9257
|
+
isFrontend: false,
|
|
9258
|
+
transports: resolvedBootstrapEndpoint ? [
|
|
9259
|
+
this.createBootstrapTransport(
|
|
9260
|
+
"cadenza-db",
|
|
9261
|
+
isFrontend ? "public" : "internal",
|
|
9262
|
+
resolvedBootstrapEndpoint
|
|
9263
|
+
)
|
|
9264
|
+
] : []
|
|
8483
9265
|
}
|
|
8484
9266
|
});
|
|
8485
9267
|
}
|
|
8486
9268
|
options.relatedServices?.forEach((service) => {
|
|
9269
|
+
const relatedTransport = normalizeServiceTransportConfig({
|
|
9270
|
+
role: isFrontend ? "public" : "internal",
|
|
9271
|
+
origin: service[2].includes("://") ? service[2] : `http://${service[2]}`,
|
|
9272
|
+
protocols: ["rest", "socket"]
|
|
9273
|
+
});
|
|
8487
9274
|
this.emit("meta.initializing_service", {
|
|
8488
9275
|
serviceInstance: {
|
|
8489
9276
|
uuid: service[0],
|
|
8490
9277
|
serviceName: service[1],
|
|
8491
|
-
address: service[2].split(":")[0],
|
|
8492
|
-
port: service[2].split(":")[1] ?? 3e3,
|
|
8493
|
-
exposed: options.networkMode !== "dev",
|
|
8494
9278
|
numberOfRunningGraphs: 0,
|
|
8495
9279
|
isActive: true,
|
|
8496
9280
|
// Assume it is deployed
|
|
8497
9281
|
isNonResponsive: false,
|
|
8498
9282
|
isBlocked: false,
|
|
8499
|
-
health: {}
|
|
9283
|
+
health: {},
|
|
9284
|
+
isFrontend: false,
|
|
9285
|
+
transports: relatedTransport ? [
|
|
9286
|
+
{
|
|
9287
|
+
uuid: `${service[0]}-${relatedTransport.role}`,
|
|
9288
|
+
service_instance_id: service[0],
|
|
9289
|
+
role: relatedTransport.role,
|
|
9290
|
+
origin: relatedTransport.origin,
|
|
9291
|
+
protocols: relatedTransport.protocols ?? ["rest", "socket"],
|
|
9292
|
+
security_profile: relatedTransport.securityProfile ?? null,
|
|
9293
|
+
auth_strategy: relatedTransport.authStrategy ?? null
|
|
9294
|
+
}
|
|
9295
|
+
] : []
|
|
8500
9296
|
}
|
|
8501
9297
|
});
|
|
8502
9298
|
});
|
|
@@ -8517,7 +9313,9 @@ var CadenzaService = class {
|
|
|
8517
9313
|
__networkMode: options.networkMode,
|
|
8518
9314
|
__retryCount: options.retryCount,
|
|
8519
9315
|
__cadenzaDBConnect: options.cadenzaDB?.connect,
|
|
8520
|
-
__isDatabase: options.isDatabase
|
|
9316
|
+
__isDatabase: options.isDatabase,
|
|
9317
|
+
__isFrontend: isFrontend,
|
|
9318
|
+
__declaredTransports: declaredTransports
|
|
8521
9319
|
};
|
|
8522
9320
|
if (options.cadenzaDB?.connect) {
|
|
8523
9321
|
this.createEphemeralMetaTask("Create service", async (context, emit) => {
|
|
@@ -8533,12 +9331,42 @@ var CadenzaService = class {
|
|
|
8533
9331
|
}).doOn("meta.rest.handshake");
|
|
8534
9332
|
}
|
|
8535
9333
|
this.createMetaTask("Handle service setup completion", () => {
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
9334
|
+
if (isFrontend) {
|
|
9335
|
+
registerActorSessionPersistenceTasks();
|
|
9336
|
+
this.ensureFrontendSyncLoop();
|
|
9337
|
+
} else {
|
|
9338
|
+
GraphMetadataController.instance;
|
|
9339
|
+
GraphSyncController.instance.isCadenzaDBReady = !!options.cadenzaDB?.connect;
|
|
9340
|
+
GraphSyncController.instance.init();
|
|
9341
|
+
}
|
|
8539
9342
|
this.log("Service created.");
|
|
8540
9343
|
return true;
|
|
8541
9344
|
}).doOn("meta.service_registry.instance_inserted");
|
|
9345
|
+
if (!options.cadenzaDB?.connect && isFrontend) {
|
|
9346
|
+
Cadenza.schedule(
|
|
9347
|
+
"meta.service_registry.instance_registration_requested",
|
|
9348
|
+
{
|
|
9349
|
+
data: {
|
|
9350
|
+
uuid: serviceId,
|
|
9351
|
+
process_pid: 1,
|
|
9352
|
+
service_name: serviceName,
|
|
9353
|
+
is_frontend: true,
|
|
9354
|
+
is_active: true,
|
|
9355
|
+
is_non_responsive: false,
|
|
9356
|
+
is_blocked: false,
|
|
9357
|
+
health: {}
|
|
9358
|
+
},
|
|
9359
|
+
transportData: [],
|
|
9360
|
+
__serviceName: serviceName,
|
|
9361
|
+
__serviceInstanceId: serviceId,
|
|
9362
|
+
__useSocket: options.useSocket,
|
|
9363
|
+
__retryCount: options.retryCount,
|
|
9364
|
+
__isFrontend: true,
|
|
9365
|
+
__skipRemoteExecution: true
|
|
9366
|
+
},
|
|
9367
|
+
0
|
|
9368
|
+
);
|
|
9369
|
+
}
|
|
8542
9370
|
this.serviceCreated = true;
|
|
8543
9371
|
}
|
|
8544
9372
|
/**
|
|
@@ -8554,87 +9382,52 @@ var CadenzaService = class {
|
|
|
8554
9382
|
this.createCadenzaService(serviceName, description, options);
|
|
8555
9383
|
}
|
|
8556
9384
|
/**
|
|
8557
|
-
* Creates and initializes a PostgresActor
|
|
8558
|
-
* This is
|
|
9385
|
+
* Creates and initializes a specialized PostgresActor.
|
|
9386
|
+
* This is actor-only and does not create or register a network service.
|
|
8559
9387
|
*
|
|
8560
|
-
* @param {string} name - Logical
|
|
9388
|
+
* @param {string} name - Logical PostgresActor name.
|
|
8561
9389
|
* @param {DatabaseSchemaDefinition} schema - Database schema definition.
|
|
8562
|
-
* @param {string} [description=""] - Optional human-readable description.
|
|
8563
|
-
* @param {ServerOptions & DatabaseOptions} [options={}] -
|
|
9390
|
+
* @param {string} [description=""] - Optional human-readable actor description.
|
|
9391
|
+
* @param {ServerOptions & DatabaseOptions} [options={}] - Actor/database runtime options.
|
|
8564
9392
|
* @return {void}
|
|
8565
9393
|
*/
|
|
8566
9394
|
static createPostgresActor(name, schema, description = "", options = {}) {
|
|
8567
|
-
if (isBrowser) {
|
|
9395
|
+
if (isBrowser || options.isFrontend) {
|
|
8568
9396
|
console.warn(
|
|
8569
|
-
"
|
|
9397
|
+
"PostgresActor creation is not supported in frontend mode."
|
|
8570
9398
|
);
|
|
8571
9399
|
return;
|
|
8572
9400
|
}
|
|
8573
|
-
if (this.serviceCreated) return;
|
|
8574
9401
|
this.bootstrap();
|
|
8575
|
-
this.
|
|
9402
|
+
this.validateName(name);
|
|
8576
9403
|
const databaseController = DatabaseController.instance;
|
|
8577
|
-
|
|
8578
|
-
loadBalance: true,
|
|
8579
|
-
useSocket: true,
|
|
8580
|
-
displayName: void 0,
|
|
8581
|
-
isMeta: false,
|
|
8582
|
-
port: parseInt(process.env.HTTP_PORT ?? "3000"),
|
|
8583
|
-
securityProfile: process.env.SECURITY_PROFILE ?? "medium",
|
|
8584
|
-
networkMode: process.env.NETWORK_MODE ?? "dev",
|
|
8585
|
-
retryCount: 3,
|
|
8586
|
-
cadenzaDB: {
|
|
8587
|
-
connect: true,
|
|
8588
|
-
address: process.env.CADENZA_DB_ADDRESS ?? "localhost",
|
|
8589
|
-
port: parseInt(process.env.CADENZA_DB_PORT ?? "5000")
|
|
8590
|
-
},
|
|
8591
|
-
databaseType: "postgres",
|
|
8592
|
-
databaseName: snakeCase2(name),
|
|
8593
|
-
poolSize: parseInt(process.env.DATABASE_POOL_SIZE ?? "10"),
|
|
8594
|
-
isDatabase: true,
|
|
8595
|
-
...options
|
|
8596
|
-
};
|
|
9404
|
+
const normalizedOptions = this.normalizePostgresActorOptions(name, options);
|
|
8597
9405
|
const registration = databaseController.createPostgresActor(
|
|
8598
9406
|
name,
|
|
8599
9407
|
schema,
|
|
8600
|
-
|
|
9408
|
+
description,
|
|
9409
|
+
normalizedOptions
|
|
8601
9410
|
);
|
|
8602
9411
|
console.log("Creating PostgresActor", {
|
|
8603
|
-
|
|
9412
|
+
name,
|
|
8604
9413
|
actorName: registration.actorName,
|
|
8605
|
-
|
|
9414
|
+
ownerServiceName: normalizedOptions.ownerServiceName ?? null,
|
|
9415
|
+
options: normalizedOptions
|
|
8606
9416
|
});
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
9417
|
+
databaseController.requestPostgresActorSetup(registration, {
|
|
9418
|
+
actorName: registration.actorName,
|
|
9419
|
+
actorToken: registration.actorToken,
|
|
9420
|
+
databaseName: normalizedOptions.databaseName,
|
|
9421
|
+
ownerServiceName: normalizedOptions.ownerServiceName ?? null
|
|
8611
9422
|
});
|
|
8612
|
-
this.createMetaTask("Set database connection", () => {
|
|
8613
|
-
this.createMetaTask("Insert database service bridge", (_, emit) => {
|
|
8614
|
-
emit("global.meta.created_database_service", {
|
|
8615
|
-
data: {
|
|
8616
|
-
service_name: name,
|
|
8617
|
-
description,
|
|
8618
|
-
schema,
|
|
8619
|
-
is_meta: options.isMeta
|
|
8620
|
-
}
|
|
8621
|
-
});
|
|
8622
|
-
this.log("Database service created", {
|
|
8623
|
-
name,
|
|
8624
|
-
isMeta: options.isMeta,
|
|
8625
|
-
actorName: registration.actorName
|
|
8626
|
-
});
|
|
8627
|
-
}).doOn("meta.service_registry.service_inserted");
|
|
8628
|
-
this.createCadenzaService(name, description, options);
|
|
8629
|
-
}).doOn("meta.database.setup_done");
|
|
8630
9423
|
}
|
|
8631
9424
|
/**
|
|
8632
|
-
* Creates a meta PostgresActor
|
|
9425
|
+
* Creates a meta PostgresActor.
|
|
8633
9426
|
*
|
|
8634
|
-
* @param {string} name - Logical
|
|
9427
|
+
* @param {string} name - Logical PostgresActor name.
|
|
8635
9428
|
* @param {DatabaseSchemaDefinition} schema - Database schema definition.
|
|
8636
9429
|
* @param {string} [description=""] - Optional description.
|
|
8637
|
-
* @param {ServerOptions & DatabaseOptions} [options={}] - Optional
|
|
9430
|
+
* @param {ServerOptions & DatabaseOptions} [options={}] - Optional actor/database options.
|
|
8638
9431
|
* @return {void}
|
|
8639
9432
|
*/
|
|
8640
9433
|
static createMetaPostgresActor(name, schema, description = "", options = {}) {
|
|
@@ -8643,10 +9436,84 @@ var CadenzaService = class {
|
|
|
8643
9436
|
this.createPostgresActor(name, schema, description, options);
|
|
8644
9437
|
}
|
|
8645
9438
|
/**
|
|
8646
|
-
*
|
|
9439
|
+
* Creates a dedicated database service by composing a PostgresActor and a Cadenza service.
|
|
8647
9440
|
*/
|
|
8648
9441
|
static createDatabaseService(name, schema, description = "", options = {}) {
|
|
8649
|
-
|
|
9442
|
+
if (isBrowser || options.isFrontend) {
|
|
9443
|
+
console.warn(
|
|
9444
|
+
"Database service creation is not supported in frontend mode. Use the CadenzaDB service instead."
|
|
9445
|
+
);
|
|
9446
|
+
return;
|
|
9447
|
+
}
|
|
9448
|
+
if (this.serviceCreated) return;
|
|
9449
|
+
this.bootstrap();
|
|
9450
|
+
this.validateName(name);
|
|
9451
|
+
this.validateServiceName(name);
|
|
9452
|
+
const databaseController = DatabaseController.instance;
|
|
9453
|
+
const actorOptions = this.normalizePostgresActorOptions(name, {
|
|
9454
|
+
...options,
|
|
9455
|
+
ownerServiceName: options.ownerServiceName ?? name
|
|
9456
|
+
});
|
|
9457
|
+
const serviceOptions = this.normalizeDatabaseServiceOptions(name, {
|
|
9458
|
+
...options,
|
|
9459
|
+
ownerServiceName: actorOptions.ownerServiceName
|
|
9460
|
+
});
|
|
9461
|
+
const registration = databaseController.createPostgresActor(
|
|
9462
|
+
name,
|
|
9463
|
+
schema,
|
|
9464
|
+
description,
|
|
9465
|
+
actorOptions
|
|
9466
|
+
);
|
|
9467
|
+
this.registerDatabaseServiceBridgeTask(
|
|
9468
|
+
name,
|
|
9469
|
+
description,
|
|
9470
|
+
schema,
|
|
9471
|
+
Boolean(serviceOptions.isMeta),
|
|
9472
|
+
registration.actorName
|
|
9473
|
+
);
|
|
9474
|
+
const createServiceTaskName = `Create database service ${name} after ${registration.actorName} setup`;
|
|
9475
|
+
if (!this.get(createServiceTaskName)) {
|
|
9476
|
+
this.createMetaTask(
|
|
9477
|
+
createServiceTaskName,
|
|
9478
|
+
() => {
|
|
9479
|
+
this.createCadenzaService(name, description, serviceOptions);
|
|
9480
|
+
return true;
|
|
9481
|
+
},
|
|
9482
|
+
"Creates the networked database service after PostgresActor setup completes."
|
|
9483
|
+
).doOn(registration.setupDoneSignal);
|
|
9484
|
+
}
|
|
9485
|
+
const setupFailureTaskName = `Handle database service ${name} bootstrap failure`;
|
|
9486
|
+
if (!this.get(setupFailureTaskName)) {
|
|
9487
|
+
this.createMetaTask(
|
|
9488
|
+
setupFailureTaskName,
|
|
9489
|
+
(ctx) => {
|
|
9490
|
+
this.log(
|
|
9491
|
+
"Database service bootstrap failed before service creation.",
|
|
9492
|
+
{
|
|
9493
|
+
serviceName: name,
|
|
9494
|
+
actorName: registration.actorName,
|
|
9495
|
+
databaseName: registration.databaseName,
|
|
9496
|
+
error: ctx.__error
|
|
9497
|
+
},
|
|
9498
|
+
"error"
|
|
9499
|
+
);
|
|
9500
|
+
return true;
|
|
9501
|
+
},
|
|
9502
|
+
"Logs PostgresActor setup failures for database service bootstrap."
|
|
9503
|
+
).doOn(registration.setupFailedSignal);
|
|
9504
|
+
}
|
|
9505
|
+
console.log("Creating database service wrapper", {
|
|
9506
|
+
serviceName: name,
|
|
9507
|
+
actorName: registration.actorName,
|
|
9508
|
+
actorOptions,
|
|
9509
|
+
serviceOptions
|
|
9510
|
+
});
|
|
9511
|
+
databaseController.requestPostgresActorSetup(registration, {
|
|
9512
|
+
actorName: registration.actorName,
|
|
9513
|
+
actorToken: registration.actorToken,
|
|
9514
|
+
databaseName: actorOptions.databaseName,
|
|
9515
|
+
ownerServiceName: actorOptions.ownerServiceName ?? name
|
|
9516
|
+
});
|
|
8650
9517
|
}
|
|
8651
9518
|
/**
|
|
8652
9519
|
* Creates a meta database service with the specified configuration.
|
|
@@ -8658,7 +9525,71 @@ var CadenzaService = class {
|
|
|
8658
9525
|
* @return {void} - This method does not return a value.
|
|
8659
9526
|
*/
|
|
8660
9527
|
static createMetaDatabaseService(name, schema, description = "", options = {}) {
|
|
8661
|
-
this.
|
|
9528
|
+
this.createDatabaseService(name, schema, description, {
|
|
9529
|
+
...options,
|
|
9530
|
+
isMeta: true
|
|
9531
|
+
});
|
|
9532
|
+
}
|
|
9533
|
+
static normalizePostgresActorOptions(name, options = {}) {
|
|
9534
|
+
return {
|
|
9535
|
+
isMeta: false,
|
|
9536
|
+
retryCount: 3,
|
|
9537
|
+
databaseType: "postgres",
|
|
9538
|
+
databaseName: snakeCase2(name),
|
|
9539
|
+
poolSize: readIntegerEnv("DATABASE_POOL_SIZE", 10),
|
|
9540
|
+
ownerServiceName: options.ownerServiceName ?? this.serviceRegistry?.serviceName ?? null,
|
|
9541
|
+
...options
|
|
9542
|
+
};
|
|
9543
|
+
}
|
|
9544
|
+
static normalizeDatabaseServiceOptions(name, options = {}) {
|
|
9545
|
+
return {
|
|
9546
|
+
loadBalance: true,
|
|
9547
|
+
useSocket: true,
|
|
9548
|
+
displayName: void 0,
|
|
9549
|
+
isMeta: false,
|
|
9550
|
+
port: readIntegerEnv("HTTP_PORT", 3e3),
|
|
9551
|
+
securityProfile: readStringEnv("SECURITY_PROFILE") ?? "medium",
|
|
9552
|
+
networkMode: readStringEnv("NETWORK_MODE") ?? "dev",
|
|
9553
|
+
retryCount: 3,
|
|
9554
|
+
cadenzaDB: {
|
|
9555
|
+
connect: true
|
|
9556
|
+
},
|
|
9557
|
+
databaseType: "postgres",
|
|
9558
|
+
databaseName: snakeCase2(name),
|
|
9559
|
+
poolSize: readIntegerEnv("DATABASE_POOL_SIZE", 10),
|
|
9560
|
+
isDatabase: true,
|
|
9561
|
+
ownerServiceName: options.ownerServiceName ?? name,
|
|
9562
|
+
...options
|
|
9563
|
+
};
|
|
9564
|
+
}
|
|
9565
|
+
static registerDatabaseServiceBridgeTask(serviceName, description, schema, isMeta, actorName) {
|
|
9566
|
+
const taskName = `Insert database service bridge ${serviceName}`;
|
|
9567
|
+
if (this.get(taskName)) {
|
|
9568
|
+
return;
|
|
9569
|
+
}
|
|
9570
|
+
this.createMetaTask(
|
|
9571
|
+
taskName,
|
|
9572
|
+
(ctx, emit) => {
|
|
9573
|
+
if (ctx.__serviceName && ctx.__serviceName !== serviceName) {
|
|
9574
|
+
return false;
|
|
9575
|
+
}
|
|
9576
|
+
emit("global.meta.created_database_service", {
|
|
9577
|
+
data: {
|
|
9578
|
+
service_name: serviceName,
|
|
9579
|
+
description,
|
|
9580
|
+
schema,
|
|
9581
|
+
is_meta: isMeta
|
|
9582
|
+
}
|
|
9583
|
+
});
|
|
9584
|
+
this.log("Database service created", {
|
|
9585
|
+
name: serviceName,
|
|
9586
|
+
isMeta,
|
|
9587
|
+
actorName
|
|
9588
|
+
});
|
|
9589
|
+
return true;
|
|
9590
|
+
},
|
|
9591
|
+
"Bridges database service creation into the global metadata signal."
|
|
9592
|
+
).doOn("meta.service_registry.service_inserted");
|
|
8662
9593
|
}
|
|
8663
9594
|
static createActor(spec, options = {}) {
|
|
8664
9595
|
this.bootstrap();
|
|
@@ -9011,14 +9942,14 @@ var CadenzaService = class {
|
|
|
9011
9942
|
return Cadenza.createEphemeralTask(name, func, description, options);
|
|
9012
9943
|
}
|
|
9013
9944
|
/**
|
|
9014
|
-
* Creates an ephemeral meta
|
|
9945
|
+
* Creates an ephemeral meta-task with the specified name, function, description, and options.
|
|
9015
9946
|
* See {@link createEphemeralTask} and {@link createMetaTask} for more details.
|
|
9016
9947
|
*
|
|
9017
9948
|
* @param {string} name - The name of the task to be created.
|
|
9018
9949
|
* @param {TaskFunction} func - The function to be executed as part of the task.
|
|
9019
9950
|
* @param {string} [description] - An optional description of the task.
|
|
9020
9951
|
* @param {TaskOptions & EphemeralTaskOptions} [options={}] - Additional options for configuring the task.
|
|
9021
|
-
* @return {EphemeralTask} The created ephemeral meta
|
|
9952
|
+
* @return {EphemeralTask} The created ephemeral meta-task.
|
|
9022
9953
|
*/
|
|
9023
9954
|
static createEphemeralMetaTask(name, func, description, options = {}) {
|
|
9024
9955
|
this.bootstrap();
|
|
@@ -9073,12 +10004,19 @@ var CadenzaService = class {
|
|
|
9073
10004
|
}
|
|
9074
10005
|
static reset() {
|
|
9075
10006
|
Cadenza.reset();
|
|
9076
|
-
this.serviceRegistry
|
|
10007
|
+
this.serviceRegistry?.reset();
|
|
10008
|
+
this.isBootstrapped = false;
|
|
10009
|
+
this.serviceCreated = false;
|
|
10010
|
+
this.warnedInvalidMetaIntentResponderKeys = /* @__PURE__ */ new Set();
|
|
10011
|
+
this.hydratedInquiryResults = /* @__PURE__ */ new Map();
|
|
10012
|
+
this.frontendSyncScheduled = false;
|
|
9077
10013
|
}
|
|
9078
10014
|
};
|
|
9079
10015
|
CadenzaService.isBootstrapped = false;
|
|
9080
10016
|
CadenzaService.serviceCreated = false;
|
|
9081
10017
|
CadenzaService.warnedInvalidMetaIntentResponderKeys = /* @__PURE__ */ new Set();
|
|
10018
|
+
CadenzaService.hydratedInquiryResults = /* @__PURE__ */ new Map();
|
|
10019
|
+
CadenzaService.frontendSyncScheduled = false;
|
|
9082
10020
|
|
|
9083
10021
|
// src/index.ts
|
|
9084
10022
|
import {
|
|
@@ -9088,9 +10026,274 @@ import {
|
|
|
9088
10026
|
GraphRoutine as GraphRoutine2,
|
|
9089
10027
|
Task as Task4
|
|
9090
10028
|
} from "@cadenza.io/core";
|
|
10029
|
+
|
|
10030
|
+
// src/ssr/createSSRInquiryBridge.ts
|
|
10031
|
+
import { v4 as uuid4 } from "uuid";
|
|
10032
|
+
function ensureFetch() {
|
|
10033
|
+
if (typeof globalThis.fetch !== "function") {
|
|
10034
|
+
throw new Error("SSR inquiry bridge requires global fetch support.");
|
|
10035
|
+
}
|
|
10036
|
+
return globalThis.fetch.bind(globalThis);
|
|
10037
|
+
}
|
|
10038
|
+
function normalizeArrayResponse(value, keys) {
|
|
10039
|
+
for (const key of keys) {
|
|
10040
|
+
if (Array.isArray(value?.[key])) {
|
|
10041
|
+
return value[key];
|
|
10042
|
+
}
|
|
10043
|
+
}
|
|
10044
|
+
if (Array.isArray(value?.rows)) {
|
|
10045
|
+
return value.rows;
|
|
10046
|
+
}
|
|
10047
|
+
if (Array.isArray(value?.data)) {
|
|
10048
|
+
return value.data;
|
|
10049
|
+
}
|
|
10050
|
+
return [];
|
|
10051
|
+
}
|
|
10052
|
+
function normalizeIntentMap(raw) {
|
|
10053
|
+
const intentName = String(raw.intentName ?? raw.intent_name ?? "").trim();
|
|
10054
|
+
const serviceName = String(raw.serviceName ?? raw.service_name ?? "").trim();
|
|
10055
|
+
const taskName = String(raw.taskName ?? raw.task_name ?? "").trim();
|
|
10056
|
+
const taskVersion = Math.max(
|
|
10057
|
+
1,
|
|
10058
|
+
Math.trunc(Number(raw.taskVersion ?? raw.task_version ?? 1) || 1)
|
|
10059
|
+
);
|
|
10060
|
+
if (!intentName || !serviceName || !taskName) {
|
|
10061
|
+
return null;
|
|
10062
|
+
}
|
|
10063
|
+
return {
|
|
10064
|
+
intentName,
|
|
10065
|
+
serviceName,
|
|
10066
|
+
taskName,
|
|
10067
|
+
taskVersion,
|
|
10068
|
+
deleted: Boolean(raw.deleted)
|
|
10069
|
+
};
|
|
10070
|
+
}
|
|
10071
|
+
function buildInquiryMeta(inquiry, startedAt, statuses) {
|
|
10072
|
+
const counts = summarizeResponderStatuses(statuses);
|
|
10073
|
+
return {
|
|
10074
|
+
inquiry,
|
|
10075
|
+
isMetaInquiry: isMetaIntentName(inquiry),
|
|
10076
|
+
totalResponders: statuses.length,
|
|
10077
|
+
eligibleResponders: statuses.length,
|
|
10078
|
+
filteredOutResponders: 0,
|
|
10079
|
+
responded: counts.responded,
|
|
10080
|
+
failed: counts.failed,
|
|
10081
|
+
timedOut: counts.timedOut,
|
|
10082
|
+
pending: counts.pending,
|
|
10083
|
+
durationMs: Date.now() - startedAt,
|
|
10084
|
+
responders: statuses
|
|
10085
|
+
};
|
|
10086
|
+
}
|
|
10087
|
+
function createSSRInquiryBridge(options = {}) {
|
|
10088
|
+
const bootstrapEndpoint = resolveBootstrapEndpoint({
|
|
10089
|
+
runtime: "server",
|
|
10090
|
+
bootstrap: options.bootstrap,
|
|
10091
|
+
cadenzaDB: options.cadenzaDB
|
|
10092
|
+
});
|
|
10093
|
+
const fetchImplementation = ensureFetch();
|
|
10094
|
+
const initialInquiryResults = {};
|
|
10095
|
+
const postDelegation = async (targetUrl, remoteRoutineName, context, timeoutMs) => {
|
|
10096
|
+
const signal = AbortSignal.timeout(timeoutMs);
|
|
10097
|
+
const response = await fetchImplementation(`${targetUrl}/delegation`, {
|
|
10098
|
+
method: "POST",
|
|
10099
|
+
headers: {
|
|
10100
|
+
"Content-Type": "application/json"
|
|
10101
|
+
},
|
|
10102
|
+
body: JSON.stringify({
|
|
10103
|
+
...context,
|
|
10104
|
+
__remoteRoutineName: remoteRoutineName,
|
|
10105
|
+
__metadata: {
|
|
10106
|
+
...context.__metadata ?? {},
|
|
10107
|
+
__deputyExecId: uuid4()
|
|
10108
|
+
}
|
|
10109
|
+
}),
|
|
10110
|
+
signal
|
|
10111
|
+
});
|
|
10112
|
+
return await response.json();
|
|
10113
|
+
};
|
|
10114
|
+
const queryTable = async (tableName, queryData, timeoutMs) => {
|
|
10115
|
+
const response = await postDelegation(
|
|
10116
|
+
bootstrapEndpoint.url,
|
|
10117
|
+
`Query ${tableName}`,
|
|
10118
|
+
{ queryData },
|
|
10119
|
+
timeoutMs
|
|
10120
|
+
);
|
|
10121
|
+
return normalizeArrayResponse(response, [
|
|
10122
|
+
`${tableName}Rows`,
|
|
10123
|
+
`${tableName}s`,
|
|
10124
|
+
tableName,
|
|
10125
|
+
tableName.replace(/_([a-z])/g, (_match, char) => char.toUpperCase())
|
|
10126
|
+
]);
|
|
10127
|
+
};
|
|
10128
|
+
return {
|
|
10129
|
+
async inquire(inquiry, context = {}, inquiryOptions = {}) {
|
|
10130
|
+
const startedAt = Date.now();
|
|
10131
|
+
const overallTimeoutMs = inquiryOptions.overallTimeoutMs ?? inquiryOptions.timeout ?? 3e4;
|
|
10132
|
+
const perResponderTimeoutMs = inquiryOptions.perResponderTimeoutMs ?? overallTimeoutMs;
|
|
10133
|
+
const intentMaps = (await queryTable(
|
|
10134
|
+
"intent_to_task_map",
|
|
10135
|
+
{
|
|
10136
|
+
filter: {
|
|
10137
|
+
intent_name: inquiry
|
|
10138
|
+
}
|
|
10139
|
+
},
|
|
10140
|
+
overallTimeoutMs
|
|
10141
|
+
)).map(normalizeIntentMap).filter(
|
|
10142
|
+
(item) => !!item && item.intentName === inquiry && !item.deleted
|
|
10143
|
+
);
|
|
10144
|
+
if (intentMaps.length === 0) {
|
|
10145
|
+
return {
|
|
10146
|
+
__inquiryMeta: buildInquiryMeta(inquiry, startedAt, [])
|
|
10147
|
+
};
|
|
10148
|
+
}
|
|
10149
|
+
const relevantServiceNames = Array.from(
|
|
10150
|
+
new Set(intentMaps.map((item) => item.serviceName))
|
|
10151
|
+
);
|
|
10152
|
+
const rawServiceInstances = await queryTable(
|
|
10153
|
+
"service_instance",
|
|
10154
|
+
{
|
|
10155
|
+
filter: {
|
|
10156
|
+
service_name: relevantServiceNames
|
|
10157
|
+
}
|
|
10158
|
+
},
|
|
10159
|
+
overallTimeoutMs
|
|
10160
|
+
);
|
|
10161
|
+
const rawServiceTransports = await queryTable(
|
|
10162
|
+
"service_instance_transport",
|
|
10163
|
+
{
|
|
10164
|
+
filter: {
|
|
10165
|
+
deleted: false
|
|
10166
|
+
}
|
|
10167
|
+
},
|
|
10168
|
+
overallTimeoutMs
|
|
10169
|
+
);
|
|
10170
|
+
const transportsByInstance = /* @__PURE__ */ new Map();
|
|
10171
|
+
for (const transport of rawServiceTransports) {
|
|
10172
|
+
const serviceInstanceId = String(
|
|
10173
|
+
transport.serviceInstanceId ?? transport.service_instance_id ?? ""
|
|
10174
|
+
).trim();
|
|
10175
|
+
if (!serviceInstanceId) {
|
|
10176
|
+
continue;
|
|
10177
|
+
}
|
|
10178
|
+
if (!transportsByInstance.has(serviceInstanceId)) {
|
|
10179
|
+
transportsByInstance.set(serviceInstanceId, []);
|
|
10180
|
+
}
|
|
10181
|
+
transportsByInstance.get(serviceInstanceId).push(transport);
|
|
10182
|
+
}
|
|
10183
|
+
const serviceInstances = rawServiceInstances.map(
|
|
10184
|
+
(instance) => normalizeServiceInstanceDescriptor({
|
|
10185
|
+
...instance,
|
|
10186
|
+
transports: transportsByInstance.get(String(instance.uuid ?? "").trim()) ?? []
|
|
10187
|
+
})
|
|
10188
|
+
).filter(
|
|
10189
|
+
(item) => !!item && relevantServiceNames.includes(item.serviceName) && item.isActive && !item.isNonResponsive && !item.isBlocked
|
|
10190
|
+
).sort((left, right) => {
|
|
10191
|
+
if (left.serviceName !== right.serviceName) {
|
|
10192
|
+
return left.serviceName.localeCompare(right.serviceName);
|
|
10193
|
+
}
|
|
10194
|
+
if (left.isPrimary !== right.isPrimary) {
|
|
10195
|
+
return left.isPrimary ? -1 : 1;
|
|
10196
|
+
}
|
|
10197
|
+
return (left.numberOfRunningGraphs ?? 0) - (right.numberOfRunningGraphs ?? 0);
|
|
10198
|
+
});
|
|
10199
|
+
const statuses = intentMaps.map((map) => ({
|
|
10200
|
+
isRemote: true,
|
|
10201
|
+
serviceName: map.serviceName,
|
|
10202
|
+
taskName: map.taskName,
|
|
10203
|
+
taskVersion: map.taskVersion,
|
|
10204
|
+
localTaskName: `SSR inquiry via ${map.serviceName} (${map.taskName} v${map.taskVersion})`,
|
|
10205
|
+
status: "timed_out",
|
|
10206
|
+
durationMs: 0
|
|
10207
|
+
}));
|
|
10208
|
+
const fulfilledContexts = await Promise.all(
|
|
10209
|
+
intentMaps.map(async (map, index) => {
|
|
10210
|
+
const status = statuses[index];
|
|
10211
|
+
const startedAtForResponder = Date.now();
|
|
10212
|
+
const selectedInstance = serviceInstances.find(
|
|
10213
|
+
(instance) => instance.serviceName === map.serviceName
|
|
10214
|
+
);
|
|
10215
|
+
if (!selectedInstance) {
|
|
10216
|
+
status.status = "failed";
|
|
10217
|
+
status.error = `No active instances for ${map.serviceName}`;
|
|
10218
|
+
status.durationMs = Date.now() - startedAtForResponder;
|
|
10219
|
+
return null;
|
|
10220
|
+
}
|
|
10221
|
+
const targetTransport = selectTransportForRole(
|
|
10222
|
+
selectedInstance.transports,
|
|
10223
|
+
"internal",
|
|
10224
|
+
"rest"
|
|
10225
|
+
);
|
|
10226
|
+
if (!targetTransport) {
|
|
10227
|
+
status.status = "failed";
|
|
10228
|
+
status.error = `No internal transport for ${selectedInstance.serviceName}/${selectedInstance.uuid}`;
|
|
10229
|
+
status.durationMs = Date.now() - startedAtForResponder;
|
|
10230
|
+
return null;
|
|
10231
|
+
}
|
|
10232
|
+
const targetUrl = targetTransport.origin;
|
|
10233
|
+
try {
|
|
10234
|
+
const result = await postDelegation(
|
|
10235
|
+
targetUrl,
|
|
10236
|
+
map.taskName,
|
|
10237
|
+
context,
|
|
10238
|
+
perResponderTimeoutMs
|
|
10239
|
+
);
|
|
10240
|
+
status.durationMs = Date.now() - startedAtForResponder;
|
|
10241
|
+
if (result?.errored || result?.failed) {
|
|
10242
|
+
status.status = "failed";
|
|
10243
|
+
status.error = String(
|
|
10244
|
+
result?.__error ?? result?.error ?? "Remote inquiry failed"
|
|
10245
|
+
);
|
|
10246
|
+
return null;
|
|
10247
|
+
}
|
|
10248
|
+
status.status = "fulfilled";
|
|
10249
|
+
return result;
|
|
10250
|
+
} catch (error) {
|
|
10251
|
+
status.durationMs = Date.now() - startedAtForResponder;
|
|
10252
|
+
if (error instanceof Error && (error.name === "AbortError" || /timed out/i.test(error.message))) {
|
|
10253
|
+
status.status = "timed_out";
|
|
10254
|
+
status.error = error.message;
|
|
10255
|
+
return null;
|
|
10256
|
+
}
|
|
10257
|
+
status.status = "failed";
|
|
10258
|
+
status.error = error instanceof Error ? error.message : String(error);
|
|
10259
|
+
return null;
|
|
10260
|
+
}
|
|
10261
|
+
})
|
|
10262
|
+
);
|
|
10263
|
+
const mergedContext = mergeInquiryContexts(
|
|
10264
|
+
fulfilledContexts.filter(
|
|
10265
|
+
(item) => item !== null
|
|
10266
|
+
)
|
|
10267
|
+
);
|
|
10268
|
+
const responseContext = {
|
|
10269
|
+
...mergedContext,
|
|
10270
|
+
__inquiryMeta: buildInquiryMeta(inquiry, startedAt, statuses)
|
|
10271
|
+
};
|
|
10272
|
+
if (inquiryOptions.hydrationKey) {
|
|
10273
|
+
initialInquiryResults[inquiryOptions.hydrationKey] = responseContext;
|
|
10274
|
+
}
|
|
10275
|
+
if (inquiryOptions.requireComplete && statuses.some((status) => status.status !== "fulfilled")) {
|
|
10276
|
+
throw {
|
|
10277
|
+
...responseContext,
|
|
10278
|
+
__error: `Inquiry '${inquiry}' did not complete successfully`,
|
|
10279
|
+
errored: true
|
|
10280
|
+
};
|
|
10281
|
+
}
|
|
10282
|
+
return responseContext;
|
|
10283
|
+
},
|
|
10284
|
+
dehydrate() {
|
|
10285
|
+
return {
|
|
10286
|
+
initialInquiryResults: { ...initialInquiryResults }
|
|
10287
|
+
};
|
|
10288
|
+
}
|
|
10289
|
+
};
|
|
10290
|
+
}
|
|
10291
|
+
|
|
10292
|
+
// src/index.ts
|
|
9091
10293
|
var index_default = CadenzaService;
|
|
9092
10294
|
export {
|
|
9093
10295
|
Actor2 as Actor,
|
|
10296
|
+
DatabaseController,
|
|
9094
10297
|
DatabaseTask,
|
|
9095
10298
|
DebounceTask2 as DebounceTask,
|
|
9096
10299
|
DeputyTask,
|
|
@@ -9103,6 +10306,7 @@ export {
|
|
|
9103
10306
|
SignalTransmissionTask,
|
|
9104
10307
|
SocketController,
|
|
9105
10308
|
Task4 as Task,
|
|
10309
|
+
createSSRInquiryBridge,
|
|
9106
10310
|
index_default as default
|
|
9107
10311
|
};
|
|
9108
10312
|
//# sourceMappingURL=index.mjs.map
|