@cadenza.io/service 2.4.0 → 2.6.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/dist/index.d.mts +212 -134
- package/dist/index.d.ts +212 -134
- package/dist/index.js +1159 -102
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1159 -102
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -247,7 +247,74 @@ var DatabaseTask = class extends DeputyTask {
|
|
|
247
247
|
var isNode = typeof process !== "undefined" && process.versions?.node != null;
|
|
248
248
|
var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
249
249
|
|
|
250
|
+
// src/utils/inquiry.ts
|
|
251
|
+
var META_INTENT_PREFIX = "meta-";
|
|
252
|
+
var META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT = "meta-runtime-transport-diagnostics";
|
|
253
|
+
function isPlainObject(value) {
|
|
254
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
255
|
+
}
|
|
256
|
+
function deepMergeDeterministic(left, right) {
|
|
257
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
258
|
+
return [...left, ...right];
|
|
259
|
+
}
|
|
260
|
+
if (isPlainObject(left) && isPlainObject(right)) {
|
|
261
|
+
const merged = { ...left };
|
|
262
|
+
const keys = Array.from(/* @__PURE__ */ new Set([...Object.keys(left), ...Object.keys(right)])).sort();
|
|
263
|
+
for (const key of keys) {
|
|
264
|
+
if (!(key in left)) {
|
|
265
|
+
merged[key] = right[key];
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (!(key in right)) {
|
|
269
|
+
merged[key] = left[key];
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
merged[key] = deepMergeDeterministic(left[key], right[key]);
|
|
273
|
+
}
|
|
274
|
+
return merged;
|
|
275
|
+
}
|
|
276
|
+
return right;
|
|
277
|
+
}
|
|
278
|
+
function mergeInquiryContexts(contexts) {
|
|
279
|
+
return contexts.reduce((acc, next) => deepMergeDeterministic(acc, next), {});
|
|
280
|
+
}
|
|
281
|
+
function isMetaIntentName(intentName) {
|
|
282
|
+
return intentName.startsWith(META_INTENT_PREFIX);
|
|
283
|
+
}
|
|
284
|
+
function shouldExecuteInquiryResponder(inquiry, responderIsMeta) {
|
|
285
|
+
if (!isMetaIntentName(inquiry)) {
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
return responderIsMeta;
|
|
289
|
+
}
|
|
290
|
+
function compareResponderDescriptors(left, right) {
|
|
291
|
+
if (left.serviceName !== right.serviceName) {
|
|
292
|
+
return left.serviceName.localeCompare(right.serviceName);
|
|
293
|
+
}
|
|
294
|
+
if (left.taskName !== right.taskName) {
|
|
295
|
+
return left.taskName.localeCompare(right.taskName);
|
|
296
|
+
}
|
|
297
|
+
if (left.taskVersion !== right.taskVersion) {
|
|
298
|
+
return left.taskVersion - right.taskVersion;
|
|
299
|
+
}
|
|
300
|
+
return left.localTaskName.localeCompare(right.localTaskName);
|
|
301
|
+
}
|
|
302
|
+
function summarizeResponderStatuses(statuses) {
|
|
303
|
+
let responded = 0;
|
|
304
|
+
let failed = 0;
|
|
305
|
+
let timedOut = 0;
|
|
306
|
+
let pending = 0;
|
|
307
|
+
for (const status of statuses) {
|
|
308
|
+
if (status.status === "fulfilled") responded++;
|
|
309
|
+
if (status.status === "failed") failed++;
|
|
310
|
+
if (status.status === "timed_out") timedOut++;
|
|
311
|
+
}
|
|
312
|
+
pending = Math.max(0, statuses.length - responded - failed - timedOut);
|
|
313
|
+
return { responded, failed, timedOut, pending };
|
|
314
|
+
}
|
|
315
|
+
|
|
250
316
|
// src/registry/ServiceRegistry.ts
|
|
317
|
+
var META_SERVICE_REGISTRY_FULL_SYNC_INTENT = "meta-service-registry-full-sync";
|
|
251
318
|
var ServiceRegistry = class _ServiceRegistry {
|
|
252
319
|
/**
|
|
253
320
|
* Initializes a private constructor for managing service instances, remote signals,
|
|
@@ -262,11 +329,47 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
262
329
|
this.instances = /* @__PURE__ */ new Map();
|
|
263
330
|
this.deputies = /* @__PURE__ */ new Map();
|
|
264
331
|
this.remoteSignals = /* @__PURE__ */ new Map();
|
|
332
|
+
this.remoteIntents = /* @__PURE__ */ new Map();
|
|
333
|
+
this.remoteIntentDeputiesByKey = /* @__PURE__ */ new Map();
|
|
334
|
+
this.remoteIntentDeputiesByTask = /* @__PURE__ */ new Map();
|
|
265
335
|
this.serviceName = null;
|
|
266
336
|
this.serviceInstanceId = null;
|
|
267
337
|
this.numberOfRunningGraphs = 0;
|
|
268
338
|
this.useSocket = false;
|
|
269
339
|
this.retryCount = 3;
|
|
340
|
+
CadenzaService.defineIntent({
|
|
341
|
+
name: META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT,
|
|
342
|
+
description: "Gather transport diagnostics across all services and communication clients.",
|
|
343
|
+
input: {
|
|
344
|
+
type: "object",
|
|
345
|
+
properties: {
|
|
346
|
+
detailLevel: {
|
|
347
|
+
type: "string",
|
|
348
|
+
constraints: {
|
|
349
|
+
oneOf: ["summary", "full"]
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
includeErrorHistory: {
|
|
353
|
+
type: "boolean"
|
|
354
|
+
},
|
|
355
|
+
errorHistoryLimit: {
|
|
356
|
+
type: "number",
|
|
357
|
+
constraints: {
|
|
358
|
+
min: 1,
|
|
359
|
+
max: 200
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
output: {
|
|
365
|
+
type: "object",
|
|
366
|
+
properties: {
|
|
367
|
+
transportDiagnostics: {
|
|
368
|
+
type: "object"
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
});
|
|
270
373
|
this.handleInstanceUpdateTask = CadenzaService.createMetaTask(
|
|
271
374
|
"Handle Instance Update",
|
|
272
375
|
(ctx, emit) => {
|
|
@@ -306,7 +409,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
306
409
|
if (this.serviceName === serviceName) {
|
|
307
410
|
return false;
|
|
308
411
|
}
|
|
309
|
-
if (!isFrontend && this.deputies.has(serviceName) || this.remoteSignals.has(serviceName)) {
|
|
412
|
+
if (!isFrontend && (this.deputies.has(serviceName) || this.remoteIntents.has(serviceName)) || this.remoteSignals.has(serviceName)) {
|
|
310
413
|
const clientCreated = instances?.some(
|
|
311
414
|
(i) => i.address === address && i.port === port && i.clientCreated && i.isActive
|
|
312
415
|
);
|
|
@@ -356,7 +459,10 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
356
459
|
for (const serviceInstance of ctx.serviceInstances) {
|
|
357
460
|
yield { serviceInstance };
|
|
358
461
|
}
|
|
359
|
-
}).doOn(
|
|
462
|
+
}).doOn(
|
|
463
|
+
"meta.service_registry.registered_global_signals",
|
|
464
|
+
"meta.service_registry.registered_global_intents"
|
|
465
|
+
).then(this.handleInstanceUpdateTask);
|
|
360
466
|
this.handleGlobalSignalRegistrationTask = CadenzaService.createMetaTask(
|
|
361
467
|
"Handle global Signal Registration",
|
|
362
468
|
(ctx) => {
|
|
@@ -397,6 +503,32 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
397
503
|
},
|
|
398
504
|
"Handles registration of remote signals"
|
|
399
505
|
).emits("meta.service_registry.registered_global_signals").doOn("global.meta.cadenza_db.gathered_sync_data");
|
|
506
|
+
this.handleGlobalIntentRegistrationTask = CadenzaService.createMetaTask(
|
|
507
|
+
"Handle global intent registration",
|
|
508
|
+
(ctx) => {
|
|
509
|
+
const intentToTaskMaps = this.normalizeIntentMaps(ctx);
|
|
510
|
+
const sorted = intentToTaskMaps.sort((a, b) => {
|
|
511
|
+
if (a.deleted && !b.deleted) return -1;
|
|
512
|
+
if (!a.deleted && b.deleted) return 1;
|
|
513
|
+
return 0;
|
|
514
|
+
});
|
|
515
|
+
for (const map of sorted) {
|
|
516
|
+
if (map.deleted) {
|
|
517
|
+
this.unregisterRemoteIntentDeputy(map);
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
CadenzaService.inquiryBroker.addIntent({
|
|
521
|
+
name: map.intentName
|
|
522
|
+
});
|
|
523
|
+
this.registerRemoteIntentDeputy(map);
|
|
524
|
+
}
|
|
525
|
+
return true;
|
|
526
|
+
},
|
|
527
|
+
"Handles registration of remote inquiry intent responders"
|
|
528
|
+
).emits("meta.service_registry.registered_global_intents").doOn(
|
|
529
|
+
"global.meta.cadenza_db.gathered_sync_data",
|
|
530
|
+
"global.meta.graph_metadata.task_intent_associated"
|
|
531
|
+
);
|
|
400
532
|
this.handleServiceNotRespondingTask = CadenzaService.createMetaTask(
|
|
401
533
|
"Handle service not responding",
|
|
402
534
|
(ctx, emit) => {
|
|
@@ -501,45 +633,58 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
501
633
|
},
|
|
502
634
|
"Handles status update from socket broadcast"
|
|
503
635
|
).doOn("meta.socket_client.status_received");
|
|
504
|
-
|
|
505
|
-
"
|
|
506
|
-
(ctx) => {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
636
|
+
this.fullSyncTask = CadenzaService.createMetaTask(
|
|
637
|
+
"Full sync",
|
|
638
|
+
async (ctx) => {
|
|
639
|
+
const inquiryResult = await CadenzaService.inquire(
|
|
640
|
+
META_SERVICE_REGISTRY_FULL_SYNC_INTENT,
|
|
641
|
+
{
|
|
642
|
+
syncScope: "service-registry-full-sync"
|
|
643
|
+
},
|
|
644
|
+
ctx.inquiryOptions ?? ctx.__inquiryOptions ?? {}
|
|
645
|
+
);
|
|
646
|
+
const signalToTaskMaps = (inquiryResult.signalToTaskMaps ?? []).filter((m) => !!m.isGlobal).map((m) => ({
|
|
647
|
+
signalName: m.signalName,
|
|
648
|
+
serviceName: m.serviceName,
|
|
649
|
+
deleted: !!m.deleted
|
|
650
|
+
}));
|
|
651
|
+
const intentToTaskMaps = (inquiryResult.intentToTaskMaps ?? []).map(
|
|
652
|
+
(m) => ({
|
|
653
|
+
intentName: m.intentName,
|
|
654
|
+
taskName: m.taskName,
|
|
655
|
+
taskVersion: m.taskVersion ?? 1,
|
|
656
|
+
serviceName: m.serviceName,
|
|
657
|
+
deleted: !!m.deleted
|
|
658
|
+
})
|
|
659
|
+
);
|
|
660
|
+
const serviceInstances = (inquiryResult.serviceInstances ?? []).filter(
|
|
661
|
+
(instance) => !instance.deleted && !!instance.isActive && !instance.isNonResponsive && !instance.isBlocked
|
|
662
|
+
).map((instance) => ({
|
|
663
|
+
uuid: instance.uuid,
|
|
664
|
+
address: instance.address,
|
|
665
|
+
port: instance.port,
|
|
666
|
+
serviceName: instance.serviceName,
|
|
667
|
+
isActive: !!instance.isActive,
|
|
668
|
+
isNonResponsive: !!instance.isNonResponsive,
|
|
669
|
+
isBlocked: !!instance.isBlocked,
|
|
670
|
+
health: instance.health ?? {},
|
|
671
|
+
exposed: !!instance.exposed,
|
|
672
|
+
created: instance.created,
|
|
673
|
+
isFrontend: !!instance.isFrontend
|
|
674
|
+
}));
|
|
675
|
+
return {
|
|
676
|
+
...ctx,
|
|
677
|
+
signalToTaskMaps,
|
|
678
|
+
intentToTaskMaps,
|
|
679
|
+
serviceInstances,
|
|
680
|
+
__inquiryMeta: inquiryResult.__inquiryMeta
|
|
681
|
+
};
|
|
682
|
+
},
|
|
683
|
+
"Runs service registry full sync through one distributed inquiry intent."
|
|
684
|
+
).doOn("meta.sync_requested").emits("meta.service_registry.initial_sync_complete").then(
|
|
685
|
+
this.handleGlobalSignalRegistrationTask,
|
|
686
|
+
this.handleGlobalIntentRegistrationTask
|
|
687
|
+
);
|
|
543
688
|
this.getInstanceById = CadenzaService.createMetaTask(
|
|
544
689
|
"Get instance by id",
|
|
545
690
|
(context) => {
|
|
@@ -708,6 +853,25 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
708
853
|
__active: self?.isActive ?? false
|
|
709
854
|
};
|
|
710
855
|
}).doOn("meta.socket.status_check_requested");
|
|
856
|
+
this.collectTransportDiagnosticsTask = CadenzaService.createMetaTask(
|
|
857
|
+
"Collect transport diagnostics",
|
|
858
|
+
async (ctx) => {
|
|
859
|
+
const inquiryResult = await CadenzaService.inquire(
|
|
860
|
+
META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT,
|
|
861
|
+
{
|
|
862
|
+
detailLevel: ctx.detailLevel,
|
|
863
|
+
includeErrorHistory: ctx.includeErrorHistory,
|
|
864
|
+
errorHistoryLimit: ctx.errorHistoryLimit
|
|
865
|
+
},
|
|
866
|
+
ctx.inquiryOptions ?? ctx.__inquiryOptions ?? {}
|
|
867
|
+
);
|
|
868
|
+
return {
|
|
869
|
+
...ctx,
|
|
870
|
+
...inquiryResult
|
|
871
|
+
};
|
|
872
|
+
},
|
|
873
|
+
"Collects distributed transport diagnostics using inquiry responders."
|
|
874
|
+
).doOn("meta.service_registry.transport_diagnostics_requested").emits("meta.service_registry.transport_diagnostics_collected").emitsOnFail("meta.service_registry.transport_diagnostics_failed");
|
|
711
875
|
this.insertServiceTask = CadenzaService.createCadenzaDBInsertTask(
|
|
712
876
|
"service",
|
|
713
877
|
{
|
|
@@ -916,8 +1080,125 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
916
1080
|
if (!this._instance) this._instance = new _ServiceRegistry();
|
|
917
1081
|
return this._instance;
|
|
918
1082
|
}
|
|
1083
|
+
buildRemoteIntentDeputyKey(map) {
|
|
1084
|
+
return `${map.intentName}|${map.serviceName}|${map.taskName}|${map.taskVersion ?? 1}`;
|
|
1085
|
+
}
|
|
1086
|
+
normalizeIntentMaps(ctx) {
|
|
1087
|
+
if (Array.isArray(ctx.intentToTaskMaps)) {
|
|
1088
|
+
return ctx.intentToTaskMaps.map((m) => ({
|
|
1089
|
+
intentName: m.intentName ?? m.intent_name,
|
|
1090
|
+
serviceName: m.serviceName ?? m.service_name,
|
|
1091
|
+
taskName: m.taskName ?? m.task_name,
|
|
1092
|
+
taskVersion: m.taskVersion ?? m.task_version ?? 1,
|
|
1093
|
+
deleted: !!m.deleted
|
|
1094
|
+
})).filter((m) => m.intentName && m.serviceName && m.taskName);
|
|
1095
|
+
}
|
|
1096
|
+
const single = ctx.intentToTaskMap ?? ctx.data ?? (ctx.intentName ? ctx : void 0);
|
|
1097
|
+
if (!single) return [];
|
|
1098
|
+
const normalized = {
|
|
1099
|
+
intentName: single.intentName ?? single.intent_name,
|
|
1100
|
+
serviceName: single.serviceName ?? single.service_name,
|
|
1101
|
+
taskName: single.taskName ?? single.task_name,
|
|
1102
|
+
taskVersion: single.taskVersion ?? single.task_version ?? 1,
|
|
1103
|
+
deleted: !!single.deleted
|
|
1104
|
+
};
|
|
1105
|
+
if (!normalized.intentName || !normalized.serviceName || !normalized.taskName)
|
|
1106
|
+
return [];
|
|
1107
|
+
return [normalized];
|
|
1108
|
+
}
|
|
1109
|
+
registerRemoteIntentDeputy(map) {
|
|
1110
|
+
if (!this.serviceName || map.serviceName === this.serviceName) {
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
const key = this.buildRemoteIntentDeputyKey(map);
|
|
1114
|
+
if (this.remoteIntentDeputiesByKey.has(key)) {
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
const deputyTaskName = `Inquire ${map.intentName} via ${map.serviceName} (${map.taskName} v${map.taskVersion})`;
|
|
1118
|
+
const deputyTask = isMetaIntentName(map.intentName) ? CadenzaService.createMetaDeputyTask(map.taskName, map.serviceName, {
|
|
1119
|
+
register: false,
|
|
1120
|
+
isHidden: true,
|
|
1121
|
+
retryCount: 1,
|
|
1122
|
+
retryDelay: 50,
|
|
1123
|
+
retryDelayFactor: 1.2
|
|
1124
|
+
}) : CadenzaService.createDeputyTask(map.taskName, map.serviceName, {
|
|
1125
|
+
register: false,
|
|
1126
|
+
isHidden: true,
|
|
1127
|
+
retryCount: 1,
|
|
1128
|
+
retryDelay: 50,
|
|
1129
|
+
retryDelayFactor: 1.2
|
|
1130
|
+
});
|
|
1131
|
+
deputyTask.respondsTo(map.intentName);
|
|
1132
|
+
if (!this.remoteIntents.has(map.serviceName)) {
|
|
1133
|
+
this.remoteIntents.set(map.serviceName, /* @__PURE__ */ new Set());
|
|
1134
|
+
}
|
|
1135
|
+
this.remoteIntents.get(map.serviceName).add(map.intentName);
|
|
1136
|
+
const descriptor = {
|
|
1137
|
+
key,
|
|
1138
|
+
intentName: map.intentName,
|
|
1139
|
+
serviceName: map.serviceName,
|
|
1140
|
+
remoteTaskName: map.taskName,
|
|
1141
|
+
remoteTaskVersion: map.taskVersion,
|
|
1142
|
+
localTaskName: deputyTask.name || deputyTaskName,
|
|
1143
|
+
localTask: deputyTask
|
|
1144
|
+
};
|
|
1145
|
+
this.remoteIntentDeputiesByKey.set(key, descriptor);
|
|
1146
|
+
this.remoteIntentDeputiesByTask.set(deputyTask, descriptor);
|
|
1147
|
+
}
|
|
1148
|
+
unregisterRemoteIntentDeputy(map) {
|
|
1149
|
+
const key = this.buildRemoteIntentDeputyKey(map);
|
|
1150
|
+
const descriptor = this.remoteIntentDeputiesByKey.get(key);
|
|
1151
|
+
if (!descriptor) {
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
const task = descriptor.localTask;
|
|
1155
|
+
if (task) {
|
|
1156
|
+
CadenzaService.inquiryBroker.unsubscribe(descriptor.intentName, task);
|
|
1157
|
+
task.destroy();
|
|
1158
|
+
}
|
|
1159
|
+
this.remoteIntentDeputiesByTask.delete(descriptor.localTask);
|
|
1160
|
+
this.remoteIntentDeputiesByKey.delete(key);
|
|
1161
|
+
this.remoteIntents.get(descriptor.serviceName)?.delete(descriptor.intentName);
|
|
1162
|
+
if (!this.remoteIntents.get(descriptor.serviceName)?.size) {
|
|
1163
|
+
this.remoteIntents.delete(descriptor.serviceName);
|
|
1164
|
+
}
|
|
1165
|
+
const deputies = this.deputies.get(descriptor.serviceName);
|
|
1166
|
+
if (deputies) {
|
|
1167
|
+
this.deputies.set(
|
|
1168
|
+
descriptor.serviceName,
|
|
1169
|
+
deputies.filter((d) => d.localTaskName !== descriptor.localTaskName)
|
|
1170
|
+
);
|
|
1171
|
+
if (this.deputies.get(descriptor.serviceName)?.length === 0) {
|
|
1172
|
+
this.deputies.delete(descriptor.serviceName);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
getInquiryResponderDescriptor(task) {
|
|
1177
|
+
const remote = this.remoteIntentDeputiesByTask.get(task);
|
|
1178
|
+
if (remote) {
|
|
1179
|
+
return {
|
|
1180
|
+
isRemote: true,
|
|
1181
|
+
serviceName: remote.serviceName,
|
|
1182
|
+
taskName: remote.remoteTaskName,
|
|
1183
|
+
taskVersion: remote.remoteTaskVersion,
|
|
1184
|
+
localTaskName: remote.localTaskName
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
return {
|
|
1188
|
+
isRemote: false,
|
|
1189
|
+
serviceName: this.serviceName ?? "UnknownService",
|
|
1190
|
+
taskName: task.name,
|
|
1191
|
+
taskVersion: task.version,
|
|
1192
|
+
localTaskName: task.name
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
919
1195
|
reset() {
|
|
920
1196
|
this.instances.clear();
|
|
1197
|
+
this.deputies.clear();
|
|
1198
|
+
this.remoteSignals.clear();
|
|
1199
|
+
this.remoteIntents.clear();
|
|
1200
|
+
this.remoteIntentDeputiesByKey.clear();
|
|
1201
|
+
this.remoteIntentDeputiesByTask.clear();
|
|
921
1202
|
}
|
|
922
1203
|
};
|
|
923
1204
|
|
|
@@ -1034,6 +1315,8 @@ var RestController = class _RestController {
|
|
|
1034
1315
|
* It initializes and configures the REST server tasks.
|
|
1035
1316
|
*/
|
|
1036
1317
|
constructor() {
|
|
1318
|
+
this.fetchClientDiagnostics = /* @__PURE__ */ new Map();
|
|
1319
|
+
this.diagnosticsErrorHistoryLimit = 100;
|
|
1037
1320
|
/**
|
|
1038
1321
|
* Fetches data from the given URL with a specified timeout. This function performs
|
|
1039
1322
|
* a fetch request with the ability to cancel the request if it exceeds the provided timeout duration.
|
|
@@ -1074,6 +1357,11 @@ var RestController = class _RestController {
|
|
|
1074
1357
|
"meta.rest.delegation_requested",
|
|
1075
1358
|
"meta.socket.delegation_requested"
|
|
1076
1359
|
);
|
|
1360
|
+
CadenzaService.createMetaTask(
|
|
1361
|
+
"Collect fetch transport diagnostics",
|
|
1362
|
+
(ctx) => this.collectFetchTransportDiagnostics(ctx),
|
|
1363
|
+
"Responds to distributed transport diagnostics inquiries with REST/fetch client data."
|
|
1364
|
+
).respondsTo(META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT);
|
|
1077
1365
|
CadenzaService.createMetaRoutine(
|
|
1078
1366
|
"RestServer",
|
|
1079
1367
|
[
|
|
@@ -1404,6 +1692,13 @@ var RestController = class _RestController {
|
|
|
1404
1692
|
const port = protocol === "https" ? 443 : servicePort;
|
|
1405
1693
|
const URL = `${protocol}://${serviceAddress}:${port}`;
|
|
1406
1694
|
const fetchId = `${serviceAddress}_${port}`;
|
|
1695
|
+
const fetchDiagnostics = this.ensureFetchClientDiagnostics(
|
|
1696
|
+
fetchId,
|
|
1697
|
+
serviceName,
|
|
1698
|
+
URL
|
|
1699
|
+
);
|
|
1700
|
+
fetchDiagnostics.destroyed = false;
|
|
1701
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1407
1702
|
if (CadenzaService.get(`Send Handshake to ${URL}`)) {
|
|
1408
1703
|
console.error("Fetch client already exists", URL);
|
|
1409
1704
|
return;
|
|
@@ -1425,6 +1720,10 @@ var RestController = class _RestController {
|
|
|
1425
1720
|
);
|
|
1426
1721
|
if (response.__status !== "success") {
|
|
1427
1722
|
const error = response.__error ?? `Failed to connect to service ${serviceName} ${ctx2.serviceInstanceId}`;
|
|
1723
|
+
fetchDiagnostics.connected = false;
|
|
1724
|
+
fetchDiagnostics.lastHandshakeError = error;
|
|
1725
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1726
|
+
this.recordFetchClientError(fetchId, serviceName, URL, error);
|
|
1428
1727
|
CadenzaService.log(
|
|
1429
1728
|
"Fetch handshake failed.",
|
|
1430
1729
|
{ error, serviceName, URL },
|
|
@@ -1434,6 +1733,11 @@ var RestController = class _RestController {
|
|
|
1434
1733
|
return { ...ctx2, __error: error, errored: true };
|
|
1435
1734
|
}
|
|
1436
1735
|
ctx2.serviceInstanceId = response.__serviceInstanceId;
|
|
1736
|
+
fetchDiagnostics.connected = true;
|
|
1737
|
+
fetchDiagnostics.destroyed = false;
|
|
1738
|
+
fetchDiagnostics.lastHandshakeAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1739
|
+
fetchDiagnostics.lastHandshakeError = null;
|
|
1740
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1437
1741
|
CadenzaService.log("Fetch client connected.", {
|
|
1438
1742
|
response,
|
|
1439
1743
|
serviceName,
|
|
@@ -1449,6 +1753,10 @@ var RestController = class _RestController {
|
|
|
1449
1753
|
});
|
|
1450
1754
|
}
|
|
1451
1755
|
} catch (e) {
|
|
1756
|
+
fetchDiagnostics.connected = false;
|
|
1757
|
+
fetchDiagnostics.lastHandshakeError = this.getErrorMessage(e);
|
|
1758
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1759
|
+
this.recordFetchClientError(fetchId, serviceName, URL, e);
|
|
1452
1760
|
CadenzaService.log(
|
|
1453
1761
|
"Error in fetch handshake",
|
|
1454
1762
|
{ error: e, serviceName, URL, ctx: ctx2 },
|
|
@@ -1470,6 +1778,8 @@ var RestController = class _RestController {
|
|
|
1470
1778
|
if (ctx2.__remoteRoutineName === void 0) {
|
|
1471
1779
|
return;
|
|
1472
1780
|
}
|
|
1781
|
+
fetchDiagnostics.delegationRequests++;
|
|
1782
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1473
1783
|
let resultContext;
|
|
1474
1784
|
try {
|
|
1475
1785
|
resultContext = await this.fetchDataWithTimeout(
|
|
@@ -1483,8 +1793,21 @@ var RestController = class _RestController {
|
|
|
1483
1793
|
},
|
|
1484
1794
|
3e4
|
|
1485
1795
|
);
|
|
1796
|
+
if (resultContext?.errored || resultContext?.failed) {
|
|
1797
|
+
fetchDiagnostics.delegationFailures++;
|
|
1798
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1799
|
+
this.recordFetchClientError(
|
|
1800
|
+
fetchId,
|
|
1801
|
+
serviceName,
|
|
1802
|
+
URL,
|
|
1803
|
+
resultContext?.__error ?? resultContext?.error ?? "Delegation failed"
|
|
1804
|
+
);
|
|
1805
|
+
}
|
|
1486
1806
|
} catch (e) {
|
|
1487
1807
|
console.error("Error in delegation", e);
|
|
1808
|
+
fetchDiagnostics.delegationFailures++;
|
|
1809
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1810
|
+
this.recordFetchClientError(fetchId, serviceName, URL, e);
|
|
1488
1811
|
resultContext = {
|
|
1489
1812
|
__error: `Error: ${e}`,
|
|
1490
1813
|
errored: true,
|
|
@@ -1510,6 +1833,8 @@ var RestController = class _RestController {
|
|
|
1510
1833
|
if (ctx2.__signalName === void 0) {
|
|
1511
1834
|
return;
|
|
1512
1835
|
}
|
|
1836
|
+
fetchDiagnostics.signalTransmissions++;
|
|
1837
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1513
1838
|
let response;
|
|
1514
1839
|
try {
|
|
1515
1840
|
response = await this.fetchDataWithTimeout(
|
|
@@ -1526,8 +1851,21 @@ var RestController = class _RestController {
|
|
|
1526
1851
|
if (ctx2.__routineExecId) {
|
|
1527
1852
|
emit(`meta.fetch.transmitted:${ctx2.__routineExecId}`, response);
|
|
1528
1853
|
}
|
|
1854
|
+
if (response?.errored || response?.failed) {
|
|
1855
|
+
fetchDiagnostics.signalFailures++;
|
|
1856
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1857
|
+
this.recordFetchClientError(
|
|
1858
|
+
fetchId,
|
|
1859
|
+
serviceName,
|
|
1860
|
+
URL,
|
|
1861
|
+
response?.__error ?? response?.error ?? "Signal transmission failed"
|
|
1862
|
+
);
|
|
1863
|
+
}
|
|
1529
1864
|
} catch (e) {
|
|
1530
1865
|
console.error("Error in transmission", e);
|
|
1866
|
+
fetchDiagnostics.signalFailures++;
|
|
1867
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1868
|
+
this.recordFetchClientError(fetchId, serviceName, URL, e);
|
|
1531
1869
|
response = {
|
|
1532
1870
|
__error: `Error: ${e}`,
|
|
1533
1871
|
errored: true,
|
|
@@ -1545,6 +1883,8 @@ var RestController = class _RestController {
|
|
|
1545
1883
|
const statusTask = CadenzaService.createMetaTask(
|
|
1546
1884
|
`Request status from ${URL}`,
|
|
1547
1885
|
async (ctx2) => {
|
|
1886
|
+
fetchDiagnostics.statusChecks++;
|
|
1887
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1548
1888
|
let status;
|
|
1549
1889
|
try {
|
|
1550
1890
|
status = await this.fetchDataWithTimeout(
|
|
@@ -1554,7 +1894,20 @@ var RestController = class _RestController {
|
|
|
1554
1894
|
},
|
|
1555
1895
|
1e3
|
|
1556
1896
|
);
|
|
1897
|
+
if (status?.errored || status?.failed) {
|
|
1898
|
+
fetchDiagnostics.statusFailures++;
|
|
1899
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1900
|
+
this.recordFetchClientError(
|
|
1901
|
+
fetchId,
|
|
1902
|
+
serviceName,
|
|
1903
|
+
URL,
|
|
1904
|
+
status?.__error ?? status?.error ?? "Status check failed"
|
|
1905
|
+
);
|
|
1906
|
+
}
|
|
1557
1907
|
} catch (e) {
|
|
1908
|
+
fetchDiagnostics.statusFailures++;
|
|
1909
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1910
|
+
this.recordFetchClientError(fetchId, serviceName, URL, e);
|
|
1558
1911
|
status = {
|
|
1559
1912
|
__error: `Error: ${e}`,
|
|
1560
1913
|
errored: true,
|
|
@@ -1566,6 +1919,9 @@ var RestController = class _RestController {
|
|
|
1566
1919
|
"Requests status"
|
|
1567
1920
|
).doOn("meta.fetch.status_check_requested").emits("meta.fetch.status_checked").emitsOnFail("meta.fetch.status_check_failed");
|
|
1568
1921
|
CadenzaService.createEphemeralMetaTask("Destroy fetch client", () => {
|
|
1922
|
+
fetchDiagnostics.connected = false;
|
|
1923
|
+
fetchDiagnostics.destroyed = true;
|
|
1924
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1569
1925
|
CadenzaService.log("Destroying fetch client", { URL, serviceName });
|
|
1570
1926
|
handshakeTask.destroy();
|
|
1571
1927
|
delegateTask.destroy();
|
|
@@ -1614,6 +1970,144 @@ var RestController = class _RestController {
|
|
|
1614
1970
|
if (!this._instance) this._instance = new _RestController();
|
|
1615
1971
|
return this._instance;
|
|
1616
1972
|
}
|
|
1973
|
+
resolveTransportDiagnosticsOptions(ctx) {
|
|
1974
|
+
const detailLevel = ctx.detailLevel === "full" ? "full" : "summary";
|
|
1975
|
+
const includeErrorHistory = Boolean(ctx.includeErrorHistory);
|
|
1976
|
+
const requestedLimit = Number(ctx.errorHistoryLimit);
|
|
1977
|
+
const errorHistoryLimit = Number.isFinite(requestedLimit) ? Math.max(1, Math.min(200, Math.trunc(requestedLimit))) : 10;
|
|
1978
|
+
return {
|
|
1979
|
+
detailLevel,
|
|
1980
|
+
includeErrorHistory,
|
|
1981
|
+
errorHistoryLimit
|
|
1982
|
+
};
|
|
1983
|
+
}
|
|
1984
|
+
ensureFetchClientDiagnostics(fetchId, serviceName, url) {
|
|
1985
|
+
let state = this.fetchClientDiagnostics.get(fetchId);
|
|
1986
|
+
if (!state) {
|
|
1987
|
+
state = {
|
|
1988
|
+
fetchId,
|
|
1989
|
+
serviceName,
|
|
1990
|
+
url,
|
|
1991
|
+
connected: false,
|
|
1992
|
+
destroyed: false,
|
|
1993
|
+
lastHandshakeAt: null,
|
|
1994
|
+
lastHandshakeError: null,
|
|
1995
|
+
lastError: null,
|
|
1996
|
+
lastErrorAt: 0,
|
|
1997
|
+
errorHistory: [],
|
|
1998
|
+
delegationRequests: 0,
|
|
1999
|
+
delegationFailures: 0,
|
|
2000
|
+
signalTransmissions: 0,
|
|
2001
|
+
signalFailures: 0,
|
|
2002
|
+
statusChecks: 0,
|
|
2003
|
+
statusFailures: 0,
|
|
2004
|
+
updatedAt: Date.now()
|
|
2005
|
+
};
|
|
2006
|
+
this.fetchClientDiagnostics.set(fetchId, state);
|
|
2007
|
+
} else {
|
|
2008
|
+
state.serviceName = serviceName;
|
|
2009
|
+
state.url = url;
|
|
2010
|
+
}
|
|
2011
|
+
return state;
|
|
2012
|
+
}
|
|
2013
|
+
getErrorMessage(error) {
|
|
2014
|
+
if (error instanceof Error) {
|
|
2015
|
+
return error.message;
|
|
2016
|
+
}
|
|
2017
|
+
if (typeof error === "string") {
|
|
2018
|
+
return error;
|
|
2019
|
+
}
|
|
2020
|
+
try {
|
|
2021
|
+
return JSON.stringify(error);
|
|
2022
|
+
} catch {
|
|
2023
|
+
return String(error);
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
recordFetchClientError(fetchId, serviceName, url, error) {
|
|
2027
|
+
const state = this.ensureFetchClientDiagnostics(fetchId, serviceName, url);
|
|
2028
|
+
const message = this.getErrorMessage(error);
|
|
2029
|
+
const now = Date.now();
|
|
2030
|
+
state.lastError = message;
|
|
2031
|
+
state.lastErrorAt = now;
|
|
2032
|
+
state.updatedAt = now;
|
|
2033
|
+
state.errorHistory.push({ at: new Date(now).toISOString(), message });
|
|
2034
|
+
if (state.errorHistory.length > this.diagnosticsErrorHistoryLimit) {
|
|
2035
|
+
state.errorHistory.splice(
|
|
2036
|
+
0,
|
|
2037
|
+
state.errorHistory.length - this.diagnosticsErrorHistoryLimit
|
|
2038
|
+
);
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
collectFetchTransportDiagnostics(ctx) {
|
|
2042
|
+
const { detailLevel, includeErrorHistory, errorHistoryLimit } = this.resolveTransportDiagnosticsOptions(ctx);
|
|
2043
|
+
const serviceName = CadenzaService.serviceRegistry.serviceName ?? "UnknownService";
|
|
2044
|
+
const states = Array.from(this.fetchClientDiagnostics.values()).sort(
|
|
2045
|
+
(a, b) => a.fetchId.localeCompare(b.fetchId)
|
|
2046
|
+
);
|
|
2047
|
+
const summary = {
|
|
2048
|
+
detailLevel,
|
|
2049
|
+
totalClients: states.length,
|
|
2050
|
+
connectedClients: states.filter((state) => state.connected).length,
|
|
2051
|
+
destroyedClients: states.filter((state) => state.destroyed).length,
|
|
2052
|
+
delegationRequests: states.reduce(
|
|
2053
|
+
(acc, state) => acc + state.delegationRequests,
|
|
2054
|
+
0
|
|
2055
|
+
),
|
|
2056
|
+
delegationFailures: states.reduce(
|
|
2057
|
+
(acc, state) => acc + state.delegationFailures,
|
|
2058
|
+
0
|
|
2059
|
+
),
|
|
2060
|
+
signalTransmissions: states.reduce(
|
|
2061
|
+
(acc, state) => acc + state.signalTransmissions,
|
|
2062
|
+
0
|
|
2063
|
+
),
|
|
2064
|
+
signalFailures: states.reduce((acc, state) => acc + state.signalFailures, 0),
|
|
2065
|
+
statusChecks: states.reduce((acc, state) => acc + state.statusChecks, 0),
|
|
2066
|
+
statusFailures: states.reduce((acc, state) => acc + state.statusFailures, 0),
|
|
2067
|
+
latestError: states.slice().sort((a, b) => b.lastErrorAt - a.lastErrorAt).find((state) => state.lastError)?.lastError ?? null
|
|
2068
|
+
};
|
|
2069
|
+
if (detailLevel === "summary") {
|
|
2070
|
+
return {
|
|
2071
|
+
transportDiagnostics: {
|
|
2072
|
+
[serviceName]: {
|
|
2073
|
+
fetchClient: summary
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
};
|
|
2077
|
+
}
|
|
2078
|
+
const clients = states.map((state) => {
|
|
2079
|
+
const details = {
|
|
2080
|
+
fetchId: state.fetchId,
|
|
2081
|
+
serviceName: state.serviceName,
|
|
2082
|
+
url: state.url,
|
|
2083
|
+
connected: state.connected,
|
|
2084
|
+
destroyed: state.destroyed,
|
|
2085
|
+
lastHandshakeAt: state.lastHandshakeAt,
|
|
2086
|
+
lastHandshakeError: state.lastHandshakeError,
|
|
2087
|
+
latestError: state.lastError,
|
|
2088
|
+
delegationRequests: state.delegationRequests,
|
|
2089
|
+
delegationFailures: state.delegationFailures,
|
|
2090
|
+
signalTransmissions: state.signalTransmissions,
|
|
2091
|
+
signalFailures: state.signalFailures,
|
|
2092
|
+
statusChecks: state.statusChecks,
|
|
2093
|
+
statusFailures: state.statusFailures
|
|
2094
|
+
};
|
|
2095
|
+
if (includeErrorHistory) {
|
|
2096
|
+
details.errorHistory = state.errorHistory.slice(-errorHistoryLimit);
|
|
2097
|
+
}
|
|
2098
|
+
return details;
|
|
2099
|
+
});
|
|
2100
|
+
return {
|
|
2101
|
+
transportDiagnostics: {
|
|
2102
|
+
[serviceName]: {
|
|
2103
|
+
fetchClient: {
|
|
2104
|
+
...summary,
|
|
2105
|
+
clients
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
};
|
|
2110
|
+
}
|
|
1617
2111
|
};
|
|
1618
2112
|
|
|
1619
2113
|
// src/network/SocketController.ts
|
|
@@ -1661,10 +2155,6 @@ var waitForSocketConnection = async (socket, timeoutMs, createError) => {
|
|
|
1661
2155
|
|
|
1662
2156
|
// src/network/SocketController.ts
|
|
1663
2157
|
var SocketController = class _SocketController {
|
|
1664
|
-
static get instance() {
|
|
1665
|
-
if (!this._instance) this._instance = new _SocketController();
|
|
1666
|
-
return this._instance;
|
|
1667
|
-
}
|
|
1668
2158
|
/**
|
|
1669
2159
|
* Constructs the `SocketServer`, setting up a WebSocket server with specific configurations,
|
|
1670
2160
|
* including connection state recovery, rate limiting, CORS handling, and custom event handling.
|
|
@@ -1683,6 +2173,13 @@ var SocketController = class _SocketController {
|
|
|
1683
2173
|
* Initializes the `SocketServer` to be ready for WebSocket communication.
|
|
1684
2174
|
*/
|
|
1685
2175
|
constructor() {
|
|
2176
|
+
this.socketClientDiagnostics = /* @__PURE__ */ new Map();
|
|
2177
|
+
this.diagnosticsErrorHistoryLimit = 100;
|
|
2178
|
+
CadenzaService.createMetaTask(
|
|
2179
|
+
"Collect socket transport diagnostics",
|
|
2180
|
+
(ctx) => this.collectSocketTransportDiagnostics(ctx),
|
|
2181
|
+
"Responds to distributed transport diagnostics inquiries with socket client data."
|
|
2182
|
+
).respondsTo(META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT);
|
|
1686
2183
|
CadenzaService.createMetaRoutine(
|
|
1687
2184
|
"SocketServer",
|
|
1688
2185
|
[
|
|
@@ -1910,6 +2407,13 @@ var SocketController = class _SocketController {
|
|
|
1910
2407
|
const port = protocol === "https" ? 443 : servicePort;
|
|
1911
2408
|
const URL = `${socketProtocol}://${serviceAddress}:${port}`;
|
|
1912
2409
|
const fetchId = `${serviceAddress}_${port}`;
|
|
2410
|
+
const socketDiagnostics = this.ensureSocketClientDiagnostics(
|
|
2411
|
+
fetchId,
|
|
2412
|
+
serviceName,
|
|
2413
|
+
URL
|
|
2414
|
+
);
|
|
2415
|
+
socketDiagnostics.destroyed = false;
|
|
2416
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
1913
2417
|
let handshake = false;
|
|
1914
2418
|
let errorCount = 0;
|
|
1915
2419
|
const ERROR_LIMIT = 5;
|
|
@@ -1919,6 +2423,11 @@ var SocketController = class _SocketController {
|
|
|
1919
2423
|
}
|
|
1920
2424
|
const pendingDelegationIds = /* @__PURE__ */ new Set();
|
|
1921
2425
|
const pendingTimers = /* @__PURE__ */ new Set();
|
|
2426
|
+
const syncPendingCounts = () => {
|
|
2427
|
+
socketDiagnostics.pendingDelegations = pendingDelegationIds.size;
|
|
2428
|
+
socketDiagnostics.pendingTimers = pendingTimers.size;
|
|
2429
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2430
|
+
};
|
|
1922
2431
|
let handshakeTask = null;
|
|
1923
2432
|
let emitWhenReady = null;
|
|
1924
2433
|
let transmitTask = null;
|
|
@@ -1968,6 +2477,12 @@ var SocketController = class _SocketController {
|
|
|
1968
2477
|
{ socketId: socket?.id, serviceName, URL, event },
|
|
1969
2478
|
"error"
|
|
1970
2479
|
);
|
|
2480
|
+
this.recordSocketClientError(
|
|
2481
|
+
fetchId,
|
|
2482
|
+
serviceName,
|
|
2483
|
+
URL,
|
|
2484
|
+
waitResult.error
|
|
2485
|
+
);
|
|
1971
2486
|
resolveWithError(waitResult.error);
|
|
1972
2487
|
return;
|
|
1973
2488
|
}
|
|
@@ -1976,6 +2491,7 @@ var SocketController = class _SocketController {
|
|
|
1976
2491
|
timer = setTimeout(() => {
|
|
1977
2492
|
if (timer) {
|
|
1978
2493
|
pendingTimers.delete(timer);
|
|
2494
|
+
syncPendingCounts();
|
|
1979
2495
|
timer = null;
|
|
1980
2496
|
}
|
|
1981
2497
|
CadenzaService.log(
|
|
@@ -1983,9 +2499,16 @@ var SocketController = class _SocketController {
|
|
|
1983
2499
|
{ socketId: socket?.id, serviceName, URL },
|
|
1984
2500
|
"error"
|
|
1985
2501
|
);
|
|
2502
|
+
this.recordSocketClientError(
|
|
2503
|
+
fetchId,
|
|
2504
|
+
serviceName,
|
|
2505
|
+
URL,
|
|
2506
|
+
`Socket event '${event}' timed out`
|
|
2507
|
+
);
|
|
1986
2508
|
resolveWithError(`Socket event '${event}' timed out`);
|
|
1987
2509
|
}, timeoutMs + 10);
|
|
1988
2510
|
pendingTimers.add(timer);
|
|
2511
|
+
syncPendingCounts();
|
|
1989
2512
|
}
|
|
1990
2513
|
const connectedSocket = socket;
|
|
1991
2514
|
if (!connectedSocket) {
|
|
@@ -1998,6 +2521,7 @@ var SocketController = class _SocketController {
|
|
|
1998
2521
|
if (timer) {
|
|
1999
2522
|
clearTimeout(timer);
|
|
2000
2523
|
pendingTimers.delete(timer);
|
|
2524
|
+
syncPendingCounts();
|
|
2001
2525
|
timer = null;
|
|
2002
2526
|
}
|
|
2003
2527
|
if (err) {
|
|
@@ -2011,6 +2535,12 @@ var SocketController = class _SocketController {
|
|
|
2011
2535
|
},
|
|
2012
2536
|
"warning"
|
|
2013
2537
|
);
|
|
2538
|
+
this.recordSocketClientError(
|
|
2539
|
+
fetchId,
|
|
2540
|
+
serviceName,
|
|
2541
|
+
URL,
|
|
2542
|
+
err
|
|
2543
|
+
);
|
|
2014
2544
|
response = {
|
|
2015
2545
|
__error: `Timeout error: ${err}`,
|
|
2016
2546
|
errored: true,
|
|
@@ -2027,6 +2557,10 @@ var SocketController = class _SocketController {
|
|
|
2027
2557
|
};
|
|
2028
2558
|
socket.on("connect", () => {
|
|
2029
2559
|
if (handshake) return;
|
|
2560
|
+
socketDiagnostics.connected = true;
|
|
2561
|
+
socketDiagnostics.destroyed = false;
|
|
2562
|
+
socketDiagnostics.socketId = socket?.id ?? null;
|
|
2563
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2030
2564
|
CadenzaService.emit(`meta.socket_client.connected:${fetchId}`, ctx);
|
|
2031
2565
|
});
|
|
2032
2566
|
socket.on("delegation_progress", (ctx2) => {
|
|
@@ -2045,6 +2579,12 @@ var SocketController = class _SocketController {
|
|
|
2045
2579
|
});
|
|
2046
2580
|
socket.on("connect_error", (err) => {
|
|
2047
2581
|
handshake = false;
|
|
2582
|
+
socketDiagnostics.connected = false;
|
|
2583
|
+
socketDiagnostics.handshake = false;
|
|
2584
|
+
socketDiagnostics.connectErrors++;
|
|
2585
|
+
socketDiagnostics.lastHandshakeError = err.message;
|
|
2586
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2587
|
+
this.recordSocketClientError(fetchId, serviceName, URL, err);
|
|
2048
2588
|
CadenzaService.log(
|
|
2049
2589
|
"Socket connect error",
|
|
2050
2590
|
{ error: err.message, serviceName, socketId: socket?.id, URL },
|
|
@@ -2053,9 +2593,16 @@ var SocketController = class _SocketController {
|
|
|
2053
2593
|
CadenzaService.emit(`meta.socket_client.connect_error:${fetchId}`, err);
|
|
2054
2594
|
});
|
|
2055
2595
|
socket.on("reconnect_attempt", (attempt) => {
|
|
2596
|
+
socketDiagnostics.reconnectAttempts = Math.max(
|
|
2597
|
+
socketDiagnostics.reconnectAttempts,
|
|
2598
|
+
attempt
|
|
2599
|
+
);
|
|
2600
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2056
2601
|
CadenzaService.log(`Reconnect attempt: ${attempt}`);
|
|
2057
2602
|
});
|
|
2058
2603
|
socket.on("reconnect", (attempt) => {
|
|
2604
|
+
socketDiagnostics.connected = true;
|
|
2605
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2059
2606
|
CadenzaService.log(`Socket reconnected after ${attempt} tries`, {
|
|
2060
2607
|
socketId: socket?.id,
|
|
2061
2608
|
URL,
|
|
@@ -2064,6 +2611,12 @@ var SocketController = class _SocketController {
|
|
|
2064
2611
|
});
|
|
2065
2612
|
socket.on("reconnect_error", (err) => {
|
|
2066
2613
|
handshake = false;
|
|
2614
|
+
socketDiagnostics.connected = false;
|
|
2615
|
+
socketDiagnostics.handshake = false;
|
|
2616
|
+
socketDiagnostics.reconnectErrors++;
|
|
2617
|
+
socketDiagnostics.lastHandshakeError = err.message;
|
|
2618
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2619
|
+
this.recordSocketClientError(fetchId, serviceName, URL, err);
|
|
2067
2620
|
CadenzaService.log(
|
|
2068
2621
|
"Socket reconnect failed.",
|
|
2069
2622
|
{ error: err.message, serviceName, URL, socketId: socket?.id },
|
|
@@ -2072,6 +2625,9 @@ var SocketController = class _SocketController {
|
|
|
2072
2625
|
});
|
|
2073
2626
|
socket.on("error", (err) => {
|
|
2074
2627
|
errorCount++;
|
|
2628
|
+
socketDiagnostics.socketErrors++;
|
|
2629
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2630
|
+
this.recordSocketClientError(fetchId, serviceName, URL, err);
|
|
2075
2631
|
CadenzaService.log(
|
|
2076
2632
|
"Socket error",
|
|
2077
2633
|
{ error: err, socketId: socket?.id, URL, serviceName },
|
|
@@ -2080,6 +2636,11 @@ var SocketController = class _SocketController {
|
|
|
2080
2636
|
CadenzaService.emit("meta.socket_client.error", err);
|
|
2081
2637
|
});
|
|
2082
2638
|
socket.on("disconnect", () => {
|
|
2639
|
+
const disconnectedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2640
|
+
socketDiagnostics.connected = false;
|
|
2641
|
+
socketDiagnostics.handshake = false;
|
|
2642
|
+
socketDiagnostics.lastDisconnectAt = disconnectedAt;
|
|
2643
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2083
2644
|
CadenzaService.log(
|
|
2084
2645
|
"Socket disconnected.",
|
|
2085
2646
|
{ URL, serviceName, socketId: socket?.id },
|
|
@@ -2098,6 +2659,8 @@ var SocketController = class _SocketController {
|
|
|
2098
2659
|
async (ctx2, emit) => {
|
|
2099
2660
|
if (handshake) return;
|
|
2100
2661
|
handshake = true;
|
|
2662
|
+
socketDiagnostics.handshake = true;
|
|
2663
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2101
2664
|
await emitWhenReady?.(
|
|
2102
2665
|
"handshake",
|
|
2103
2666
|
{
|
|
@@ -2109,6 +2672,11 @@ var SocketController = class _SocketController {
|
|
|
2109
2672
|
1e4,
|
|
2110
2673
|
(result) => {
|
|
2111
2674
|
if (result.status === "success") {
|
|
2675
|
+
socketDiagnostics.connected = true;
|
|
2676
|
+
socketDiagnostics.handshake = true;
|
|
2677
|
+
socketDiagnostics.lastHandshakeAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2678
|
+
socketDiagnostics.lastHandshakeError = null;
|
|
2679
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2112
2680
|
CadenzaService.log("Socket client connected", {
|
|
2113
2681
|
result,
|
|
2114
2682
|
serviceName,
|
|
@@ -2116,6 +2684,16 @@ var SocketController = class _SocketController {
|
|
|
2116
2684
|
URL
|
|
2117
2685
|
});
|
|
2118
2686
|
} else {
|
|
2687
|
+
socketDiagnostics.connected = false;
|
|
2688
|
+
socketDiagnostics.handshake = false;
|
|
2689
|
+
socketDiagnostics.lastHandshakeError = result?.__error ?? result?.error ?? "Socket handshake failed";
|
|
2690
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2691
|
+
this.recordSocketClientError(
|
|
2692
|
+
fetchId,
|
|
2693
|
+
serviceName,
|
|
2694
|
+
URL,
|
|
2695
|
+
socketDiagnostics.lastHandshakeError
|
|
2696
|
+
);
|
|
2119
2697
|
CadenzaService.log(
|
|
2120
2698
|
"Socket handshake failed",
|
|
2121
2699
|
{ result, serviceName, socketId: socket?.id, URL },
|
|
@@ -2138,6 +2716,7 @@ var SocketController = class _SocketController {
|
|
|
2138
2716
|
delete ctx2.__broadcast;
|
|
2139
2717
|
const requestSentAt = Date.now();
|
|
2140
2718
|
pendingDelegationIds.add(ctx2.__metadata.__deputyExecId);
|
|
2719
|
+
syncPendingCounts();
|
|
2141
2720
|
emitWhenReady?.(
|
|
2142
2721
|
"delegation",
|
|
2143
2722
|
ctx2,
|
|
@@ -2155,6 +2734,15 @@ var SocketController = class _SocketController {
|
|
|
2155
2734
|
}
|
|
2156
2735
|
);
|
|
2157
2736
|
pendingDelegationIds.delete(ctx2.__metadata.__deputyExecId);
|
|
2737
|
+
syncPendingCounts();
|
|
2738
|
+
if (resultContext?.errored || resultContext?.failed) {
|
|
2739
|
+
this.recordSocketClientError(
|
|
2740
|
+
fetchId,
|
|
2741
|
+
serviceName,
|
|
2742
|
+
URL,
|
|
2743
|
+
resultContext?.__error ?? resultContext?.error ?? "Socket delegation failed"
|
|
2744
|
+
);
|
|
2745
|
+
}
|
|
2158
2746
|
resolve(resultContext);
|
|
2159
2747
|
}
|
|
2160
2748
|
);
|
|
@@ -2190,6 +2778,10 @@ var SocketController = class _SocketController {
|
|
|
2190
2778
|
`Shutdown SocketClient ${URL}`,
|
|
2191
2779
|
(ctx2, emit) => {
|
|
2192
2780
|
handshake = false;
|
|
2781
|
+
socketDiagnostics.connected = false;
|
|
2782
|
+
socketDiagnostics.handshake = false;
|
|
2783
|
+
socketDiagnostics.destroyed = true;
|
|
2784
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2193
2785
|
CadenzaService.log("Shutting down socket client", { URL, serviceName });
|
|
2194
2786
|
socket?.close();
|
|
2195
2787
|
handshakeTask?.destroy();
|
|
@@ -2219,10 +2811,12 @@ var SocketController = class _SocketController {
|
|
|
2219
2811
|
});
|
|
2220
2812
|
}
|
|
2221
2813
|
pendingDelegationIds.clear();
|
|
2814
|
+
syncPendingCounts();
|
|
2222
2815
|
for (const timer of pendingTimers) {
|
|
2223
2816
|
clearTimeout(timer);
|
|
2224
2817
|
}
|
|
2225
2818
|
pendingTimers.clear();
|
|
2819
|
+
syncPendingCounts();
|
|
2226
2820
|
},
|
|
2227
2821
|
"Shuts down the socket client"
|
|
2228
2822
|
).doOn(
|
|
@@ -2236,6 +2830,157 @@ var SocketController = class _SocketController {
|
|
|
2236
2830
|
"Connects to a specified socket server"
|
|
2237
2831
|
).doOn("meta.fetch.handshake_complete").emitsOnFail("meta.socket_client.connect_failed");
|
|
2238
2832
|
}
|
|
2833
|
+
static get instance() {
|
|
2834
|
+
if (!this._instance) this._instance = new _SocketController();
|
|
2835
|
+
return this._instance;
|
|
2836
|
+
}
|
|
2837
|
+
resolveTransportDiagnosticsOptions(ctx) {
|
|
2838
|
+
const detailLevel = ctx.detailLevel === "full" ? "full" : "summary";
|
|
2839
|
+
const includeErrorHistory = Boolean(ctx.includeErrorHistory);
|
|
2840
|
+
const requestedLimit = Number(ctx.errorHistoryLimit);
|
|
2841
|
+
const errorHistoryLimit = Number.isFinite(requestedLimit) ? Math.max(1, Math.min(200, Math.trunc(requestedLimit))) : 10;
|
|
2842
|
+
return {
|
|
2843
|
+
detailLevel,
|
|
2844
|
+
includeErrorHistory,
|
|
2845
|
+
errorHistoryLimit
|
|
2846
|
+
};
|
|
2847
|
+
}
|
|
2848
|
+
ensureSocketClientDiagnostics(fetchId, serviceName, url) {
|
|
2849
|
+
let state = this.socketClientDiagnostics.get(fetchId);
|
|
2850
|
+
if (!state) {
|
|
2851
|
+
state = {
|
|
2852
|
+
fetchId,
|
|
2853
|
+
serviceName,
|
|
2854
|
+
url,
|
|
2855
|
+
socketId: null,
|
|
2856
|
+
connected: false,
|
|
2857
|
+
handshake: false,
|
|
2858
|
+
reconnectAttempts: 0,
|
|
2859
|
+
connectErrors: 0,
|
|
2860
|
+
reconnectErrors: 0,
|
|
2861
|
+
socketErrors: 0,
|
|
2862
|
+
pendingDelegations: 0,
|
|
2863
|
+
pendingTimers: 0,
|
|
2864
|
+
destroyed: false,
|
|
2865
|
+
lastHandshakeAt: null,
|
|
2866
|
+
lastHandshakeError: null,
|
|
2867
|
+
lastDisconnectAt: null,
|
|
2868
|
+
lastError: null,
|
|
2869
|
+
lastErrorAt: 0,
|
|
2870
|
+
errorHistory: [],
|
|
2871
|
+
updatedAt: Date.now()
|
|
2872
|
+
};
|
|
2873
|
+
this.socketClientDiagnostics.set(fetchId, state);
|
|
2874
|
+
} else {
|
|
2875
|
+
state.serviceName = serviceName;
|
|
2876
|
+
state.url = url;
|
|
2877
|
+
}
|
|
2878
|
+
return state;
|
|
2879
|
+
}
|
|
2880
|
+
getErrorMessage(error) {
|
|
2881
|
+
if (error instanceof Error) {
|
|
2882
|
+
return error.message;
|
|
2883
|
+
}
|
|
2884
|
+
if (typeof error === "string") {
|
|
2885
|
+
return error;
|
|
2886
|
+
}
|
|
2887
|
+
try {
|
|
2888
|
+
return JSON.stringify(error);
|
|
2889
|
+
} catch {
|
|
2890
|
+
return String(error);
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
recordSocketClientError(fetchId, serviceName, url, error) {
|
|
2894
|
+
const state = this.ensureSocketClientDiagnostics(fetchId, serviceName, url);
|
|
2895
|
+
const message = this.getErrorMessage(error);
|
|
2896
|
+
const now = Date.now();
|
|
2897
|
+
state.lastError = message;
|
|
2898
|
+
state.lastErrorAt = now;
|
|
2899
|
+
state.updatedAt = now;
|
|
2900
|
+
state.errorHistory.push({
|
|
2901
|
+
at: new Date(now).toISOString(),
|
|
2902
|
+
message
|
|
2903
|
+
});
|
|
2904
|
+
if (state.errorHistory.length > this.diagnosticsErrorHistoryLimit) {
|
|
2905
|
+
state.errorHistory.splice(
|
|
2906
|
+
0,
|
|
2907
|
+
state.errorHistory.length - this.diagnosticsErrorHistoryLimit
|
|
2908
|
+
);
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
collectSocketTransportDiagnostics(ctx) {
|
|
2912
|
+
const { detailLevel, includeErrorHistory, errorHistoryLimit } = this.resolveTransportDiagnosticsOptions(ctx);
|
|
2913
|
+
const serviceName = CadenzaService.serviceRegistry.serviceName ?? "UnknownService";
|
|
2914
|
+
const states = Array.from(this.socketClientDiagnostics.values()).sort(
|
|
2915
|
+
(a, b) => a.fetchId.localeCompare(b.fetchId)
|
|
2916
|
+
);
|
|
2917
|
+
const summary = {
|
|
2918
|
+
detailLevel,
|
|
2919
|
+
totalClients: states.length,
|
|
2920
|
+
connectedClients: states.filter((state) => state.connected).length,
|
|
2921
|
+
activeHandshakes: states.filter((state) => state.handshake).length,
|
|
2922
|
+
pendingDelegations: states.reduce(
|
|
2923
|
+
(acc, state) => acc + state.pendingDelegations,
|
|
2924
|
+
0
|
|
2925
|
+
),
|
|
2926
|
+
pendingTimers: states.reduce((acc, state) => acc + state.pendingTimers, 0),
|
|
2927
|
+
reconnectAttempts: states.reduce(
|
|
2928
|
+
(acc, state) => acc + state.reconnectAttempts,
|
|
2929
|
+
0
|
|
2930
|
+
),
|
|
2931
|
+
connectErrors: states.reduce((acc, state) => acc + state.connectErrors, 0),
|
|
2932
|
+
reconnectErrors: states.reduce(
|
|
2933
|
+
(acc, state) => acc + state.reconnectErrors,
|
|
2934
|
+
0
|
|
2935
|
+
),
|
|
2936
|
+
socketErrors: states.reduce((acc, state) => acc + state.socketErrors, 0),
|
|
2937
|
+
latestError: states.slice().sort((a, b) => b.lastErrorAt - a.lastErrorAt).find((state) => state.lastError)?.lastError ?? null
|
|
2938
|
+
};
|
|
2939
|
+
if (detailLevel === "summary") {
|
|
2940
|
+
return {
|
|
2941
|
+
transportDiagnostics: {
|
|
2942
|
+
[serviceName]: {
|
|
2943
|
+
socketClient: summary
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
};
|
|
2947
|
+
}
|
|
2948
|
+
const clients = states.map((state) => {
|
|
2949
|
+
const details = {
|
|
2950
|
+
fetchId: state.fetchId,
|
|
2951
|
+
serviceName: state.serviceName,
|
|
2952
|
+
url: state.url,
|
|
2953
|
+
socketId: state.socketId,
|
|
2954
|
+
connected: state.connected,
|
|
2955
|
+
handshake: state.handshake,
|
|
2956
|
+
reconnectAttempts: state.reconnectAttempts,
|
|
2957
|
+
connectErrors: state.connectErrors,
|
|
2958
|
+
reconnectErrors: state.reconnectErrors,
|
|
2959
|
+
socketErrors: state.socketErrors,
|
|
2960
|
+
pendingDelegations: state.pendingDelegations,
|
|
2961
|
+
pendingTimers: state.pendingTimers,
|
|
2962
|
+
destroyed: state.destroyed,
|
|
2963
|
+
lastHandshakeAt: state.lastHandshakeAt,
|
|
2964
|
+
lastHandshakeError: state.lastHandshakeError,
|
|
2965
|
+
lastDisconnectAt: state.lastDisconnectAt,
|
|
2966
|
+
latestError: state.lastError
|
|
2967
|
+
};
|
|
2968
|
+
if (includeErrorHistory) {
|
|
2969
|
+
details.errorHistory = state.errorHistory.slice(-errorHistoryLimit);
|
|
2970
|
+
}
|
|
2971
|
+
return details;
|
|
2972
|
+
});
|
|
2973
|
+
return {
|
|
2974
|
+
transportDiagnostics: {
|
|
2975
|
+
[serviceName]: {
|
|
2976
|
+
socketClient: {
|
|
2977
|
+
...summary,
|
|
2978
|
+
clients
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
};
|
|
2983
|
+
}
|
|
2239
2984
|
};
|
|
2240
2985
|
|
|
2241
2986
|
// src/utils/tools.ts
|
|
@@ -2339,25 +3084,8 @@ var GraphMetadataController = class _GraphMetadataController {
|
|
|
2339
3084
|
return {
|
|
2340
3085
|
data: {
|
|
2341
3086
|
...ctx.data,
|
|
2342
|
-
serviceName: CadenzaService.serviceRegistry.serviceName
|
|
2343
|
-
|
|
2344
|
-
subOperation: "insert",
|
|
2345
|
-
table: "context_schema",
|
|
2346
|
-
data: {
|
|
2347
|
-
...ctx.data.inputContextSchemaId
|
|
2348
|
-
},
|
|
2349
|
-
return: "uuid"
|
|
2350
|
-
} : null,
|
|
2351
|
-
outputContextSchemaId: ctx.data.outputContextSchemaId ? {
|
|
2352
|
-
subOperation: "insert",
|
|
2353
|
-
table: "context_schema",
|
|
2354
|
-
data: {
|
|
2355
|
-
...ctx.data.outputContextSchemaId
|
|
2356
|
-
},
|
|
2357
|
-
return: "uuid"
|
|
2358
|
-
} : null
|
|
2359
|
-
},
|
|
2360
|
-
transaction: true
|
|
3087
|
+
serviceName: CadenzaService.serviceRegistry.serviceName
|
|
3088
|
+
}
|
|
2361
3089
|
};
|
|
2362
3090
|
}).doOn("meta.task.created").emits("global.meta.graph_metadata.task_created");
|
|
2363
3091
|
CadenzaService.createMetaTask("Handle task update", (ctx) => {
|
|
@@ -2564,9 +3292,11 @@ var GraphMetadataController = class _GraphMetadataController {
|
|
|
2564
3292
|
{ concurrency: 100, isSubMeta: true }
|
|
2565
3293
|
).doOn("meta.node.mapped", "meta.node.detected_previous_task_execution").emits("global.meta.graph_metadata.relationship_executed");
|
|
2566
3294
|
CadenzaService.createMetaTask("Handle Intent Creation", (ctx) => {
|
|
3295
|
+
const intentName = ctx.data?.name;
|
|
2567
3296
|
return {
|
|
2568
3297
|
data: {
|
|
2569
|
-
...ctx.data
|
|
3298
|
+
...ctx.data,
|
|
3299
|
+
isMeta: intentName ? isMetaIntentName(intentName) : false
|
|
2570
3300
|
}
|
|
2571
3301
|
};
|
|
2572
3302
|
}).doOn("meta.inquiry_broker.added").emits("global.meta.graph_metadata.intent_created");
|
|
@@ -2598,6 +3328,52 @@ var SCHEMA_TYPES = [
|
|
|
2598
3328
|
// src/database/DatabaseController.ts
|
|
2599
3329
|
import { Pool } from "pg";
|
|
2600
3330
|
import { camelCase, snakeCase } from "lodash-es";
|
|
3331
|
+
function resolveTableQueryIntents(serviceName, tableName, table, defaultInputSchema) {
|
|
3332
|
+
const resolvedServiceName = serviceName ?? "unknown-service";
|
|
3333
|
+
const defaultIntentName = `query-${resolvedServiceName}-${tableName}`;
|
|
3334
|
+
const defaultDescription = `Perform a query operation on the ${tableName} table`;
|
|
3335
|
+
const intents = [
|
|
3336
|
+
{
|
|
3337
|
+
name: defaultIntentName,
|
|
3338
|
+
description: defaultDescription,
|
|
3339
|
+
input: defaultInputSchema
|
|
3340
|
+
}
|
|
3341
|
+
];
|
|
3342
|
+
const warnings = [];
|
|
3343
|
+
const names = /* @__PURE__ */ new Set([defaultIntentName]);
|
|
3344
|
+
for (const customIntent of table.customIntents?.query ?? []) {
|
|
3345
|
+
const name = typeof customIntent === "string" ? customIntent.trim() : customIntent.intent?.trim();
|
|
3346
|
+
if (!name) {
|
|
3347
|
+
warnings.push(`Skipped empty custom query intent for table '${tableName}'.`);
|
|
3348
|
+
continue;
|
|
3349
|
+
}
|
|
3350
|
+
if (name.length > 100) {
|
|
3351
|
+
warnings.push(
|
|
3352
|
+
`Skipped custom query intent '${name}' for table '${tableName}': name must be <= 100 characters.`
|
|
3353
|
+
);
|
|
3354
|
+
continue;
|
|
3355
|
+
}
|
|
3356
|
+
if (name.includes(" ") || name.includes(".") || name.includes("\\")) {
|
|
3357
|
+
warnings.push(
|
|
3358
|
+
`Skipped custom query intent '${name}' for table '${tableName}': name cannot contain spaces, dots or backslashes.`
|
|
3359
|
+
);
|
|
3360
|
+
continue;
|
|
3361
|
+
}
|
|
3362
|
+
if (names.has(name)) {
|
|
3363
|
+
warnings.push(
|
|
3364
|
+
`Skipped duplicate custom query intent '${name}' for table '${tableName}'.`
|
|
3365
|
+
);
|
|
3366
|
+
continue;
|
|
3367
|
+
}
|
|
3368
|
+
names.add(name);
|
|
3369
|
+
intents.push({
|
|
3370
|
+
name,
|
|
3371
|
+
description: typeof customIntent === "string" ? `Perform a query operation on the ${tableName} table` : customIntent.description ?? defaultDescription,
|
|
3372
|
+
input: typeof customIntent === "string" ? defaultInputSchema : customIntent.input ?? defaultInputSchema
|
|
3373
|
+
});
|
|
3374
|
+
}
|
|
3375
|
+
return { intents, warnings };
|
|
3376
|
+
}
|
|
2601
3377
|
var DatabaseController = class _DatabaseController {
|
|
2602
3378
|
/**
|
|
2603
3379
|
* Constructor for initializing the `DatabaseService` class.
|
|
@@ -2739,6 +3515,20 @@ var DatabaseController = class _DatabaseController {
|
|
|
2739
3515
|
}
|
|
2740
3516
|
}
|
|
2741
3517
|
}
|
|
3518
|
+
if (table.customIntents?.query) {
|
|
3519
|
+
if (!Array.isArray(table.customIntents.query)) {
|
|
3520
|
+
throw new Error(
|
|
3521
|
+
`Invalid customIntents.query for ${tableName}: expected array`
|
|
3522
|
+
);
|
|
3523
|
+
}
|
|
3524
|
+
for (const customIntent of table.customIntents.query) {
|
|
3525
|
+
if (typeof customIntent !== "string" && (typeof customIntent !== "object" || !customIntent || typeof customIntent.intent !== "string")) {
|
|
3526
|
+
throw new Error(
|
|
3527
|
+
`Invalid custom query intent on ${tableName}: expected string or object with intent`
|
|
3528
|
+
);
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
}
|
|
2742
3532
|
}
|
|
2743
3533
|
}
|
|
2744
3534
|
console.log("SCHEMA VALIDATED");
|
|
@@ -3775,13 +4565,30 @@ var DatabaseController = class _DatabaseController {
|
|
|
3775
4565
|
}) ?? []
|
|
3776
4566
|
);
|
|
3777
4567
|
if (op === "query") {
|
|
3778
|
-
const
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
4568
|
+
const { intents, warnings } = resolveTableQueryIntents(
|
|
4569
|
+
CadenzaService.serviceRegistry?.serviceName,
|
|
4570
|
+
tableName,
|
|
4571
|
+
table,
|
|
4572
|
+
schema
|
|
4573
|
+
);
|
|
4574
|
+
for (const warning of warnings) {
|
|
4575
|
+
CadenzaService.log(
|
|
4576
|
+
"Skipped custom query intent registration.",
|
|
4577
|
+
{
|
|
4578
|
+
tableName,
|
|
4579
|
+
warning
|
|
4580
|
+
},
|
|
4581
|
+
"warning"
|
|
4582
|
+
);
|
|
4583
|
+
}
|
|
4584
|
+
for (const intent of intents) {
|
|
4585
|
+
CadenzaService.defineIntent({
|
|
4586
|
+
name: intent.name,
|
|
4587
|
+
description: intent.description,
|
|
4588
|
+
input: intent.input
|
|
4589
|
+
});
|
|
4590
|
+
}
|
|
4591
|
+
task.respondsTo(...intents.map((intent) => intent.name));
|
|
3785
4592
|
}
|
|
3786
4593
|
}
|
|
3787
4594
|
getInputSchema(op, tableName, table) {
|
|
@@ -3873,18 +4680,18 @@ function getInsertDataSchemaFromTable(table, tableName) {
|
|
|
3873
4680
|
Object.entries(table.fields).map((field) => {
|
|
3874
4681
|
return [
|
|
3875
4682
|
field[0],
|
|
3876
|
-
|
|
3877
|
-
{
|
|
4683
|
+
{
|
|
4684
|
+
value: {
|
|
3878
4685
|
type: tableFieldTypeToSchemaType(field[1].type),
|
|
3879
4686
|
description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
|
|
3880
4687
|
},
|
|
3881
|
-
{
|
|
4688
|
+
effect: {
|
|
3882
4689
|
type: "string",
|
|
3883
4690
|
constraints: {
|
|
3884
4691
|
oneOf: ["increment", "decrement", "set"]
|
|
3885
4692
|
}
|
|
3886
4693
|
},
|
|
3887
|
-
{
|
|
4694
|
+
subOperation: {
|
|
3888
4695
|
type: "object",
|
|
3889
4696
|
properties: {
|
|
3890
4697
|
subOperation: {
|
|
@@ -3894,17 +4701,17 @@ function getInsertDataSchemaFromTable(table, tableName) {
|
|
|
3894
4701
|
table: {
|
|
3895
4702
|
type: "string"
|
|
3896
4703
|
},
|
|
3897
|
-
data:
|
|
3898
|
-
{
|
|
4704
|
+
data: {
|
|
4705
|
+
single: {
|
|
3899
4706
|
type: "object"
|
|
3900
4707
|
},
|
|
3901
|
-
{
|
|
4708
|
+
batch: {
|
|
3902
4709
|
type: "array",
|
|
3903
4710
|
items: {
|
|
3904
4711
|
type: "object"
|
|
3905
4712
|
}
|
|
3906
4713
|
}
|
|
3907
|
-
|
|
4714
|
+
},
|
|
3908
4715
|
filter: {
|
|
3909
4716
|
type: "object"
|
|
3910
4717
|
},
|
|
@@ -3920,7 +4727,7 @@ function getInsertDataSchemaFromTable(table, tableName) {
|
|
|
3920
4727
|
},
|
|
3921
4728
|
required: ["subOperation", "table"]
|
|
3922
4729
|
}
|
|
3923
|
-
|
|
4730
|
+
}
|
|
3924
4731
|
];
|
|
3925
4732
|
})
|
|
3926
4733
|
)
|
|
@@ -3928,13 +4735,13 @@ function getInsertDataSchemaFromTable(table, tableName) {
|
|
|
3928
4735
|
required: Object.entries(table.fields).filter((field) => field[1].required || field[1].primary).map((field) => field[0]),
|
|
3929
4736
|
strict: true
|
|
3930
4737
|
};
|
|
3931
|
-
return
|
|
3932
|
-
dataSchema,
|
|
3933
|
-
{
|
|
4738
|
+
return {
|
|
4739
|
+
single: dataSchema,
|
|
4740
|
+
batch: {
|
|
3934
4741
|
type: "array",
|
|
3935
4742
|
items: dataSchema
|
|
3936
4743
|
}
|
|
3937
|
-
|
|
4744
|
+
};
|
|
3938
4745
|
}
|
|
3939
4746
|
function getQueryFilterSchemaFromTable(table, tableName) {
|
|
3940
4747
|
return {
|
|
@@ -3944,24 +4751,24 @@ function getQueryFilterSchemaFromTable(table, tableName) {
|
|
|
3944
4751
|
Object.entries(table.fields).map((field) => {
|
|
3945
4752
|
return [
|
|
3946
4753
|
field[0],
|
|
3947
|
-
|
|
3948
|
-
{
|
|
4754
|
+
{
|
|
4755
|
+
value: {
|
|
3949
4756
|
type: tableFieldTypeToSchemaType(field[1].type),
|
|
3950
4757
|
description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
|
|
3951
4758
|
},
|
|
3952
|
-
{
|
|
4759
|
+
in: {
|
|
3953
4760
|
type: "array",
|
|
3954
4761
|
items: {
|
|
3955
4762
|
type: tableFieldTypeToSchemaType(field[1].type)
|
|
3956
4763
|
}
|
|
3957
4764
|
}
|
|
3958
|
-
|
|
4765
|
+
}
|
|
3959
4766
|
];
|
|
3960
4767
|
})
|
|
3961
4768
|
)
|
|
3962
4769
|
},
|
|
3963
4770
|
strict: true,
|
|
3964
|
-
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry
|
|
4771
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry?.serviceName ?? "unknown-service"}.`
|
|
3965
4772
|
};
|
|
3966
4773
|
}
|
|
3967
4774
|
function getQueryFieldsSchemaFromTable(table, tableName) {
|
|
@@ -3973,7 +4780,7 @@ function getQueryFieldsSchemaFromTable(table, tableName) {
|
|
|
3973
4780
|
oneOf: Object.keys(table.fields)
|
|
3974
4781
|
}
|
|
3975
4782
|
},
|
|
3976
|
-
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry
|
|
4783
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry?.serviceName ?? "unknown-service"}.`
|
|
3977
4784
|
};
|
|
3978
4785
|
}
|
|
3979
4786
|
function getQueryJoinsSchemaFromTable(table, tableName) {
|
|
@@ -4020,7 +4827,7 @@ function getQueryJoinsSchemaFromTable(table, tableName) {
|
|
|
4020
4827
|
)
|
|
4021
4828
|
},
|
|
4022
4829
|
strict: true,
|
|
4023
|
-
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry
|
|
4830
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry?.serviceName ?? "unknown-service"}.`
|
|
4024
4831
|
};
|
|
4025
4832
|
}
|
|
4026
4833
|
function getQuerySortSchemaFromTable(table, tableName) {
|
|
@@ -4042,7 +4849,7 @@ function getQuerySortSchemaFromTable(table, tableName) {
|
|
|
4042
4849
|
)
|
|
4043
4850
|
},
|
|
4044
4851
|
strict: true,
|
|
4045
|
-
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry
|
|
4852
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry?.serviceName ?? "unknown-service"}.`
|
|
4046
4853
|
};
|
|
4047
4854
|
}
|
|
4048
4855
|
function getQueryLimitSchemaFromTable() {
|
|
@@ -4104,12 +4911,10 @@ function getQueryOnConflictSchemaFromTable(table, tableName) {
|
|
|
4104
4911
|
Object.entries(table.fields).map((field) => {
|
|
4105
4912
|
return [
|
|
4106
4913
|
field[0],
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
}
|
|
4112
|
-
]
|
|
4914
|
+
{
|
|
4915
|
+
type: tableFieldTypeToSchemaType(field[1].type),
|
|
4916
|
+
description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
|
|
4917
|
+
}
|
|
4113
4918
|
];
|
|
4114
4919
|
})
|
|
4115
4920
|
)
|
|
@@ -4467,6 +5272,75 @@ var GraphSyncController = class _GraphSyncController {
|
|
|
4467
5272
|
{ concurrency: 30 }
|
|
4468
5273
|
) : CadenzaService.get("dbInsertSignalToTaskMap"))?.then(registerSignalTask)
|
|
4469
5274
|
);
|
|
5275
|
+
const registerIntentTask = CadenzaService.createMetaTask(
|
|
5276
|
+
"Record intent registration",
|
|
5277
|
+
(ctx) => {
|
|
5278
|
+
if (!ctx.__syncing) {
|
|
5279
|
+
return;
|
|
5280
|
+
}
|
|
5281
|
+
CadenzaService.debounce("meta.sync_controller.synced_resource", {
|
|
5282
|
+
delayMs: 3e3
|
|
5283
|
+
});
|
|
5284
|
+
const task = CadenzaService.get(ctx.__taskName);
|
|
5285
|
+
task.__registeredIntents = task.__registeredIntents ?? /* @__PURE__ */ new Set();
|
|
5286
|
+
task.__registeredIntents.add(ctx.__intent);
|
|
5287
|
+
}
|
|
5288
|
+
);
|
|
5289
|
+
this.registerIntentToTaskMapTask = CadenzaService.createMetaTask(
|
|
5290
|
+
"Split intents of task",
|
|
5291
|
+
function* (ctx) {
|
|
5292
|
+
const task = ctx.task;
|
|
5293
|
+
if (task.hidden || !task.register) return;
|
|
5294
|
+
task.__registeredIntents = task.__registeredIntents ?? /* @__PURE__ */ new Set();
|
|
5295
|
+
task.__invalidMetaIntentWarnings = task.__invalidMetaIntentWarnings ?? /* @__PURE__ */ new Set();
|
|
5296
|
+
for (const intent of task.handlesIntents) {
|
|
5297
|
+
if (task.__registeredIntents.has(intent)) continue;
|
|
5298
|
+
if (isMetaIntentName(intent) && !task.isMeta) {
|
|
5299
|
+
if (!task.__invalidMetaIntentWarnings.has(intent)) {
|
|
5300
|
+
task.__invalidMetaIntentWarnings.add(intent);
|
|
5301
|
+
CadenzaService.log(
|
|
5302
|
+
"Skipping intent-to-task registration: non-meta task cannot handle meta intent.",
|
|
5303
|
+
{
|
|
5304
|
+
intent,
|
|
5305
|
+
taskName: task.name,
|
|
5306
|
+
taskVersion: task.version
|
|
5307
|
+
},
|
|
5308
|
+
"warning"
|
|
5309
|
+
);
|
|
5310
|
+
}
|
|
5311
|
+
continue;
|
|
5312
|
+
}
|
|
5313
|
+
yield {
|
|
5314
|
+
data: {
|
|
5315
|
+
intentName: intent,
|
|
5316
|
+
taskName: task.name,
|
|
5317
|
+
taskVersion: task.version,
|
|
5318
|
+
serviceName: CadenzaService.serviceRegistry.serviceName
|
|
5319
|
+
},
|
|
5320
|
+
__taskName: task.name,
|
|
5321
|
+
__intent: intent
|
|
5322
|
+
};
|
|
5323
|
+
}
|
|
5324
|
+
}
|
|
5325
|
+
).then(
|
|
5326
|
+
(this.isCadenzaDBReady ? CadenzaService.createCadenzaDBInsertTask(
|
|
5327
|
+
"intent_to_task_map",
|
|
5328
|
+
{
|
|
5329
|
+
onConflict: {
|
|
5330
|
+
target: [
|
|
5331
|
+
"intent_name",
|
|
5332
|
+
"task_name",
|
|
5333
|
+
"task_version",
|
|
5334
|
+
"service_name"
|
|
5335
|
+
],
|
|
5336
|
+
action: {
|
|
5337
|
+
do: "nothing"
|
|
5338
|
+
}
|
|
5339
|
+
}
|
|
5340
|
+
},
|
|
5341
|
+
{ concurrency: 30 }
|
|
5342
|
+
) : CadenzaService.get("dbInsertIntentToTaskMap"))?.then(registerIntentTask)
|
|
5343
|
+
);
|
|
4470
5344
|
this.registerTaskMapTask = CadenzaService.createMetaTask(
|
|
4471
5345
|
"Register task map to DB",
|
|
4472
5346
|
function* (ctx) {
|
|
@@ -4589,6 +5463,7 @@ var GraphSyncController = class _GraphSyncController {
|
|
|
4589
5463
|
CadenzaService.registry.doForEachTask.clone().doOn("meta.sync_controller.synced_tasks").then(
|
|
4590
5464
|
this.registerTaskMapTask,
|
|
4591
5465
|
this.registerSignalToTaskMapTask,
|
|
5466
|
+
this.registerIntentToTaskMapTask,
|
|
4592
5467
|
this.registerDeputyRelationshipTask
|
|
4593
5468
|
);
|
|
4594
5469
|
CadenzaService.registry.getAllRoutines.clone().doOn("meta.sync_controller.synced_routines").then(this.splitTasksInRoutines);
|
|
@@ -4730,11 +5605,192 @@ var CadenzaService = class {
|
|
|
4730
5605
|
Cadenza.interval(signal, context, intervalMs, leading, startDateTime);
|
|
4731
5606
|
}
|
|
4732
5607
|
static defineIntent(intent) {
|
|
4733
|
-
this.inquiryBroker?.
|
|
5608
|
+
this.inquiryBroker?.addIntent(intent);
|
|
4734
5609
|
return intent;
|
|
4735
5610
|
}
|
|
4736
|
-
static
|
|
4737
|
-
return this.
|
|
5611
|
+
static getInquiryResponderDescriptor(task) {
|
|
5612
|
+
return this.serviceRegistry.getInquiryResponderDescriptor(task);
|
|
5613
|
+
}
|
|
5614
|
+
static compareInquiryResponders(left, right) {
|
|
5615
|
+
return compareResponderDescriptors(left.descriptor, right.descriptor);
|
|
5616
|
+
}
|
|
5617
|
+
static buildInquirySummary(inquiry, startedAt, statuses, totalResponders) {
|
|
5618
|
+
const counts = summarizeResponderStatuses(statuses);
|
|
5619
|
+
const isMetaInquiry = isMetaIntentName(inquiry);
|
|
5620
|
+
const eligibleResponders = statuses.length;
|
|
5621
|
+
return {
|
|
5622
|
+
inquiry,
|
|
5623
|
+
isMetaInquiry,
|
|
5624
|
+
totalResponders,
|
|
5625
|
+
eligibleResponders,
|
|
5626
|
+
filteredOutResponders: Math.max(0, totalResponders - eligibleResponders),
|
|
5627
|
+
responded: counts.responded,
|
|
5628
|
+
failed: counts.failed,
|
|
5629
|
+
timedOut: counts.timedOut,
|
|
5630
|
+
pending: counts.pending,
|
|
5631
|
+
durationMs: Date.now() - startedAt,
|
|
5632
|
+
responders: statuses
|
|
5633
|
+
};
|
|
5634
|
+
}
|
|
5635
|
+
static async inquire(inquiry, context, options = {}) {
|
|
5636
|
+
this.bootstrap();
|
|
5637
|
+
const observer = this.inquiryBroker?.inquiryObservers.get(inquiry);
|
|
5638
|
+
const allResponders = observer ? Array.from(observer.tasks).map((task) => ({
|
|
5639
|
+
task,
|
|
5640
|
+
descriptor: this.getInquiryResponderDescriptor(task)
|
|
5641
|
+
})) : [];
|
|
5642
|
+
const isMetaInquiry = isMetaIntentName(inquiry);
|
|
5643
|
+
const responders = allResponders.filter(({ task, descriptor }) => {
|
|
5644
|
+
const shouldExecute = shouldExecuteInquiryResponder(inquiry, task.isMeta);
|
|
5645
|
+
if (shouldExecute) {
|
|
5646
|
+
return true;
|
|
5647
|
+
}
|
|
5648
|
+
const warningKey = `${inquiry}|${descriptor.serviceName}|${descriptor.taskName}|${descriptor.taskVersion}|${descriptor.localTaskName}`;
|
|
5649
|
+
if (!this.warnedInvalidMetaIntentResponderKeys.has(warningKey)) {
|
|
5650
|
+
this.warnedInvalidMetaIntentResponderKeys.add(warningKey);
|
|
5651
|
+
this.log(
|
|
5652
|
+
"Skipping non-meta task for meta intent inquiry.",
|
|
5653
|
+
{
|
|
5654
|
+
inquiry,
|
|
5655
|
+
responder: descriptor
|
|
5656
|
+
},
|
|
5657
|
+
"warning",
|
|
5658
|
+
descriptor.serviceName
|
|
5659
|
+
);
|
|
5660
|
+
}
|
|
5661
|
+
return false;
|
|
5662
|
+
});
|
|
5663
|
+
if (responders.length === 0) {
|
|
5664
|
+
return {
|
|
5665
|
+
__inquiryMeta: {
|
|
5666
|
+
inquiry,
|
|
5667
|
+
isMetaInquiry,
|
|
5668
|
+
totalResponders: allResponders.length,
|
|
5669
|
+
eligibleResponders: 0,
|
|
5670
|
+
filteredOutResponders: allResponders.length,
|
|
5671
|
+
responded: 0,
|
|
5672
|
+
failed: 0,
|
|
5673
|
+
timedOut: 0,
|
|
5674
|
+
pending: 0,
|
|
5675
|
+
durationMs: 0,
|
|
5676
|
+
responders: []
|
|
5677
|
+
}
|
|
5678
|
+
};
|
|
5679
|
+
}
|
|
5680
|
+
responders.sort(this.compareInquiryResponders.bind(this));
|
|
5681
|
+
const overallTimeoutMs = options.overallTimeoutMs ?? options.timeout ?? 0;
|
|
5682
|
+
const requireComplete = options.requireComplete ?? false;
|
|
5683
|
+
const perResponderTimeoutMs = options.perResponderTimeoutMs;
|
|
5684
|
+
const startedAt = Date.now();
|
|
5685
|
+
const statuses = [];
|
|
5686
|
+
const statusByTask = /* @__PURE__ */ new Map();
|
|
5687
|
+
for (const responder of responders) {
|
|
5688
|
+
const status = {
|
|
5689
|
+
...responder.descriptor,
|
|
5690
|
+
status: "timed_out",
|
|
5691
|
+
durationMs: 0
|
|
5692
|
+
};
|
|
5693
|
+
statuses.push(status);
|
|
5694
|
+
statusByTask.set(responder.task, status);
|
|
5695
|
+
}
|
|
5696
|
+
const resultsByTask = /* @__PURE__ */ new Map();
|
|
5697
|
+
const resolverTasks = [];
|
|
5698
|
+
const pending = new Set(responders.map((r) => r.task));
|
|
5699
|
+
const startTimeByTask = /* @__PURE__ */ new Map();
|
|
5700
|
+
this.emit("meta.inquiry_broker.inquire", { inquiry, context });
|
|
5701
|
+
return new Promise((resolve, reject) => {
|
|
5702
|
+
let finalized = false;
|
|
5703
|
+
let timeoutId;
|
|
5704
|
+
const finalize = (timedOut) => {
|
|
5705
|
+
if (finalized) return;
|
|
5706
|
+
finalized = true;
|
|
5707
|
+
if (timeoutId) {
|
|
5708
|
+
clearTimeout(timeoutId);
|
|
5709
|
+
timeoutId = void 0;
|
|
5710
|
+
}
|
|
5711
|
+
for (const resolverTask of resolverTasks) {
|
|
5712
|
+
resolverTask.destroy();
|
|
5713
|
+
}
|
|
5714
|
+
if (timedOut && pending.size > 0) {
|
|
5715
|
+
for (const task of pending) {
|
|
5716
|
+
const status = statusByTask.get(task);
|
|
5717
|
+
if (!status) continue;
|
|
5718
|
+
status.status = "timed_out";
|
|
5719
|
+
status.durationMs = Date.now() - (startTimeByTask.get(task) ?? startedAt);
|
|
5720
|
+
}
|
|
5721
|
+
}
|
|
5722
|
+
const fulfilledContexts = responders.filter((responder) => resultsByTask.has(responder.task)).map((responder) => resultsByTask.get(responder.task));
|
|
5723
|
+
const mergedContext = mergeInquiryContexts(fulfilledContexts);
|
|
5724
|
+
const inquiryMeta = this.buildInquirySummary(
|
|
5725
|
+
inquiry,
|
|
5726
|
+
startedAt,
|
|
5727
|
+
statuses,
|
|
5728
|
+
allResponders.length
|
|
5729
|
+
);
|
|
5730
|
+
const responseContext = {
|
|
5731
|
+
...mergedContext,
|
|
5732
|
+
__inquiryMeta: inquiryMeta
|
|
5733
|
+
};
|
|
5734
|
+
if (requireComplete && (timedOut || inquiryMeta.failed > 0 || inquiryMeta.timedOut > 0 || inquiryMeta.pending > 0)) {
|
|
5735
|
+
reject({
|
|
5736
|
+
...responseContext,
|
|
5737
|
+
__error: `Inquiry '${inquiry}' did not complete successfully`,
|
|
5738
|
+
errored: true
|
|
5739
|
+
});
|
|
5740
|
+
return;
|
|
5741
|
+
}
|
|
5742
|
+
resolve(responseContext);
|
|
5743
|
+
};
|
|
5744
|
+
if (overallTimeoutMs > 0) {
|
|
5745
|
+
timeoutId = setTimeout(() => finalize(true), overallTimeoutMs);
|
|
5746
|
+
}
|
|
5747
|
+
for (const responder of responders) {
|
|
5748
|
+
const { task, descriptor } = responder;
|
|
5749
|
+
const inquiryId = uuid3();
|
|
5750
|
+
startTimeByTask.set(task, Date.now());
|
|
5751
|
+
const resolverTask = this.createEphemeralMetaTask(
|
|
5752
|
+
`Resolve inquiry ${inquiry} for ${descriptor.localTaskName}`,
|
|
5753
|
+
(resultCtx) => {
|
|
5754
|
+
if (finalized) {
|
|
5755
|
+
return;
|
|
5756
|
+
}
|
|
5757
|
+
pending.delete(task);
|
|
5758
|
+
const status = statusByTask.get(task);
|
|
5759
|
+
if (status) {
|
|
5760
|
+
status.durationMs = Date.now() - (startTimeByTask.get(task) ?? startedAt);
|
|
5761
|
+
if (resultCtx?.errored || resultCtx?.failed) {
|
|
5762
|
+
status.status = "failed";
|
|
5763
|
+
status.error = String(
|
|
5764
|
+
resultCtx?.__error ?? resultCtx?.error ?? "Inquiry responder failed"
|
|
5765
|
+
);
|
|
5766
|
+
} else {
|
|
5767
|
+
status.status = "fulfilled";
|
|
5768
|
+
resultsByTask.set(task, resultCtx);
|
|
5769
|
+
}
|
|
5770
|
+
}
|
|
5771
|
+
if (pending.size === 0) {
|
|
5772
|
+
finalize(false);
|
|
5773
|
+
}
|
|
5774
|
+
},
|
|
5775
|
+
"Resolves distributed inquiry responder result",
|
|
5776
|
+
{ register: false }
|
|
5777
|
+
).doOn(`meta.node.graph_completed:${inquiryId}`);
|
|
5778
|
+
resolverTasks.push(resolverTask);
|
|
5779
|
+
const executionContext = {
|
|
5780
|
+
...context,
|
|
5781
|
+
__routineExecId: inquiryId,
|
|
5782
|
+
__isInquiry: true
|
|
5783
|
+
};
|
|
5784
|
+
if (perResponderTimeoutMs !== void 0) {
|
|
5785
|
+
executionContext.__timeout = perResponderTimeoutMs;
|
|
5786
|
+
}
|
|
5787
|
+
if (task.isMeta) {
|
|
5788
|
+
this.metaRunner?.run(task, executionContext);
|
|
5789
|
+
} else {
|
|
5790
|
+
this.runner?.run(task, executionContext);
|
|
5791
|
+
}
|
|
5792
|
+
}
|
|
5793
|
+
});
|
|
4738
5794
|
}
|
|
4739
5795
|
/**
|
|
4740
5796
|
* Executes the given task or graph routine within the provided context using the configured runner.
|
|
@@ -5771,6 +6827,7 @@ var CadenzaService = class {
|
|
|
5771
6827
|
};
|
|
5772
6828
|
CadenzaService.isBootstrapped = false;
|
|
5773
6829
|
CadenzaService.serviceCreated = false;
|
|
6830
|
+
CadenzaService.warnedInvalidMetaIntentResponderKeys = /* @__PURE__ */ new Set();
|
|
5774
6831
|
|
|
5775
6832
|
// src/index.ts
|
|
5776
6833
|
import {
|