@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.js
CHANGED
|
@@ -295,7 +295,74 @@ var DatabaseTask = class extends DeputyTask {
|
|
|
295
295
|
var isNode = typeof process !== "undefined" && process.versions?.node != null;
|
|
296
296
|
var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
297
297
|
|
|
298
|
+
// src/utils/inquiry.ts
|
|
299
|
+
var META_INTENT_PREFIX = "meta-";
|
|
300
|
+
var META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT = "meta-runtime-transport-diagnostics";
|
|
301
|
+
function isPlainObject(value) {
|
|
302
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
303
|
+
}
|
|
304
|
+
function deepMergeDeterministic(left, right) {
|
|
305
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
306
|
+
return [...left, ...right];
|
|
307
|
+
}
|
|
308
|
+
if (isPlainObject(left) && isPlainObject(right)) {
|
|
309
|
+
const merged = { ...left };
|
|
310
|
+
const keys = Array.from(/* @__PURE__ */ new Set([...Object.keys(left), ...Object.keys(right)])).sort();
|
|
311
|
+
for (const key of keys) {
|
|
312
|
+
if (!(key in left)) {
|
|
313
|
+
merged[key] = right[key];
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
if (!(key in right)) {
|
|
317
|
+
merged[key] = left[key];
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
merged[key] = deepMergeDeterministic(left[key], right[key]);
|
|
321
|
+
}
|
|
322
|
+
return merged;
|
|
323
|
+
}
|
|
324
|
+
return right;
|
|
325
|
+
}
|
|
326
|
+
function mergeInquiryContexts(contexts) {
|
|
327
|
+
return contexts.reduce((acc, next) => deepMergeDeterministic(acc, next), {});
|
|
328
|
+
}
|
|
329
|
+
function isMetaIntentName(intentName) {
|
|
330
|
+
return intentName.startsWith(META_INTENT_PREFIX);
|
|
331
|
+
}
|
|
332
|
+
function shouldExecuteInquiryResponder(inquiry, responderIsMeta) {
|
|
333
|
+
if (!isMetaIntentName(inquiry)) {
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
return responderIsMeta;
|
|
337
|
+
}
|
|
338
|
+
function compareResponderDescriptors(left, right) {
|
|
339
|
+
if (left.serviceName !== right.serviceName) {
|
|
340
|
+
return left.serviceName.localeCompare(right.serviceName);
|
|
341
|
+
}
|
|
342
|
+
if (left.taskName !== right.taskName) {
|
|
343
|
+
return left.taskName.localeCompare(right.taskName);
|
|
344
|
+
}
|
|
345
|
+
if (left.taskVersion !== right.taskVersion) {
|
|
346
|
+
return left.taskVersion - right.taskVersion;
|
|
347
|
+
}
|
|
348
|
+
return left.localTaskName.localeCompare(right.localTaskName);
|
|
349
|
+
}
|
|
350
|
+
function summarizeResponderStatuses(statuses) {
|
|
351
|
+
let responded = 0;
|
|
352
|
+
let failed = 0;
|
|
353
|
+
let timedOut = 0;
|
|
354
|
+
let pending = 0;
|
|
355
|
+
for (const status of statuses) {
|
|
356
|
+
if (status.status === "fulfilled") responded++;
|
|
357
|
+
if (status.status === "failed") failed++;
|
|
358
|
+
if (status.status === "timed_out") timedOut++;
|
|
359
|
+
}
|
|
360
|
+
pending = Math.max(0, statuses.length - responded - failed - timedOut);
|
|
361
|
+
return { responded, failed, timedOut, pending };
|
|
362
|
+
}
|
|
363
|
+
|
|
298
364
|
// src/registry/ServiceRegistry.ts
|
|
365
|
+
var META_SERVICE_REGISTRY_FULL_SYNC_INTENT = "meta-service-registry-full-sync";
|
|
299
366
|
var ServiceRegistry = class _ServiceRegistry {
|
|
300
367
|
/**
|
|
301
368
|
* Initializes a private constructor for managing service instances, remote signals,
|
|
@@ -310,11 +377,47 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
310
377
|
this.instances = /* @__PURE__ */ new Map();
|
|
311
378
|
this.deputies = /* @__PURE__ */ new Map();
|
|
312
379
|
this.remoteSignals = /* @__PURE__ */ new Map();
|
|
380
|
+
this.remoteIntents = /* @__PURE__ */ new Map();
|
|
381
|
+
this.remoteIntentDeputiesByKey = /* @__PURE__ */ new Map();
|
|
382
|
+
this.remoteIntentDeputiesByTask = /* @__PURE__ */ new Map();
|
|
313
383
|
this.serviceName = null;
|
|
314
384
|
this.serviceInstanceId = null;
|
|
315
385
|
this.numberOfRunningGraphs = 0;
|
|
316
386
|
this.useSocket = false;
|
|
317
387
|
this.retryCount = 3;
|
|
388
|
+
CadenzaService.defineIntent({
|
|
389
|
+
name: META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT,
|
|
390
|
+
description: "Gather transport diagnostics across all services and communication clients.",
|
|
391
|
+
input: {
|
|
392
|
+
type: "object",
|
|
393
|
+
properties: {
|
|
394
|
+
detailLevel: {
|
|
395
|
+
type: "string",
|
|
396
|
+
constraints: {
|
|
397
|
+
oneOf: ["summary", "full"]
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
includeErrorHistory: {
|
|
401
|
+
type: "boolean"
|
|
402
|
+
},
|
|
403
|
+
errorHistoryLimit: {
|
|
404
|
+
type: "number",
|
|
405
|
+
constraints: {
|
|
406
|
+
min: 1,
|
|
407
|
+
max: 200
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
},
|
|
412
|
+
output: {
|
|
413
|
+
type: "object",
|
|
414
|
+
properties: {
|
|
415
|
+
transportDiagnostics: {
|
|
416
|
+
type: "object"
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
});
|
|
318
421
|
this.handleInstanceUpdateTask = CadenzaService.createMetaTask(
|
|
319
422
|
"Handle Instance Update",
|
|
320
423
|
(ctx, emit) => {
|
|
@@ -354,7 +457,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
354
457
|
if (this.serviceName === serviceName) {
|
|
355
458
|
return false;
|
|
356
459
|
}
|
|
357
|
-
if (!isFrontend && this.deputies.has(serviceName) || this.remoteSignals.has(serviceName)) {
|
|
460
|
+
if (!isFrontend && (this.deputies.has(serviceName) || this.remoteIntents.has(serviceName)) || this.remoteSignals.has(serviceName)) {
|
|
358
461
|
const clientCreated = instances?.some(
|
|
359
462
|
(i) => i.address === address && i.port === port && i.clientCreated && i.isActive
|
|
360
463
|
);
|
|
@@ -404,7 +507,10 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
404
507
|
for (const serviceInstance of ctx.serviceInstances) {
|
|
405
508
|
yield { serviceInstance };
|
|
406
509
|
}
|
|
407
|
-
}).doOn(
|
|
510
|
+
}).doOn(
|
|
511
|
+
"meta.service_registry.registered_global_signals",
|
|
512
|
+
"meta.service_registry.registered_global_intents"
|
|
513
|
+
).then(this.handleInstanceUpdateTask);
|
|
408
514
|
this.handleGlobalSignalRegistrationTask = CadenzaService.createMetaTask(
|
|
409
515
|
"Handle global Signal Registration",
|
|
410
516
|
(ctx) => {
|
|
@@ -445,6 +551,32 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
445
551
|
},
|
|
446
552
|
"Handles registration of remote signals"
|
|
447
553
|
).emits("meta.service_registry.registered_global_signals").doOn("global.meta.cadenza_db.gathered_sync_data");
|
|
554
|
+
this.handleGlobalIntentRegistrationTask = CadenzaService.createMetaTask(
|
|
555
|
+
"Handle global intent registration",
|
|
556
|
+
(ctx) => {
|
|
557
|
+
const intentToTaskMaps = this.normalizeIntentMaps(ctx);
|
|
558
|
+
const sorted = intentToTaskMaps.sort((a, b) => {
|
|
559
|
+
if (a.deleted && !b.deleted) return -1;
|
|
560
|
+
if (!a.deleted && b.deleted) return 1;
|
|
561
|
+
return 0;
|
|
562
|
+
});
|
|
563
|
+
for (const map of sorted) {
|
|
564
|
+
if (map.deleted) {
|
|
565
|
+
this.unregisterRemoteIntentDeputy(map);
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
CadenzaService.inquiryBroker.addIntent({
|
|
569
|
+
name: map.intentName
|
|
570
|
+
});
|
|
571
|
+
this.registerRemoteIntentDeputy(map);
|
|
572
|
+
}
|
|
573
|
+
return true;
|
|
574
|
+
},
|
|
575
|
+
"Handles registration of remote inquiry intent responders"
|
|
576
|
+
).emits("meta.service_registry.registered_global_intents").doOn(
|
|
577
|
+
"global.meta.cadenza_db.gathered_sync_data",
|
|
578
|
+
"global.meta.graph_metadata.task_intent_associated"
|
|
579
|
+
);
|
|
448
580
|
this.handleServiceNotRespondingTask = CadenzaService.createMetaTask(
|
|
449
581
|
"Handle service not responding",
|
|
450
582
|
(ctx, emit) => {
|
|
@@ -549,45 +681,58 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
549
681
|
},
|
|
550
682
|
"Handles status update from socket broadcast"
|
|
551
683
|
).doOn("meta.socket_client.status_received");
|
|
552
|
-
|
|
553
|
-
"
|
|
554
|
-
(ctx) => {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
684
|
+
this.fullSyncTask = CadenzaService.createMetaTask(
|
|
685
|
+
"Full sync",
|
|
686
|
+
async (ctx) => {
|
|
687
|
+
const inquiryResult = await CadenzaService.inquire(
|
|
688
|
+
META_SERVICE_REGISTRY_FULL_SYNC_INTENT,
|
|
689
|
+
{
|
|
690
|
+
syncScope: "service-registry-full-sync"
|
|
691
|
+
},
|
|
692
|
+
ctx.inquiryOptions ?? ctx.__inquiryOptions ?? {}
|
|
693
|
+
);
|
|
694
|
+
const signalToTaskMaps = (inquiryResult.signalToTaskMaps ?? []).filter((m) => !!m.isGlobal).map((m) => ({
|
|
695
|
+
signalName: m.signalName,
|
|
696
|
+
serviceName: m.serviceName,
|
|
697
|
+
deleted: !!m.deleted
|
|
698
|
+
}));
|
|
699
|
+
const intentToTaskMaps = (inquiryResult.intentToTaskMaps ?? []).map(
|
|
700
|
+
(m) => ({
|
|
701
|
+
intentName: m.intentName,
|
|
702
|
+
taskName: m.taskName,
|
|
703
|
+
taskVersion: m.taskVersion ?? 1,
|
|
704
|
+
serviceName: m.serviceName,
|
|
705
|
+
deleted: !!m.deleted
|
|
706
|
+
})
|
|
707
|
+
);
|
|
708
|
+
const serviceInstances = (inquiryResult.serviceInstances ?? []).filter(
|
|
709
|
+
(instance) => !instance.deleted && !!instance.isActive && !instance.isNonResponsive && !instance.isBlocked
|
|
710
|
+
).map((instance) => ({
|
|
711
|
+
uuid: instance.uuid,
|
|
712
|
+
address: instance.address,
|
|
713
|
+
port: instance.port,
|
|
714
|
+
serviceName: instance.serviceName,
|
|
715
|
+
isActive: !!instance.isActive,
|
|
716
|
+
isNonResponsive: !!instance.isNonResponsive,
|
|
717
|
+
isBlocked: !!instance.isBlocked,
|
|
718
|
+
health: instance.health ?? {},
|
|
719
|
+
exposed: !!instance.exposed,
|
|
720
|
+
created: instance.created,
|
|
721
|
+
isFrontend: !!instance.isFrontend
|
|
722
|
+
}));
|
|
723
|
+
return {
|
|
724
|
+
...ctx,
|
|
725
|
+
signalToTaskMaps,
|
|
726
|
+
intentToTaskMaps,
|
|
727
|
+
serviceInstances,
|
|
728
|
+
__inquiryMeta: inquiryResult.__inquiryMeta
|
|
729
|
+
};
|
|
730
|
+
},
|
|
731
|
+
"Runs service registry full sync through one distributed inquiry intent."
|
|
732
|
+
).doOn("meta.sync_requested").emits("meta.service_registry.initial_sync_complete").then(
|
|
733
|
+
this.handleGlobalSignalRegistrationTask,
|
|
734
|
+
this.handleGlobalIntentRegistrationTask
|
|
735
|
+
);
|
|
591
736
|
this.getInstanceById = CadenzaService.createMetaTask(
|
|
592
737
|
"Get instance by id",
|
|
593
738
|
(context) => {
|
|
@@ -756,6 +901,25 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
756
901
|
__active: self?.isActive ?? false
|
|
757
902
|
};
|
|
758
903
|
}).doOn("meta.socket.status_check_requested");
|
|
904
|
+
this.collectTransportDiagnosticsTask = CadenzaService.createMetaTask(
|
|
905
|
+
"Collect transport diagnostics",
|
|
906
|
+
async (ctx) => {
|
|
907
|
+
const inquiryResult = await CadenzaService.inquire(
|
|
908
|
+
META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT,
|
|
909
|
+
{
|
|
910
|
+
detailLevel: ctx.detailLevel,
|
|
911
|
+
includeErrorHistory: ctx.includeErrorHistory,
|
|
912
|
+
errorHistoryLimit: ctx.errorHistoryLimit
|
|
913
|
+
},
|
|
914
|
+
ctx.inquiryOptions ?? ctx.__inquiryOptions ?? {}
|
|
915
|
+
);
|
|
916
|
+
return {
|
|
917
|
+
...ctx,
|
|
918
|
+
...inquiryResult
|
|
919
|
+
};
|
|
920
|
+
},
|
|
921
|
+
"Collects distributed transport diagnostics using inquiry responders."
|
|
922
|
+
).doOn("meta.service_registry.transport_diagnostics_requested").emits("meta.service_registry.transport_diagnostics_collected").emitsOnFail("meta.service_registry.transport_diagnostics_failed");
|
|
759
923
|
this.insertServiceTask = CadenzaService.createCadenzaDBInsertTask(
|
|
760
924
|
"service",
|
|
761
925
|
{
|
|
@@ -964,8 +1128,125 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
964
1128
|
if (!this._instance) this._instance = new _ServiceRegistry();
|
|
965
1129
|
return this._instance;
|
|
966
1130
|
}
|
|
1131
|
+
buildRemoteIntentDeputyKey(map) {
|
|
1132
|
+
return `${map.intentName}|${map.serviceName}|${map.taskName}|${map.taskVersion ?? 1}`;
|
|
1133
|
+
}
|
|
1134
|
+
normalizeIntentMaps(ctx) {
|
|
1135
|
+
if (Array.isArray(ctx.intentToTaskMaps)) {
|
|
1136
|
+
return ctx.intentToTaskMaps.map((m) => ({
|
|
1137
|
+
intentName: m.intentName ?? m.intent_name,
|
|
1138
|
+
serviceName: m.serviceName ?? m.service_name,
|
|
1139
|
+
taskName: m.taskName ?? m.task_name,
|
|
1140
|
+
taskVersion: m.taskVersion ?? m.task_version ?? 1,
|
|
1141
|
+
deleted: !!m.deleted
|
|
1142
|
+
})).filter((m) => m.intentName && m.serviceName && m.taskName);
|
|
1143
|
+
}
|
|
1144
|
+
const single = ctx.intentToTaskMap ?? ctx.data ?? (ctx.intentName ? ctx : void 0);
|
|
1145
|
+
if (!single) return [];
|
|
1146
|
+
const normalized = {
|
|
1147
|
+
intentName: single.intentName ?? single.intent_name,
|
|
1148
|
+
serviceName: single.serviceName ?? single.service_name,
|
|
1149
|
+
taskName: single.taskName ?? single.task_name,
|
|
1150
|
+
taskVersion: single.taskVersion ?? single.task_version ?? 1,
|
|
1151
|
+
deleted: !!single.deleted
|
|
1152
|
+
};
|
|
1153
|
+
if (!normalized.intentName || !normalized.serviceName || !normalized.taskName)
|
|
1154
|
+
return [];
|
|
1155
|
+
return [normalized];
|
|
1156
|
+
}
|
|
1157
|
+
registerRemoteIntentDeputy(map) {
|
|
1158
|
+
if (!this.serviceName || map.serviceName === this.serviceName) {
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
const key = this.buildRemoteIntentDeputyKey(map);
|
|
1162
|
+
if (this.remoteIntentDeputiesByKey.has(key)) {
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
const deputyTaskName = `Inquire ${map.intentName} via ${map.serviceName} (${map.taskName} v${map.taskVersion})`;
|
|
1166
|
+
const deputyTask = isMetaIntentName(map.intentName) ? CadenzaService.createMetaDeputyTask(map.taskName, map.serviceName, {
|
|
1167
|
+
register: false,
|
|
1168
|
+
isHidden: true,
|
|
1169
|
+
retryCount: 1,
|
|
1170
|
+
retryDelay: 50,
|
|
1171
|
+
retryDelayFactor: 1.2
|
|
1172
|
+
}) : CadenzaService.createDeputyTask(map.taskName, map.serviceName, {
|
|
1173
|
+
register: false,
|
|
1174
|
+
isHidden: true,
|
|
1175
|
+
retryCount: 1,
|
|
1176
|
+
retryDelay: 50,
|
|
1177
|
+
retryDelayFactor: 1.2
|
|
1178
|
+
});
|
|
1179
|
+
deputyTask.respondsTo(map.intentName);
|
|
1180
|
+
if (!this.remoteIntents.has(map.serviceName)) {
|
|
1181
|
+
this.remoteIntents.set(map.serviceName, /* @__PURE__ */ new Set());
|
|
1182
|
+
}
|
|
1183
|
+
this.remoteIntents.get(map.serviceName).add(map.intentName);
|
|
1184
|
+
const descriptor = {
|
|
1185
|
+
key,
|
|
1186
|
+
intentName: map.intentName,
|
|
1187
|
+
serviceName: map.serviceName,
|
|
1188
|
+
remoteTaskName: map.taskName,
|
|
1189
|
+
remoteTaskVersion: map.taskVersion,
|
|
1190
|
+
localTaskName: deputyTask.name || deputyTaskName,
|
|
1191
|
+
localTask: deputyTask
|
|
1192
|
+
};
|
|
1193
|
+
this.remoteIntentDeputiesByKey.set(key, descriptor);
|
|
1194
|
+
this.remoteIntentDeputiesByTask.set(deputyTask, descriptor);
|
|
1195
|
+
}
|
|
1196
|
+
unregisterRemoteIntentDeputy(map) {
|
|
1197
|
+
const key = this.buildRemoteIntentDeputyKey(map);
|
|
1198
|
+
const descriptor = this.remoteIntentDeputiesByKey.get(key);
|
|
1199
|
+
if (!descriptor) {
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
const task = descriptor.localTask;
|
|
1203
|
+
if (task) {
|
|
1204
|
+
CadenzaService.inquiryBroker.unsubscribe(descriptor.intentName, task);
|
|
1205
|
+
task.destroy();
|
|
1206
|
+
}
|
|
1207
|
+
this.remoteIntentDeputiesByTask.delete(descriptor.localTask);
|
|
1208
|
+
this.remoteIntentDeputiesByKey.delete(key);
|
|
1209
|
+
this.remoteIntents.get(descriptor.serviceName)?.delete(descriptor.intentName);
|
|
1210
|
+
if (!this.remoteIntents.get(descriptor.serviceName)?.size) {
|
|
1211
|
+
this.remoteIntents.delete(descriptor.serviceName);
|
|
1212
|
+
}
|
|
1213
|
+
const deputies = this.deputies.get(descriptor.serviceName);
|
|
1214
|
+
if (deputies) {
|
|
1215
|
+
this.deputies.set(
|
|
1216
|
+
descriptor.serviceName,
|
|
1217
|
+
deputies.filter((d) => d.localTaskName !== descriptor.localTaskName)
|
|
1218
|
+
);
|
|
1219
|
+
if (this.deputies.get(descriptor.serviceName)?.length === 0) {
|
|
1220
|
+
this.deputies.delete(descriptor.serviceName);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
getInquiryResponderDescriptor(task) {
|
|
1225
|
+
const remote = this.remoteIntentDeputiesByTask.get(task);
|
|
1226
|
+
if (remote) {
|
|
1227
|
+
return {
|
|
1228
|
+
isRemote: true,
|
|
1229
|
+
serviceName: remote.serviceName,
|
|
1230
|
+
taskName: remote.remoteTaskName,
|
|
1231
|
+
taskVersion: remote.remoteTaskVersion,
|
|
1232
|
+
localTaskName: remote.localTaskName
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
return {
|
|
1236
|
+
isRemote: false,
|
|
1237
|
+
serviceName: this.serviceName ?? "UnknownService",
|
|
1238
|
+
taskName: task.name,
|
|
1239
|
+
taskVersion: task.version,
|
|
1240
|
+
localTaskName: task.name
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
967
1243
|
reset() {
|
|
968
1244
|
this.instances.clear();
|
|
1245
|
+
this.deputies.clear();
|
|
1246
|
+
this.remoteSignals.clear();
|
|
1247
|
+
this.remoteIntents.clear();
|
|
1248
|
+
this.remoteIntentDeputiesByKey.clear();
|
|
1249
|
+
this.remoteIntentDeputiesByTask.clear();
|
|
969
1250
|
}
|
|
970
1251
|
};
|
|
971
1252
|
|
|
@@ -1082,6 +1363,8 @@ var RestController = class _RestController {
|
|
|
1082
1363
|
* It initializes and configures the REST server tasks.
|
|
1083
1364
|
*/
|
|
1084
1365
|
constructor() {
|
|
1366
|
+
this.fetchClientDiagnostics = /* @__PURE__ */ new Map();
|
|
1367
|
+
this.diagnosticsErrorHistoryLimit = 100;
|
|
1085
1368
|
/**
|
|
1086
1369
|
* Fetches data from the given URL with a specified timeout. This function performs
|
|
1087
1370
|
* a fetch request with the ability to cancel the request if it exceeds the provided timeout duration.
|
|
@@ -1122,6 +1405,11 @@ var RestController = class _RestController {
|
|
|
1122
1405
|
"meta.rest.delegation_requested",
|
|
1123
1406
|
"meta.socket.delegation_requested"
|
|
1124
1407
|
);
|
|
1408
|
+
CadenzaService.createMetaTask(
|
|
1409
|
+
"Collect fetch transport diagnostics",
|
|
1410
|
+
(ctx) => this.collectFetchTransportDiagnostics(ctx),
|
|
1411
|
+
"Responds to distributed transport diagnostics inquiries with REST/fetch client data."
|
|
1412
|
+
).respondsTo(META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT);
|
|
1125
1413
|
CadenzaService.createMetaRoutine(
|
|
1126
1414
|
"RestServer",
|
|
1127
1415
|
[
|
|
@@ -1452,6 +1740,13 @@ var RestController = class _RestController {
|
|
|
1452
1740
|
const port = protocol === "https" ? 443 : servicePort;
|
|
1453
1741
|
const URL = `${protocol}://${serviceAddress}:${port}`;
|
|
1454
1742
|
const fetchId = `${serviceAddress}_${port}`;
|
|
1743
|
+
const fetchDiagnostics = this.ensureFetchClientDiagnostics(
|
|
1744
|
+
fetchId,
|
|
1745
|
+
serviceName,
|
|
1746
|
+
URL
|
|
1747
|
+
);
|
|
1748
|
+
fetchDiagnostics.destroyed = false;
|
|
1749
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1455
1750
|
if (CadenzaService.get(`Send Handshake to ${URL}`)) {
|
|
1456
1751
|
console.error("Fetch client already exists", URL);
|
|
1457
1752
|
return;
|
|
@@ -1473,6 +1768,10 @@ var RestController = class _RestController {
|
|
|
1473
1768
|
);
|
|
1474
1769
|
if (response.__status !== "success") {
|
|
1475
1770
|
const error = response.__error ?? `Failed to connect to service ${serviceName} ${ctx2.serviceInstanceId}`;
|
|
1771
|
+
fetchDiagnostics.connected = false;
|
|
1772
|
+
fetchDiagnostics.lastHandshakeError = error;
|
|
1773
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1774
|
+
this.recordFetchClientError(fetchId, serviceName, URL, error);
|
|
1476
1775
|
CadenzaService.log(
|
|
1477
1776
|
"Fetch handshake failed.",
|
|
1478
1777
|
{ error, serviceName, URL },
|
|
@@ -1482,6 +1781,11 @@ var RestController = class _RestController {
|
|
|
1482
1781
|
return { ...ctx2, __error: error, errored: true };
|
|
1483
1782
|
}
|
|
1484
1783
|
ctx2.serviceInstanceId = response.__serviceInstanceId;
|
|
1784
|
+
fetchDiagnostics.connected = true;
|
|
1785
|
+
fetchDiagnostics.destroyed = false;
|
|
1786
|
+
fetchDiagnostics.lastHandshakeAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1787
|
+
fetchDiagnostics.lastHandshakeError = null;
|
|
1788
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1485
1789
|
CadenzaService.log("Fetch client connected.", {
|
|
1486
1790
|
response,
|
|
1487
1791
|
serviceName,
|
|
@@ -1497,6 +1801,10 @@ var RestController = class _RestController {
|
|
|
1497
1801
|
});
|
|
1498
1802
|
}
|
|
1499
1803
|
} catch (e) {
|
|
1804
|
+
fetchDiagnostics.connected = false;
|
|
1805
|
+
fetchDiagnostics.lastHandshakeError = this.getErrorMessage(e);
|
|
1806
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1807
|
+
this.recordFetchClientError(fetchId, serviceName, URL, e);
|
|
1500
1808
|
CadenzaService.log(
|
|
1501
1809
|
"Error in fetch handshake",
|
|
1502
1810
|
{ error: e, serviceName, URL, ctx: ctx2 },
|
|
@@ -1518,6 +1826,8 @@ var RestController = class _RestController {
|
|
|
1518
1826
|
if (ctx2.__remoteRoutineName === void 0) {
|
|
1519
1827
|
return;
|
|
1520
1828
|
}
|
|
1829
|
+
fetchDiagnostics.delegationRequests++;
|
|
1830
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1521
1831
|
let resultContext;
|
|
1522
1832
|
try {
|
|
1523
1833
|
resultContext = await this.fetchDataWithTimeout(
|
|
@@ -1531,8 +1841,21 @@ var RestController = class _RestController {
|
|
|
1531
1841
|
},
|
|
1532
1842
|
3e4
|
|
1533
1843
|
);
|
|
1844
|
+
if (resultContext?.errored || resultContext?.failed) {
|
|
1845
|
+
fetchDiagnostics.delegationFailures++;
|
|
1846
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1847
|
+
this.recordFetchClientError(
|
|
1848
|
+
fetchId,
|
|
1849
|
+
serviceName,
|
|
1850
|
+
URL,
|
|
1851
|
+
resultContext?.__error ?? resultContext?.error ?? "Delegation failed"
|
|
1852
|
+
);
|
|
1853
|
+
}
|
|
1534
1854
|
} catch (e) {
|
|
1535
1855
|
console.error("Error in delegation", e);
|
|
1856
|
+
fetchDiagnostics.delegationFailures++;
|
|
1857
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1858
|
+
this.recordFetchClientError(fetchId, serviceName, URL, e);
|
|
1536
1859
|
resultContext = {
|
|
1537
1860
|
__error: `Error: ${e}`,
|
|
1538
1861
|
errored: true,
|
|
@@ -1558,6 +1881,8 @@ var RestController = class _RestController {
|
|
|
1558
1881
|
if (ctx2.__signalName === void 0) {
|
|
1559
1882
|
return;
|
|
1560
1883
|
}
|
|
1884
|
+
fetchDiagnostics.signalTransmissions++;
|
|
1885
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1561
1886
|
let response;
|
|
1562
1887
|
try {
|
|
1563
1888
|
response = await this.fetchDataWithTimeout(
|
|
@@ -1574,8 +1899,21 @@ var RestController = class _RestController {
|
|
|
1574
1899
|
if (ctx2.__routineExecId) {
|
|
1575
1900
|
emit(`meta.fetch.transmitted:${ctx2.__routineExecId}`, response);
|
|
1576
1901
|
}
|
|
1902
|
+
if (response?.errored || response?.failed) {
|
|
1903
|
+
fetchDiagnostics.signalFailures++;
|
|
1904
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1905
|
+
this.recordFetchClientError(
|
|
1906
|
+
fetchId,
|
|
1907
|
+
serviceName,
|
|
1908
|
+
URL,
|
|
1909
|
+
response?.__error ?? response?.error ?? "Signal transmission failed"
|
|
1910
|
+
);
|
|
1911
|
+
}
|
|
1577
1912
|
} catch (e) {
|
|
1578
1913
|
console.error("Error in transmission", e);
|
|
1914
|
+
fetchDiagnostics.signalFailures++;
|
|
1915
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1916
|
+
this.recordFetchClientError(fetchId, serviceName, URL, e);
|
|
1579
1917
|
response = {
|
|
1580
1918
|
__error: `Error: ${e}`,
|
|
1581
1919
|
errored: true,
|
|
@@ -1593,6 +1931,8 @@ var RestController = class _RestController {
|
|
|
1593
1931
|
const statusTask = CadenzaService.createMetaTask(
|
|
1594
1932
|
`Request status from ${URL}`,
|
|
1595
1933
|
async (ctx2) => {
|
|
1934
|
+
fetchDiagnostics.statusChecks++;
|
|
1935
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1596
1936
|
let status;
|
|
1597
1937
|
try {
|
|
1598
1938
|
status = await this.fetchDataWithTimeout(
|
|
@@ -1602,7 +1942,20 @@ var RestController = class _RestController {
|
|
|
1602
1942
|
},
|
|
1603
1943
|
1e3
|
|
1604
1944
|
);
|
|
1945
|
+
if (status?.errored || status?.failed) {
|
|
1946
|
+
fetchDiagnostics.statusFailures++;
|
|
1947
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1948
|
+
this.recordFetchClientError(
|
|
1949
|
+
fetchId,
|
|
1950
|
+
serviceName,
|
|
1951
|
+
URL,
|
|
1952
|
+
status?.__error ?? status?.error ?? "Status check failed"
|
|
1953
|
+
);
|
|
1954
|
+
}
|
|
1605
1955
|
} catch (e) {
|
|
1956
|
+
fetchDiagnostics.statusFailures++;
|
|
1957
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1958
|
+
this.recordFetchClientError(fetchId, serviceName, URL, e);
|
|
1606
1959
|
status = {
|
|
1607
1960
|
__error: `Error: ${e}`,
|
|
1608
1961
|
errored: true,
|
|
@@ -1614,6 +1967,9 @@ var RestController = class _RestController {
|
|
|
1614
1967
|
"Requests status"
|
|
1615
1968
|
).doOn("meta.fetch.status_check_requested").emits("meta.fetch.status_checked").emitsOnFail("meta.fetch.status_check_failed");
|
|
1616
1969
|
CadenzaService.createEphemeralMetaTask("Destroy fetch client", () => {
|
|
1970
|
+
fetchDiagnostics.connected = false;
|
|
1971
|
+
fetchDiagnostics.destroyed = true;
|
|
1972
|
+
fetchDiagnostics.updatedAt = Date.now();
|
|
1617
1973
|
CadenzaService.log("Destroying fetch client", { URL, serviceName });
|
|
1618
1974
|
handshakeTask.destroy();
|
|
1619
1975
|
delegateTask.destroy();
|
|
@@ -1662,6 +2018,144 @@ var RestController = class _RestController {
|
|
|
1662
2018
|
if (!this._instance) this._instance = new _RestController();
|
|
1663
2019
|
return this._instance;
|
|
1664
2020
|
}
|
|
2021
|
+
resolveTransportDiagnosticsOptions(ctx) {
|
|
2022
|
+
const detailLevel = ctx.detailLevel === "full" ? "full" : "summary";
|
|
2023
|
+
const includeErrorHistory = Boolean(ctx.includeErrorHistory);
|
|
2024
|
+
const requestedLimit = Number(ctx.errorHistoryLimit);
|
|
2025
|
+
const errorHistoryLimit = Number.isFinite(requestedLimit) ? Math.max(1, Math.min(200, Math.trunc(requestedLimit))) : 10;
|
|
2026
|
+
return {
|
|
2027
|
+
detailLevel,
|
|
2028
|
+
includeErrorHistory,
|
|
2029
|
+
errorHistoryLimit
|
|
2030
|
+
};
|
|
2031
|
+
}
|
|
2032
|
+
ensureFetchClientDiagnostics(fetchId, serviceName, url) {
|
|
2033
|
+
let state = this.fetchClientDiagnostics.get(fetchId);
|
|
2034
|
+
if (!state) {
|
|
2035
|
+
state = {
|
|
2036
|
+
fetchId,
|
|
2037
|
+
serviceName,
|
|
2038
|
+
url,
|
|
2039
|
+
connected: false,
|
|
2040
|
+
destroyed: false,
|
|
2041
|
+
lastHandshakeAt: null,
|
|
2042
|
+
lastHandshakeError: null,
|
|
2043
|
+
lastError: null,
|
|
2044
|
+
lastErrorAt: 0,
|
|
2045
|
+
errorHistory: [],
|
|
2046
|
+
delegationRequests: 0,
|
|
2047
|
+
delegationFailures: 0,
|
|
2048
|
+
signalTransmissions: 0,
|
|
2049
|
+
signalFailures: 0,
|
|
2050
|
+
statusChecks: 0,
|
|
2051
|
+
statusFailures: 0,
|
|
2052
|
+
updatedAt: Date.now()
|
|
2053
|
+
};
|
|
2054
|
+
this.fetchClientDiagnostics.set(fetchId, state);
|
|
2055
|
+
} else {
|
|
2056
|
+
state.serviceName = serviceName;
|
|
2057
|
+
state.url = url;
|
|
2058
|
+
}
|
|
2059
|
+
return state;
|
|
2060
|
+
}
|
|
2061
|
+
getErrorMessage(error) {
|
|
2062
|
+
if (error instanceof Error) {
|
|
2063
|
+
return error.message;
|
|
2064
|
+
}
|
|
2065
|
+
if (typeof error === "string") {
|
|
2066
|
+
return error;
|
|
2067
|
+
}
|
|
2068
|
+
try {
|
|
2069
|
+
return JSON.stringify(error);
|
|
2070
|
+
} catch {
|
|
2071
|
+
return String(error);
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
recordFetchClientError(fetchId, serviceName, url, error) {
|
|
2075
|
+
const state = this.ensureFetchClientDiagnostics(fetchId, serviceName, url);
|
|
2076
|
+
const message = this.getErrorMessage(error);
|
|
2077
|
+
const now = Date.now();
|
|
2078
|
+
state.lastError = message;
|
|
2079
|
+
state.lastErrorAt = now;
|
|
2080
|
+
state.updatedAt = now;
|
|
2081
|
+
state.errorHistory.push({ at: new Date(now).toISOString(), message });
|
|
2082
|
+
if (state.errorHistory.length > this.diagnosticsErrorHistoryLimit) {
|
|
2083
|
+
state.errorHistory.splice(
|
|
2084
|
+
0,
|
|
2085
|
+
state.errorHistory.length - this.diagnosticsErrorHistoryLimit
|
|
2086
|
+
);
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
collectFetchTransportDiagnostics(ctx) {
|
|
2090
|
+
const { detailLevel, includeErrorHistory, errorHistoryLimit } = this.resolveTransportDiagnosticsOptions(ctx);
|
|
2091
|
+
const serviceName = CadenzaService.serviceRegistry.serviceName ?? "UnknownService";
|
|
2092
|
+
const states = Array.from(this.fetchClientDiagnostics.values()).sort(
|
|
2093
|
+
(a, b) => a.fetchId.localeCompare(b.fetchId)
|
|
2094
|
+
);
|
|
2095
|
+
const summary = {
|
|
2096
|
+
detailLevel,
|
|
2097
|
+
totalClients: states.length,
|
|
2098
|
+
connectedClients: states.filter((state) => state.connected).length,
|
|
2099
|
+
destroyedClients: states.filter((state) => state.destroyed).length,
|
|
2100
|
+
delegationRequests: states.reduce(
|
|
2101
|
+
(acc, state) => acc + state.delegationRequests,
|
|
2102
|
+
0
|
|
2103
|
+
),
|
|
2104
|
+
delegationFailures: states.reduce(
|
|
2105
|
+
(acc, state) => acc + state.delegationFailures,
|
|
2106
|
+
0
|
|
2107
|
+
),
|
|
2108
|
+
signalTransmissions: states.reduce(
|
|
2109
|
+
(acc, state) => acc + state.signalTransmissions,
|
|
2110
|
+
0
|
|
2111
|
+
),
|
|
2112
|
+
signalFailures: states.reduce((acc, state) => acc + state.signalFailures, 0),
|
|
2113
|
+
statusChecks: states.reduce((acc, state) => acc + state.statusChecks, 0),
|
|
2114
|
+
statusFailures: states.reduce((acc, state) => acc + state.statusFailures, 0),
|
|
2115
|
+
latestError: states.slice().sort((a, b) => b.lastErrorAt - a.lastErrorAt).find((state) => state.lastError)?.lastError ?? null
|
|
2116
|
+
};
|
|
2117
|
+
if (detailLevel === "summary") {
|
|
2118
|
+
return {
|
|
2119
|
+
transportDiagnostics: {
|
|
2120
|
+
[serviceName]: {
|
|
2121
|
+
fetchClient: summary
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
};
|
|
2125
|
+
}
|
|
2126
|
+
const clients = states.map((state) => {
|
|
2127
|
+
const details = {
|
|
2128
|
+
fetchId: state.fetchId,
|
|
2129
|
+
serviceName: state.serviceName,
|
|
2130
|
+
url: state.url,
|
|
2131
|
+
connected: state.connected,
|
|
2132
|
+
destroyed: state.destroyed,
|
|
2133
|
+
lastHandshakeAt: state.lastHandshakeAt,
|
|
2134
|
+
lastHandshakeError: state.lastHandshakeError,
|
|
2135
|
+
latestError: state.lastError,
|
|
2136
|
+
delegationRequests: state.delegationRequests,
|
|
2137
|
+
delegationFailures: state.delegationFailures,
|
|
2138
|
+
signalTransmissions: state.signalTransmissions,
|
|
2139
|
+
signalFailures: state.signalFailures,
|
|
2140
|
+
statusChecks: state.statusChecks,
|
|
2141
|
+
statusFailures: state.statusFailures
|
|
2142
|
+
};
|
|
2143
|
+
if (includeErrorHistory) {
|
|
2144
|
+
details.errorHistory = state.errorHistory.slice(-errorHistoryLimit);
|
|
2145
|
+
}
|
|
2146
|
+
return details;
|
|
2147
|
+
});
|
|
2148
|
+
return {
|
|
2149
|
+
transportDiagnostics: {
|
|
2150
|
+
[serviceName]: {
|
|
2151
|
+
fetchClient: {
|
|
2152
|
+
...summary,
|
|
2153
|
+
clients
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
};
|
|
2158
|
+
}
|
|
1665
2159
|
};
|
|
1666
2160
|
|
|
1667
2161
|
// src/network/SocketController.ts
|
|
@@ -1709,10 +2203,6 @@ var waitForSocketConnection = async (socket, timeoutMs, createError) => {
|
|
|
1709
2203
|
|
|
1710
2204
|
// src/network/SocketController.ts
|
|
1711
2205
|
var SocketController = class _SocketController {
|
|
1712
|
-
static get instance() {
|
|
1713
|
-
if (!this._instance) this._instance = new _SocketController();
|
|
1714
|
-
return this._instance;
|
|
1715
|
-
}
|
|
1716
2206
|
/**
|
|
1717
2207
|
* Constructs the `SocketServer`, setting up a WebSocket server with specific configurations,
|
|
1718
2208
|
* including connection state recovery, rate limiting, CORS handling, and custom event handling.
|
|
@@ -1731,6 +2221,13 @@ var SocketController = class _SocketController {
|
|
|
1731
2221
|
* Initializes the `SocketServer` to be ready for WebSocket communication.
|
|
1732
2222
|
*/
|
|
1733
2223
|
constructor() {
|
|
2224
|
+
this.socketClientDiagnostics = /* @__PURE__ */ new Map();
|
|
2225
|
+
this.diagnosticsErrorHistoryLimit = 100;
|
|
2226
|
+
CadenzaService.createMetaTask(
|
|
2227
|
+
"Collect socket transport diagnostics",
|
|
2228
|
+
(ctx) => this.collectSocketTransportDiagnostics(ctx),
|
|
2229
|
+
"Responds to distributed transport diagnostics inquiries with socket client data."
|
|
2230
|
+
).respondsTo(META_RUNTIME_TRANSPORT_DIAGNOSTICS_INTENT);
|
|
1734
2231
|
CadenzaService.createMetaRoutine(
|
|
1735
2232
|
"SocketServer",
|
|
1736
2233
|
[
|
|
@@ -1958,6 +2455,13 @@ var SocketController = class _SocketController {
|
|
|
1958
2455
|
const port = protocol === "https" ? 443 : servicePort;
|
|
1959
2456
|
const URL = `${socketProtocol}://${serviceAddress}:${port}`;
|
|
1960
2457
|
const fetchId = `${serviceAddress}_${port}`;
|
|
2458
|
+
const socketDiagnostics = this.ensureSocketClientDiagnostics(
|
|
2459
|
+
fetchId,
|
|
2460
|
+
serviceName,
|
|
2461
|
+
URL
|
|
2462
|
+
);
|
|
2463
|
+
socketDiagnostics.destroyed = false;
|
|
2464
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
1961
2465
|
let handshake = false;
|
|
1962
2466
|
let errorCount = 0;
|
|
1963
2467
|
const ERROR_LIMIT = 5;
|
|
@@ -1967,6 +2471,11 @@ var SocketController = class _SocketController {
|
|
|
1967
2471
|
}
|
|
1968
2472
|
const pendingDelegationIds = /* @__PURE__ */ new Set();
|
|
1969
2473
|
const pendingTimers = /* @__PURE__ */ new Set();
|
|
2474
|
+
const syncPendingCounts = () => {
|
|
2475
|
+
socketDiagnostics.pendingDelegations = pendingDelegationIds.size;
|
|
2476
|
+
socketDiagnostics.pendingTimers = pendingTimers.size;
|
|
2477
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2478
|
+
};
|
|
1970
2479
|
let handshakeTask = null;
|
|
1971
2480
|
let emitWhenReady = null;
|
|
1972
2481
|
let transmitTask = null;
|
|
@@ -2016,6 +2525,12 @@ var SocketController = class _SocketController {
|
|
|
2016
2525
|
{ socketId: socket?.id, serviceName, URL, event },
|
|
2017
2526
|
"error"
|
|
2018
2527
|
);
|
|
2528
|
+
this.recordSocketClientError(
|
|
2529
|
+
fetchId,
|
|
2530
|
+
serviceName,
|
|
2531
|
+
URL,
|
|
2532
|
+
waitResult.error
|
|
2533
|
+
);
|
|
2019
2534
|
resolveWithError(waitResult.error);
|
|
2020
2535
|
return;
|
|
2021
2536
|
}
|
|
@@ -2024,6 +2539,7 @@ var SocketController = class _SocketController {
|
|
|
2024
2539
|
timer = setTimeout(() => {
|
|
2025
2540
|
if (timer) {
|
|
2026
2541
|
pendingTimers.delete(timer);
|
|
2542
|
+
syncPendingCounts();
|
|
2027
2543
|
timer = null;
|
|
2028
2544
|
}
|
|
2029
2545
|
CadenzaService.log(
|
|
@@ -2031,9 +2547,16 @@ var SocketController = class _SocketController {
|
|
|
2031
2547
|
{ socketId: socket?.id, serviceName, URL },
|
|
2032
2548
|
"error"
|
|
2033
2549
|
);
|
|
2550
|
+
this.recordSocketClientError(
|
|
2551
|
+
fetchId,
|
|
2552
|
+
serviceName,
|
|
2553
|
+
URL,
|
|
2554
|
+
`Socket event '${event}' timed out`
|
|
2555
|
+
);
|
|
2034
2556
|
resolveWithError(`Socket event '${event}' timed out`);
|
|
2035
2557
|
}, timeoutMs + 10);
|
|
2036
2558
|
pendingTimers.add(timer);
|
|
2559
|
+
syncPendingCounts();
|
|
2037
2560
|
}
|
|
2038
2561
|
const connectedSocket = socket;
|
|
2039
2562
|
if (!connectedSocket) {
|
|
@@ -2046,6 +2569,7 @@ var SocketController = class _SocketController {
|
|
|
2046
2569
|
if (timer) {
|
|
2047
2570
|
clearTimeout(timer);
|
|
2048
2571
|
pendingTimers.delete(timer);
|
|
2572
|
+
syncPendingCounts();
|
|
2049
2573
|
timer = null;
|
|
2050
2574
|
}
|
|
2051
2575
|
if (err) {
|
|
@@ -2059,6 +2583,12 @@ var SocketController = class _SocketController {
|
|
|
2059
2583
|
},
|
|
2060
2584
|
"warning"
|
|
2061
2585
|
);
|
|
2586
|
+
this.recordSocketClientError(
|
|
2587
|
+
fetchId,
|
|
2588
|
+
serviceName,
|
|
2589
|
+
URL,
|
|
2590
|
+
err
|
|
2591
|
+
);
|
|
2062
2592
|
response = {
|
|
2063
2593
|
__error: `Timeout error: ${err}`,
|
|
2064
2594
|
errored: true,
|
|
@@ -2075,6 +2605,10 @@ var SocketController = class _SocketController {
|
|
|
2075
2605
|
};
|
|
2076
2606
|
socket.on("connect", () => {
|
|
2077
2607
|
if (handshake) return;
|
|
2608
|
+
socketDiagnostics.connected = true;
|
|
2609
|
+
socketDiagnostics.destroyed = false;
|
|
2610
|
+
socketDiagnostics.socketId = socket?.id ?? null;
|
|
2611
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2078
2612
|
CadenzaService.emit(`meta.socket_client.connected:${fetchId}`, ctx);
|
|
2079
2613
|
});
|
|
2080
2614
|
socket.on("delegation_progress", (ctx2) => {
|
|
@@ -2093,6 +2627,12 @@ var SocketController = class _SocketController {
|
|
|
2093
2627
|
});
|
|
2094
2628
|
socket.on("connect_error", (err) => {
|
|
2095
2629
|
handshake = false;
|
|
2630
|
+
socketDiagnostics.connected = false;
|
|
2631
|
+
socketDiagnostics.handshake = false;
|
|
2632
|
+
socketDiagnostics.connectErrors++;
|
|
2633
|
+
socketDiagnostics.lastHandshakeError = err.message;
|
|
2634
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2635
|
+
this.recordSocketClientError(fetchId, serviceName, URL, err);
|
|
2096
2636
|
CadenzaService.log(
|
|
2097
2637
|
"Socket connect error",
|
|
2098
2638
|
{ error: err.message, serviceName, socketId: socket?.id, URL },
|
|
@@ -2101,9 +2641,16 @@ var SocketController = class _SocketController {
|
|
|
2101
2641
|
CadenzaService.emit(`meta.socket_client.connect_error:${fetchId}`, err);
|
|
2102
2642
|
});
|
|
2103
2643
|
socket.on("reconnect_attempt", (attempt) => {
|
|
2644
|
+
socketDiagnostics.reconnectAttempts = Math.max(
|
|
2645
|
+
socketDiagnostics.reconnectAttempts,
|
|
2646
|
+
attempt
|
|
2647
|
+
);
|
|
2648
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2104
2649
|
CadenzaService.log(`Reconnect attempt: ${attempt}`);
|
|
2105
2650
|
});
|
|
2106
2651
|
socket.on("reconnect", (attempt) => {
|
|
2652
|
+
socketDiagnostics.connected = true;
|
|
2653
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2107
2654
|
CadenzaService.log(`Socket reconnected after ${attempt} tries`, {
|
|
2108
2655
|
socketId: socket?.id,
|
|
2109
2656
|
URL,
|
|
@@ -2112,6 +2659,12 @@ var SocketController = class _SocketController {
|
|
|
2112
2659
|
});
|
|
2113
2660
|
socket.on("reconnect_error", (err) => {
|
|
2114
2661
|
handshake = false;
|
|
2662
|
+
socketDiagnostics.connected = false;
|
|
2663
|
+
socketDiagnostics.handshake = false;
|
|
2664
|
+
socketDiagnostics.reconnectErrors++;
|
|
2665
|
+
socketDiagnostics.lastHandshakeError = err.message;
|
|
2666
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2667
|
+
this.recordSocketClientError(fetchId, serviceName, URL, err);
|
|
2115
2668
|
CadenzaService.log(
|
|
2116
2669
|
"Socket reconnect failed.",
|
|
2117
2670
|
{ error: err.message, serviceName, URL, socketId: socket?.id },
|
|
@@ -2120,6 +2673,9 @@ var SocketController = class _SocketController {
|
|
|
2120
2673
|
});
|
|
2121
2674
|
socket.on("error", (err) => {
|
|
2122
2675
|
errorCount++;
|
|
2676
|
+
socketDiagnostics.socketErrors++;
|
|
2677
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2678
|
+
this.recordSocketClientError(fetchId, serviceName, URL, err);
|
|
2123
2679
|
CadenzaService.log(
|
|
2124
2680
|
"Socket error",
|
|
2125
2681
|
{ error: err, socketId: socket?.id, URL, serviceName },
|
|
@@ -2128,6 +2684,11 @@ var SocketController = class _SocketController {
|
|
|
2128
2684
|
CadenzaService.emit("meta.socket_client.error", err);
|
|
2129
2685
|
});
|
|
2130
2686
|
socket.on("disconnect", () => {
|
|
2687
|
+
const disconnectedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2688
|
+
socketDiagnostics.connected = false;
|
|
2689
|
+
socketDiagnostics.handshake = false;
|
|
2690
|
+
socketDiagnostics.lastDisconnectAt = disconnectedAt;
|
|
2691
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2131
2692
|
CadenzaService.log(
|
|
2132
2693
|
"Socket disconnected.",
|
|
2133
2694
|
{ URL, serviceName, socketId: socket?.id },
|
|
@@ -2146,6 +2707,8 @@ var SocketController = class _SocketController {
|
|
|
2146
2707
|
async (ctx2, emit) => {
|
|
2147
2708
|
if (handshake) return;
|
|
2148
2709
|
handshake = true;
|
|
2710
|
+
socketDiagnostics.handshake = true;
|
|
2711
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2149
2712
|
await emitWhenReady?.(
|
|
2150
2713
|
"handshake",
|
|
2151
2714
|
{
|
|
@@ -2157,6 +2720,11 @@ var SocketController = class _SocketController {
|
|
|
2157
2720
|
1e4,
|
|
2158
2721
|
(result) => {
|
|
2159
2722
|
if (result.status === "success") {
|
|
2723
|
+
socketDiagnostics.connected = true;
|
|
2724
|
+
socketDiagnostics.handshake = true;
|
|
2725
|
+
socketDiagnostics.lastHandshakeAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2726
|
+
socketDiagnostics.lastHandshakeError = null;
|
|
2727
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2160
2728
|
CadenzaService.log("Socket client connected", {
|
|
2161
2729
|
result,
|
|
2162
2730
|
serviceName,
|
|
@@ -2164,6 +2732,16 @@ var SocketController = class _SocketController {
|
|
|
2164
2732
|
URL
|
|
2165
2733
|
});
|
|
2166
2734
|
} else {
|
|
2735
|
+
socketDiagnostics.connected = false;
|
|
2736
|
+
socketDiagnostics.handshake = false;
|
|
2737
|
+
socketDiagnostics.lastHandshakeError = result?.__error ?? result?.error ?? "Socket handshake failed";
|
|
2738
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2739
|
+
this.recordSocketClientError(
|
|
2740
|
+
fetchId,
|
|
2741
|
+
serviceName,
|
|
2742
|
+
URL,
|
|
2743
|
+
socketDiagnostics.lastHandshakeError
|
|
2744
|
+
);
|
|
2167
2745
|
CadenzaService.log(
|
|
2168
2746
|
"Socket handshake failed",
|
|
2169
2747
|
{ result, serviceName, socketId: socket?.id, URL },
|
|
@@ -2186,6 +2764,7 @@ var SocketController = class _SocketController {
|
|
|
2186
2764
|
delete ctx2.__broadcast;
|
|
2187
2765
|
const requestSentAt = Date.now();
|
|
2188
2766
|
pendingDelegationIds.add(ctx2.__metadata.__deputyExecId);
|
|
2767
|
+
syncPendingCounts();
|
|
2189
2768
|
emitWhenReady?.(
|
|
2190
2769
|
"delegation",
|
|
2191
2770
|
ctx2,
|
|
@@ -2203,6 +2782,15 @@ var SocketController = class _SocketController {
|
|
|
2203
2782
|
}
|
|
2204
2783
|
);
|
|
2205
2784
|
pendingDelegationIds.delete(ctx2.__metadata.__deputyExecId);
|
|
2785
|
+
syncPendingCounts();
|
|
2786
|
+
if (resultContext?.errored || resultContext?.failed) {
|
|
2787
|
+
this.recordSocketClientError(
|
|
2788
|
+
fetchId,
|
|
2789
|
+
serviceName,
|
|
2790
|
+
URL,
|
|
2791
|
+
resultContext?.__error ?? resultContext?.error ?? "Socket delegation failed"
|
|
2792
|
+
);
|
|
2793
|
+
}
|
|
2206
2794
|
resolve(resultContext);
|
|
2207
2795
|
}
|
|
2208
2796
|
);
|
|
@@ -2238,6 +2826,10 @@ var SocketController = class _SocketController {
|
|
|
2238
2826
|
`Shutdown SocketClient ${URL}`,
|
|
2239
2827
|
(ctx2, emit) => {
|
|
2240
2828
|
handshake = false;
|
|
2829
|
+
socketDiagnostics.connected = false;
|
|
2830
|
+
socketDiagnostics.handshake = false;
|
|
2831
|
+
socketDiagnostics.destroyed = true;
|
|
2832
|
+
socketDiagnostics.updatedAt = Date.now();
|
|
2241
2833
|
CadenzaService.log("Shutting down socket client", { URL, serviceName });
|
|
2242
2834
|
socket?.close();
|
|
2243
2835
|
handshakeTask?.destroy();
|
|
@@ -2267,10 +2859,12 @@ var SocketController = class _SocketController {
|
|
|
2267
2859
|
});
|
|
2268
2860
|
}
|
|
2269
2861
|
pendingDelegationIds.clear();
|
|
2862
|
+
syncPendingCounts();
|
|
2270
2863
|
for (const timer of pendingTimers) {
|
|
2271
2864
|
clearTimeout(timer);
|
|
2272
2865
|
}
|
|
2273
2866
|
pendingTimers.clear();
|
|
2867
|
+
syncPendingCounts();
|
|
2274
2868
|
},
|
|
2275
2869
|
"Shuts down the socket client"
|
|
2276
2870
|
).doOn(
|
|
@@ -2284,6 +2878,157 @@ var SocketController = class _SocketController {
|
|
|
2284
2878
|
"Connects to a specified socket server"
|
|
2285
2879
|
).doOn("meta.fetch.handshake_complete").emitsOnFail("meta.socket_client.connect_failed");
|
|
2286
2880
|
}
|
|
2881
|
+
static get instance() {
|
|
2882
|
+
if (!this._instance) this._instance = new _SocketController();
|
|
2883
|
+
return this._instance;
|
|
2884
|
+
}
|
|
2885
|
+
resolveTransportDiagnosticsOptions(ctx) {
|
|
2886
|
+
const detailLevel = ctx.detailLevel === "full" ? "full" : "summary";
|
|
2887
|
+
const includeErrorHistory = Boolean(ctx.includeErrorHistory);
|
|
2888
|
+
const requestedLimit = Number(ctx.errorHistoryLimit);
|
|
2889
|
+
const errorHistoryLimit = Number.isFinite(requestedLimit) ? Math.max(1, Math.min(200, Math.trunc(requestedLimit))) : 10;
|
|
2890
|
+
return {
|
|
2891
|
+
detailLevel,
|
|
2892
|
+
includeErrorHistory,
|
|
2893
|
+
errorHistoryLimit
|
|
2894
|
+
};
|
|
2895
|
+
}
|
|
2896
|
+
ensureSocketClientDiagnostics(fetchId, serviceName, url) {
|
|
2897
|
+
let state = this.socketClientDiagnostics.get(fetchId);
|
|
2898
|
+
if (!state) {
|
|
2899
|
+
state = {
|
|
2900
|
+
fetchId,
|
|
2901
|
+
serviceName,
|
|
2902
|
+
url,
|
|
2903
|
+
socketId: null,
|
|
2904
|
+
connected: false,
|
|
2905
|
+
handshake: false,
|
|
2906
|
+
reconnectAttempts: 0,
|
|
2907
|
+
connectErrors: 0,
|
|
2908
|
+
reconnectErrors: 0,
|
|
2909
|
+
socketErrors: 0,
|
|
2910
|
+
pendingDelegations: 0,
|
|
2911
|
+
pendingTimers: 0,
|
|
2912
|
+
destroyed: false,
|
|
2913
|
+
lastHandshakeAt: null,
|
|
2914
|
+
lastHandshakeError: null,
|
|
2915
|
+
lastDisconnectAt: null,
|
|
2916
|
+
lastError: null,
|
|
2917
|
+
lastErrorAt: 0,
|
|
2918
|
+
errorHistory: [],
|
|
2919
|
+
updatedAt: Date.now()
|
|
2920
|
+
};
|
|
2921
|
+
this.socketClientDiagnostics.set(fetchId, state);
|
|
2922
|
+
} else {
|
|
2923
|
+
state.serviceName = serviceName;
|
|
2924
|
+
state.url = url;
|
|
2925
|
+
}
|
|
2926
|
+
return state;
|
|
2927
|
+
}
|
|
2928
|
+
getErrorMessage(error) {
|
|
2929
|
+
if (error instanceof Error) {
|
|
2930
|
+
return error.message;
|
|
2931
|
+
}
|
|
2932
|
+
if (typeof error === "string") {
|
|
2933
|
+
return error;
|
|
2934
|
+
}
|
|
2935
|
+
try {
|
|
2936
|
+
return JSON.stringify(error);
|
|
2937
|
+
} catch {
|
|
2938
|
+
return String(error);
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
recordSocketClientError(fetchId, serviceName, url, error) {
|
|
2942
|
+
const state = this.ensureSocketClientDiagnostics(fetchId, serviceName, url);
|
|
2943
|
+
const message = this.getErrorMessage(error);
|
|
2944
|
+
const now = Date.now();
|
|
2945
|
+
state.lastError = message;
|
|
2946
|
+
state.lastErrorAt = now;
|
|
2947
|
+
state.updatedAt = now;
|
|
2948
|
+
state.errorHistory.push({
|
|
2949
|
+
at: new Date(now).toISOString(),
|
|
2950
|
+
message
|
|
2951
|
+
});
|
|
2952
|
+
if (state.errorHistory.length > this.diagnosticsErrorHistoryLimit) {
|
|
2953
|
+
state.errorHistory.splice(
|
|
2954
|
+
0,
|
|
2955
|
+
state.errorHistory.length - this.diagnosticsErrorHistoryLimit
|
|
2956
|
+
);
|
|
2957
|
+
}
|
|
2958
|
+
}
|
|
2959
|
+
collectSocketTransportDiagnostics(ctx) {
|
|
2960
|
+
const { detailLevel, includeErrorHistory, errorHistoryLimit } = this.resolveTransportDiagnosticsOptions(ctx);
|
|
2961
|
+
const serviceName = CadenzaService.serviceRegistry.serviceName ?? "UnknownService";
|
|
2962
|
+
const states = Array.from(this.socketClientDiagnostics.values()).sort(
|
|
2963
|
+
(a, b) => a.fetchId.localeCompare(b.fetchId)
|
|
2964
|
+
);
|
|
2965
|
+
const summary = {
|
|
2966
|
+
detailLevel,
|
|
2967
|
+
totalClients: states.length,
|
|
2968
|
+
connectedClients: states.filter((state) => state.connected).length,
|
|
2969
|
+
activeHandshakes: states.filter((state) => state.handshake).length,
|
|
2970
|
+
pendingDelegations: states.reduce(
|
|
2971
|
+
(acc, state) => acc + state.pendingDelegations,
|
|
2972
|
+
0
|
|
2973
|
+
),
|
|
2974
|
+
pendingTimers: states.reduce((acc, state) => acc + state.pendingTimers, 0),
|
|
2975
|
+
reconnectAttempts: states.reduce(
|
|
2976
|
+
(acc, state) => acc + state.reconnectAttempts,
|
|
2977
|
+
0
|
|
2978
|
+
),
|
|
2979
|
+
connectErrors: states.reduce((acc, state) => acc + state.connectErrors, 0),
|
|
2980
|
+
reconnectErrors: states.reduce(
|
|
2981
|
+
(acc, state) => acc + state.reconnectErrors,
|
|
2982
|
+
0
|
|
2983
|
+
),
|
|
2984
|
+
socketErrors: states.reduce((acc, state) => acc + state.socketErrors, 0),
|
|
2985
|
+
latestError: states.slice().sort((a, b) => b.lastErrorAt - a.lastErrorAt).find((state) => state.lastError)?.lastError ?? null
|
|
2986
|
+
};
|
|
2987
|
+
if (detailLevel === "summary") {
|
|
2988
|
+
return {
|
|
2989
|
+
transportDiagnostics: {
|
|
2990
|
+
[serviceName]: {
|
|
2991
|
+
socketClient: summary
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
};
|
|
2995
|
+
}
|
|
2996
|
+
const clients = states.map((state) => {
|
|
2997
|
+
const details = {
|
|
2998
|
+
fetchId: state.fetchId,
|
|
2999
|
+
serviceName: state.serviceName,
|
|
3000
|
+
url: state.url,
|
|
3001
|
+
socketId: state.socketId,
|
|
3002
|
+
connected: state.connected,
|
|
3003
|
+
handshake: state.handshake,
|
|
3004
|
+
reconnectAttempts: state.reconnectAttempts,
|
|
3005
|
+
connectErrors: state.connectErrors,
|
|
3006
|
+
reconnectErrors: state.reconnectErrors,
|
|
3007
|
+
socketErrors: state.socketErrors,
|
|
3008
|
+
pendingDelegations: state.pendingDelegations,
|
|
3009
|
+
pendingTimers: state.pendingTimers,
|
|
3010
|
+
destroyed: state.destroyed,
|
|
3011
|
+
lastHandshakeAt: state.lastHandshakeAt,
|
|
3012
|
+
lastHandshakeError: state.lastHandshakeError,
|
|
3013
|
+
lastDisconnectAt: state.lastDisconnectAt,
|
|
3014
|
+
latestError: state.lastError
|
|
3015
|
+
};
|
|
3016
|
+
if (includeErrorHistory) {
|
|
3017
|
+
details.errorHistory = state.errorHistory.slice(-errorHistoryLimit);
|
|
3018
|
+
}
|
|
3019
|
+
return details;
|
|
3020
|
+
});
|
|
3021
|
+
return {
|
|
3022
|
+
transportDiagnostics: {
|
|
3023
|
+
[serviceName]: {
|
|
3024
|
+
socketClient: {
|
|
3025
|
+
...summary,
|
|
3026
|
+
clients
|
|
3027
|
+
}
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
};
|
|
3031
|
+
}
|
|
2287
3032
|
};
|
|
2288
3033
|
|
|
2289
3034
|
// src/utils/tools.ts
|
|
@@ -2387,25 +3132,8 @@ var GraphMetadataController = class _GraphMetadataController {
|
|
|
2387
3132
|
return {
|
|
2388
3133
|
data: {
|
|
2389
3134
|
...ctx.data,
|
|
2390
|
-
serviceName: CadenzaService.serviceRegistry.serviceName
|
|
2391
|
-
|
|
2392
|
-
subOperation: "insert",
|
|
2393
|
-
table: "context_schema",
|
|
2394
|
-
data: {
|
|
2395
|
-
...ctx.data.inputContextSchemaId
|
|
2396
|
-
},
|
|
2397
|
-
return: "uuid"
|
|
2398
|
-
} : null,
|
|
2399
|
-
outputContextSchemaId: ctx.data.outputContextSchemaId ? {
|
|
2400
|
-
subOperation: "insert",
|
|
2401
|
-
table: "context_schema",
|
|
2402
|
-
data: {
|
|
2403
|
-
...ctx.data.outputContextSchemaId
|
|
2404
|
-
},
|
|
2405
|
-
return: "uuid"
|
|
2406
|
-
} : null
|
|
2407
|
-
},
|
|
2408
|
-
transaction: true
|
|
3135
|
+
serviceName: CadenzaService.serviceRegistry.serviceName
|
|
3136
|
+
}
|
|
2409
3137
|
};
|
|
2410
3138
|
}).doOn("meta.task.created").emits("global.meta.graph_metadata.task_created");
|
|
2411
3139
|
CadenzaService.createMetaTask("Handle task update", (ctx) => {
|
|
@@ -2612,9 +3340,11 @@ var GraphMetadataController = class _GraphMetadataController {
|
|
|
2612
3340
|
{ concurrency: 100, isSubMeta: true }
|
|
2613
3341
|
).doOn("meta.node.mapped", "meta.node.detected_previous_task_execution").emits("global.meta.graph_metadata.relationship_executed");
|
|
2614
3342
|
CadenzaService.createMetaTask("Handle Intent Creation", (ctx) => {
|
|
3343
|
+
const intentName = ctx.data?.name;
|
|
2615
3344
|
return {
|
|
2616
3345
|
data: {
|
|
2617
|
-
...ctx.data
|
|
3346
|
+
...ctx.data,
|
|
3347
|
+
isMeta: intentName ? isMetaIntentName(intentName) : false
|
|
2618
3348
|
}
|
|
2619
3349
|
};
|
|
2620
3350
|
}).doOn("meta.inquiry_broker.added").emits("global.meta.graph_metadata.intent_created");
|
|
@@ -2646,6 +3376,52 @@ var SCHEMA_TYPES = [
|
|
|
2646
3376
|
// src/database/DatabaseController.ts
|
|
2647
3377
|
var import_pg = require("pg");
|
|
2648
3378
|
var import_lodash_es = require("lodash-es");
|
|
3379
|
+
function resolveTableQueryIntents(serviceName, tableName, table, defaultInputSchema) {
|
|
3380
|
+
const resolvedServiceName = serviceName ?? "unknown-service";
|
|
3381
|
+
const defaultIntentName = `query-${resolvedServiceName}-${tableName}`;
|
|
3382
|
+
const defaultDescription = `Perform a query operation on the ${tableName} table`;
|
|
3383
|
+
const intents = [
|
|
3384
|
+
{
|
|
3385
|
+
name: defaultIntentName,
|
|
3386
|
+
description: defaultDescription,
|
|
3387
|
+
input: defaultInputSchema
|
|
3388
|
+
}
|
|
3389
|
+
];
|
|
3390
|
+
const warnings = [];
|
|
3391
|
+
const names = /* @__PURE__ */ new Set([defaultIntentName]);
|
|
3392
|
+
for (const customIntent of table.customIntents?.query ?? []) {
|
|
3393
|
+
const name = typeof customIntent === "string" ? customIntent.trim() : customIntent.intent?.trim();
|
|
3394
|
+
if (!name) {
|
|
3395
|
+
warnings.push(`Skipped empty custom query intent for table '${tableName}'.`);
|
|
3396
|
+
continue;
|
|
3397
|
+
}
|
|
3398
|
+
if (name.length > 100) {
|
|
3399
|
+
warnings.push(
|
|
3400
|
+
`Skipped custom query intent '${name}' for table '${tableName}': name must be <= 100 characters.`
|
|
3401
|
+
);
|
|
3402
|
+
continue;
|
|
3403
|
+
}
|
|
3404
|
+
if (name.includes(" ") || name.includes(".") || name.includes("\\")) {
|
|
3405
|
+
warnings.push(
|
|
3406
|
+
`Skipped custom query intent '${name}' for table '${tableName}': name cannot contain spaces, dots or backslashes.`
|
|
3407
|
+
);
|
|
3408
|
+
continue;
|
|
3409
|
+
}
|
|
3410
|
+
if (names.has(name)) {
|
|
3411
|
+
warnings.push(
|
|
3412
|
+
`Skipped duplicate custom query intent '${name}' for table '${tableName}'.`
|
|
3413
|
+
);
|
|
3414
|
+
continue;
|
|
3415
|
+
}
|
|
3416
|
+
names.add(name);
|
|
3417
|
+
intents.push({
|
|
3418
|
+
name,
|
|
3419
|
+
description: typeof customIntent === "string" ? `Perform a query operation on the ${tableName} table` : customIntent.description ?? defaultDescription,
|
|
3420
|
+
input: typeof customIntent === "string" ? defaultInputSchema : customIntent.input ?? defaultInputSchema
|
|
3421
|
+
});
|
|
3422
|
+
}
|
|
3423
|
+
return { intents, warnings };
|
|
3424
|
+
}
|
|
2649
3425
|
var DatabaseController = class _DatabaseController {
|
|
2650
3426
|
/**
|
|
2651
3427
|
* Constructor for initializing the `DatabaseService` class.
|
|
@@ -2787,6 +3563,20 @@ var DatabaseController = class _DatabaseController {
|
|
|
2787
3563
|
}
|
|
2788
3564
|
}
|
|
2789
3565
|
}
|
|
3566
|
+
if (table.customIntents?.query) {
|
|
3567
|
+
if (!Array.isArray(table.customIntents.query)) {
|
|
3568
|
+
throw new Error(
|
|
3569
|
+
`Invalid customIntents.query for ${tableName}: expected array`
|
|
3570
|
+
);
|
|
3571
|
+
}
|
|
3572
|
+
for (const customIntent of table.customIntents.query) {
|
|
3573
|
+
if (typeof customIntent !== "string" && (typeof customIntent !== "object" || !customIntent || typeof customIntent.intent !== "string")) {
|
|
3574
|
+
throw new Error(
|
|
3575
|
+
`Invalid custom query intent on ${tableName}: expected string or object with intent`
|
|
3576
|
+
);
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
2790
3580
|
}
|
|
2791
3581
|
}
|
|
2792
3582
|
console.log("SCHEMA VALIDATED");
|
|
@@ -3823,13 +4613,30 @@ var DatabaseController = class _DatabaseController {
|
|
|
3823
4613
|
}) ?? []
|
|
3824
4614
|
);
|
|
3825
4615
|
if (op === "query") {
|
|
3826
|
-
const
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
4616
|
+
const { intents, warnings } = resolveTableQueryIntents(
|
|
4617
|
+
CadenzaService.serviceRegistry?.serviceName,
|
|
4618
|
+
tableName,
|
|
4619
|
+
table,
|
|
4620
|
+
schema
|
|
4621
|
+
);
|
|
4622
|
+
for (const warning of warnings) {
|
|
4623
|
+
CadenzaService.log(
|
|
4624
|
+
"Skipped custom query intent registration.",
|
|
4625
|
+
{
|
|
4626
|
+
tableName,
|
|
4627
|
+
warning
|
|
4628
|
+
},
|
|
4629
|
+
"warning"
|
|
4630
|
+
);
|
|
4631
|
+
}
|
|
4632
|
+
for (const intent of intents) {
|
|
4633
|
+
CadenzaService.defineIntent({
|
|
4634
|
+
name: intent.name,
|
|
4635
|
+
description: intent.description,
|
|
4636
|
+
input: intent.input
|
|
4637
|
+
});
|
|
4638
|
+
}
|
|
4639
|
+
task.respondsTo(...intents.map((intent) => intent.name));
|
|
3833
4640
|
}
|
|
3834
4641
|
}
|
|
3835
4642
|
getInputSchema(op, tableName, table) {
|
|
@@ -3921,18 +4728,18 @@ function getInsertDataSchemaFromTable(table, tableName) {
|
|
|
3921
4728
|
Object.entries(table.fields).map((field) => {
|
|
3922
4729
|
return [
|
|
3923
4730
|
field[0],
|
|
3924
|
-
|
|
3925
|
-
{
|
|
4731
|
+
{
|
|
4732
|
+
value: {
|
|
3926
4733
|
type: tableFieldTypeToSchemaType(field[1].type),
|
|
3927
4734
|
description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
|
|
3928
4735
|
},
|
|
3929
|
-
{
|
|
4736
|
+
effect: {
|
|
3930
4737
|
type: "string",
|
|
3931
4738
|
constraints: {
|
|
3932
4739
|
oneOf: ["increment", "decrement", "set"]
|
|
3933
4740
|
}
|
|
3934
4741
|
},
|
|
3935
|
-
{
|
|
4742
|
+
subOperation: {
|
|
3936
4743
|
type: "object",
|
|
3937
4744
|
properties: {
|
|
3938
4745
|
subOperation: {
|
|
@@ -3942,17 +4749,17 @@ function getInsertDataSchemaFromTable(table, tableName) {
|
|
|
3942
4749
|
table: {
|
|
3943
4750
|
type: "string"
|
|
3944
4751
|
},
|
|
3945
|
-
data:
|
|
3946
|
-
{
|
|
4752
|
+
data: {
|
|
4753
|
+
single: {
|
|
3947
4754
|
type: "object"
|
|
3948
4755
|
},
|
|
3949
|
-
{
|
|
4756
|
+
batch: {
|
|
3950
4757
|
type: "array",
|
|
3951
4758
|
items: {
|
|
3952
4759
|
type: "object"
|
|
3953
4760
|
}
|
|
3954
4761
|
}
|
|
3955
|
-
|
|
4762
|
+
},
|
|
3956
4763
|
filter: {
|
|
3957
4764
|
type: "object"
|
|
3958
4765
|
},
|
|
@@ -3968,7 +4775,7 @@ function getInsertDataSchemaFromTable(table, tableName) {
|
|
|
3968
4775
|
},
|
|
3969
4776
|
required: ["subOperation", "table"]
|
|
3970
4777
|
}
|
|
3971
|
-
|
|
4778
|
+
}
|
|
3972
4779
|
];
|
|
3973
4780
|
})
|
|
3974
4781
|
)
|
|
@@ -3976,13 +4783,13 @@ function getInsertDataSchemaFromTable(table, tableName) {
|
|
|
3976
4783
|
required: Object.entries(table.fields).filter((field) => field[1].required || field[1].primary).map((field) => field[0]),
|
|
3977
4784
|
strict: true
|
|
3978
4785
|
};
|
|
3979
|
-
return
|
|
3980
|
-
dataSchema,
|
|
3981
|
-
{
|
|
4786
|
+
return {
|
|
4787
|
+
single: dataSchema,
|
|
4788
|
+
batch: {
|
|
3982
4789
|
type: "array",
|
|
3983
4790
|
items: dataSchema
|
|
3984
4791
|
}
|
|
3985
|
-
|
|
4792
|
+
};
|
|
3986
4793
|
}
|
|
3987
4794
|
function getQueryFilterSchemaFromTable(table, tableName) {
|
|
3988
4795
|
return {
|
|
@@ -3992,24 +4799,24 @@ function getQueryFilterSchemaFromTable(table, tableName) {
|
|
|
3992
4799
|
Object.entries(table.fields).map((field) => {
|
|
3993
4800
|
return [
|
|
3994
4801
|
field[0],
|
|
3995
|
-
|
|
3996
|
-
{
|
|
4802
|
+
{
|
|
4803
|
+
value: {
|
|
3997
4804
|
type: tableFieldTypeToSchemaType(field[1].type),
|
|
3998
4805
|
description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
|
|
3999
4806
|
},
|
|
4000
|
-
{
|
|
4807
|
+
in: {
|
|
4001
4808
|
type: "array",
|
|
4002
4809
|
items: {
|
|
4003
4810
|
type: tableFieldTypeToSchemaType(field[1].type)
|
|
4004
4811
|
}
|
|
4005
4812
|
}
|
|
4006
|
-
|
|
4813
|
+
}
|
|
4007
4814
|
];
|
|
4008
4815
|
})
|
|
4009
4816
|
)
|
|
4010
4817
|
},
|
|
4011
4818
|
strict: true,
|
|
4012
|
-
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry
|
|
4819
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry?.serviceName ?? "unknown-service"}.`
|
|
4013
4820
|
};
|
|
4014
4821
|
}
|
|
4015
4822
|
function getQueryFieldsSchemaFromTable(table, tableName) {
|
|
@@ -4021,7 +4828,7 @@ function getQueryFieldsSchemaFromTable(table, tableName) {
|
|
|
4021
4828
|
oneOf: Object.keys(table.fields)
|
|
4022
4829
|
}
|
|
4023
4830
|
},
|
|
4024
|
-
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry
|
|
4831
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry?.serviceName ?? "unknown-service"}.`
|
|
4025
4832
|
};
|
|
4026
4833
|
}
|
|
4027
4834
|
function getQueryJoinsSchemaFromTable(table, tableName) {
|
|
@@ -4068,7 +4875,7 @@ function getQueryJoinsSchemaFromTable(table, tableName) {
|
|
|
4068
4875
|
)
|
|
4069
4876
|
},
|
|
4070
4877
|
strict: true,
|
|
4071
|
-
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry
|
|
4878
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry?.serviceName ?? "unknown-service"}.`
|
|
4072
4879
|
};
|
|
4073
4880
|
}
|
|
4074
4881
|
function getQuerySortSchemaFromTable(table, tableName) {
|
|
@@ -4090,7 +4897,7 @@ function getQuerySortSchemaFromTable(table, tableName) {
|
|
|
4090
4897
|
)
|
|
4091
4898
|
},
|
|
4092
4899
|
strict: true,
|
|
4093
|
-
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry
|
|
4900
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry?.serviceName ?? "unknown-service"}.`
|
|
4094
4901
|
};
|
|
4095
4902
|
}
|
|
4096
4903
|
function getQueryLimitSchemaFromTable() {
|
|
@@ -4152,12 +4959,10 @@ function getQueryOnConflictSchemaFromTable(table, tableName) {
|
|
|
4152
4959
|
Object.entries(table.fields).map((field) => {
|
|
4153
4960
|
return [
|
|
4154
4961
|
field[0],
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
}
|
|
4160
|
-
]
|
|
4962
|
+
{
|
|
4963
|
+
type: tableFieldTypeToSchemaType(field[1].type),
|
|
4964
|
+
description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
|
|
4965
|
+
}
|
|
4161
4966
|
];
|
|
4162
4967
|
})
|
|
4163
4968
|
)
|
|
@@ -4515,6 +5320,75 @@ var GraphSyncController = class _GraphSyncController {
|
|
|
4515
5320
|
{ concurrency: 30 }
|
|
4516
5321
|
) : CadenzaService.get("dbInsertSignalToTaskMap"))?.then(registerSignalTask)
|
|
4517
5322
|
);
|
|
5323
|
+
const registerIntentTask = CadenzaService.createMetaTask(
|
|
5324
|
+
"Record intent registration",
|
|
5325
|
+
(ctx) => {
|
|
5326
|
+
if (!ctx.__syncing) {
|
|
5327
|
+
return;
|
|
5328
|
+
}
|
|
5329
|
+
CadenzaService.debounce("meta.sync_controller.synced_resource", {
|
|
5330
|
+
delayMs: 3e3
|
|
5331
|
+
});
|
|
5332
|
+
const task = CadenzaService.get(ctx.__taskName);
|
|
5333
|
+
task.__registeredIntents = task.__registeredIntents ?? /* @__PURE__ */ new Set();
|
|
5334
|
+
task.__registeredIntents.add(ctx.__intent);
|
|
5335
|
+
}
|
|
5336
|
+
);
|
|
5337
|
+
this.registerIntentToTaskMapTask = CadenzaService.createMetaTask(
|
|
5338
|
+
"Split intents of task",
|
|
5339
|
+
function* (ctx) {
|
|
5340
|
+
const task = ctx.task;
|
|
5341
|
+
if (task.hidden || !task.register) return;
|
|
5342
|
+
task.__registeredIntents = task.__registeredIntents ?? /* @__PURE__ */ new Set();
|
|
5343
|
+
task.__invalidMetaIntentWarnings = task.__invalidMetaIntentWarnings ?? /* @__PURE__ */ new Set();
|
|
5344
|
+
for (const intent of task.handlesIntents) {
|
|
5345
|
+
if (task.__registeredIntents.has(intent)) continue;
|
|
5346
|
+
if (isMetaIntentName(intent) && !task.isMeta) {
|
|
5347
|
+
if (!task.__invalidMetaIntentWarnings.has(intent)) {
|
|
5348
|
+
task.__invalidMetaIntentWarnings.add(intent);
|
|
5349
|
+
CadenzaService.log(
|
|
5350
|
+
"Skipping intent-to-task registration: non-meta task cannot handle meta intent.",
|
|
5351
|
+
{
|
|
5352
|
+
intent,
|
|
5353
|
+
taskName: task.name,
|
|
5354
|
+
taskVersion: task.version
|
|
5355
|
+
},
|
|
5356
|
+
"warning"
|
|
5357
|
+
);
|
|
5358
|
+
}
|
|
5359
|
+
continue;
|
|
5360
|
+
}
|
|
5361
|
+
yield {
|
|
5362
|
+
data: {
|
|
5363
|
+
intentName: intent,
|
|
5364
|
+
taskName: task.name,
|
|
5365
|
+
taskVersion: task.version,
|
|
5366
|
+
serviceName: CadenzaService.serviceRegistry.serviceName
|
|
5367
|
+
},
|
|
5368
|
+
__taskName: task.name,
|
|
5369
|
+
__intent: intent
|
|
5370
|
+
};
|
|
5371
|
+
}
|
|
5372
|
+
}
|
|
5373
|
+
).then(
|
|
5374
|
+
(this.isCadenzaDBReady ? CadenzaService.createCadenzaDBInsertTask(
|
|
5375
|
+
"intent_to_task_map",
|
|
5376
|
+
{
|
|
5377
|
+
onConflict: {
|
|
5378
|
+
target: [
|
|
5379
|
+
"intent_name",
|
|
5380
|
+
"task_name",
|
|
5381
|
+
"task_version",
|
|
5382
|
+
"service_name"
|
|
5383
|
+
],
|
|
5384
|
+
action: {
|
|
5385
|
+
do: "nothing"
|
|
5386
|
+
}
|
|
5387
|
+
}
|
|
5388
|
+
},
|
|
5389
|
+
{ concurrency: 30 }
|
|
5390
|
+
) : CadenzaService.get("dbInsertIntentToTaskMap"))?.then(registerIntentTask)
|
|
5391
|
+
);
|
|
4518
5392
|
this.registerTaskMapTask = CadenzaService.createMetaTask(
|
|
4519
5393
|
"Register task map to DB",
|
|
4520
5394
|
function* (ctx) {
|
|
@@ -4637,6 +5511,7 @@ var GraphSyncController = class _GraphSyncController {
|
|
|
4637
5511
|
CadenzaService.registry.doForEachTask.clone().doOn("meta.sync_controller.synced_tasks").then(
|
|
4638
5512
|
this.registerTaskMapTask,
|
|
4639
5513
|
this.registerSignalToTaskMapTask,
|
|
5514
|
+
this.registerIntentToTaskMapTask,
|
|
4640
5515
|
this.registerDeputyRelationshipTask
|
|
4641
5516
|
);
|
|
4642
5517
|
CadenzaService.registry.getAllRoutines.clone().doOn("meta.sync_controller.synced_routines").then(this.splitTasksInRoutines);
|
|
@@ -4778,11 +5653,192 @@ var CadenzaService = class {
|
|
|
4778
5653
|
import_core3.default.interval(signal, context, intervalMs, leading, startDateTime);
|
|
4779
5654
|
}
|
|
4780
5655
|
static defineIntent(intent) {
|
|
4781
|
-
this.inquiryBroker?.
|
|
5656
|
+
this.inquiryBroker?.addIntent(intent);
|
|
4782
5657
|
return intent;
|
|
4783
5658
|
}
|
|
4784
|
-
static
|
|
4785
|
-
return this.
|
|
5659
|
+
static getInquiryResponderDescriptor(task) {
|
|
5660
|
+
return this.serviceRegistry.getInquiryResponderDescriptor(task);
|
|
5661
|
+
}
|
|
5662
|
+
static compareInquiryResponders(left, right) {
|
|
5663
|
+
return compareResponderDescriptors(left.descriptor, right.descriptor);
|
|
5664
|
+
}
|
|
5665
|
+
static buildInquirySummary(inquiry, startedAt, statuses, totalResponders) {
|
|
5666
|
+
const counts = summarizeResponderStatuses(statuses);
|
|
5667
|
+
const isMetaInquiry = isMetaIntentName(inquiry);
|
|
5668
|
+
const eligibleResponders = statuses.length;
|
|
5669
|
+
return {
|
|
5670
|
+
inquiry,
|
|
5671
|
+
isMetaInquiry,
|
|
5672
|
+
totalResponders,
|
|
5673
|
+
eligibleResponders,
|
|
5674
|
+
filteredOutResponders: Math.max(0, totalResponders - eligibleResponders),
|
|
5675
|
+
responded: counts.responded,
|
|
5676
|
+
failed: counts.failed,
|
|
5677
|
+
timedOut: counts.timedOut,
|
|
5678
|
+
pending: counts.pending,
|
|
5679
|
+
durationMs: Date.now() - startedAt,
|
|
5680
|
+
responders: statuses
|
|
5681
|
+
};
|
|
5682
|
+
}
|
|
5683
|
+
static async inquire(inquiry, context, options = {}) {
|
|
5684
|
+
this.bootstrap();
|
|
5685
|
+
const observer = this.inquiryBroker?.inquiryObservers.get(inquiry);
|
|
5686
|
+
const allResponders = observer ? Array.from(observer.tasks).map((task) => ({
|
|
5687
|
+
task,
|
|
5688
|
+
descriptor: this.getInquiryResponderDescriptor(task)
|
|
5689
|
+
})) : [];
|
|
5690
|
+
const isMetaInquiry = isMetaIntentName(inquiry);
|
|
5691
|
+
const responders = allResponders.filter(({ task, descriptor }) => {
|
|
5692
|
+
const shouldExecute = shouldExecuteInquiryResponder(inquiry, task.isMeta);
|
|
5693
|
+
if (shouldExecute) {
|
|
5694
|
+
return true;
|
|
5695
|
+
}
|
|
5696
|
+
const warningKey = `${inquiry}|${descriptor.serviceName}|${descriptor.taskName}|${descriptor.taskVersion}|${descriptor.localTaskName}`;
|
|
5697
|
+
if (!this.warnedInvalidMetaIntentResponderKeys.has(warningKey)) {
|
|
5698
|
+
this.warnedInvalidMetaIntentResponderKeys.add(warningKey);
|
|
5699
|
+
this.log(
|
|
5700
|
+
"Skipping non-meta task for meta intent inquiry.",
|
|
5701
|
+
{
|
|
5702
|
+
inquiry,
|
|
5703
|
+
responder: descriptor
|
|
5704
|
+
},
|
|
5705
|
+
"warning",
|
|
5706
|
+
descriptor.serviceName
|
|
5707
|
+
);
|
|
5708
|
+
}
|
|
5709
|
+
return false;
|
|
5710
|
+
});
|
|
5711
|
+
if (responders.length === 0) {
|
|
5712
|
+
return {
|
|
5713
|
+
__inquiryMeta: {
|
|
5714
|
+
inquiry,
|
|
5715
|
+
isMetaInquiry,
|
|
5716
|
+
totalResponders: allResponders.length,
|
|
5717
|
+
eligibleResponders: 0,
|
|
5718
|
+
filteredOutResponders: allResponders.length,
|
|
5719
|
+
responded: 0,
|
|
5720
|
+
failed: 0,
|
|
5721
|
+
timedOut: 0,
|
|
5722
|
+
pending: 0,
|
|
5723
|
+
durationMs: 0,
|
|
5724
|
+
responders: []
|
|
5725
|
+
}
|
|
5726
|
+
};
|
|
5727
|
+
}
|
|
5728
|
+
responders.sort(this.compareInquiryResponders.bind(this));
|
|
5729
|
+
const overallTimeoutMs = options.overallTimeoutMs ?? options.timeout ?? 0;
|
|
5730
|
+
const requireComplete = options.requireComplete ?? false;
|
|
5731
|
+
const perResponderTimeoutMs = options.perResponderTimeoutMs;
|
|
5732
|
+
const startedAt = Date.now();
|
|
5733
|
+
const statuses = [];
|
|
5734
|
+
const statusByTask = /* @__PURE__ */ new Map();
|
|
5735
|
+
for (const responder of responders) {
|
|
5736
|
+
const status = {
|
|
5737
|
+
...responder.descriptor,
|
|
5738
|
+
status: "timed_out",
|
|
5739
|
+
durationMs: 0
|
|
5740
|
+
};
|
|
5741
|
+
statuses.push(status);
|
|
5742
|
+
statusByTask.set(responder.task, status);
|
|
5743
|
+
}
|
|
5744
|
+
const resultsByTask = /* @__PURE__ */ new Map();
|
|
5745
|
+
const resolverTasks = [];
|
|
5746
|
+
const pending = new Set(responders.map((r) => r.task));
|
|
5747
|
+
const startTimeByTask = /* @__PURE__ */ new Map();
|
|
5748
|
+
this.emit("meta.inquiry_broker.inquire", { inquiry, context });
|
|
5749
|
+
return new Promise((resolve, reject) => {
|
|
5750
|
+
let finalized = false;
|
|
5751
|
+
let timeoutId;
|
|
5752
|
+
const finalize = (timedOut) => {
|
|
5753
|
+
if (finalized) return;
|
|
5754
|
+
finalized = true;
|
|
5755
|
+
if (timeoutId) {
|
|
5756
|
+
clearTimeout(timeoutId);
|
|
5757
|
+
timeoutId = void 0;
|
|
5758
|
+
}
|
|
5759
|
+
for (const resolverTask of resolverTasks) {
|
|
5760
|
+
resolverTask.destroy();
|
|
5761
|
+
}
|
|
5762
|
+
if (timedOut && pending.size > 0) {
|
|
5763
|
+
for (const task of pending) {
|
|
5764
|
+
const status = statusByTask.get(task);
|
|
5765
|
+
if (!status) continue;
|
|
5766
|
+
status.status = "timed_out";
|
|
5767
|
+
status.durationMs = Date.now() - (startTimeByTask.get(task) ?? startedAt);
|
|
5768
|
+
}
|
|
5769
|
+
}
|
|
5770
|
+
const fulfilledContexts = responders.filter((responder) => resultsByTask.has(responder.task)).map((responder) => resultsByTask.get(responder.task));
|
|
5771
|
+
const mergedContext = mergeInquiryContexts(fulfilledContexts);
|
|
5772
|
+
const inquiryMeta = this.buildInquirySummary(
|
|
5773
|
+
inquiry,
|
|
5774
|
+
startedAt,
|
|
5775
|
+
statuses,
|
|
5776
|
+
allResponders.length
|
|
5777
|
+
);
|
|
5778
|
+
const responseContext = {
|
|
5779
|
+
...mergedContext,
|
|
5780
|
+
__inquiryMeta: inquiryMeta
|
|
5781
|
+
};
|
|
5782
|
+
if (requireComplete && (timedOut || inquiryMeta.failed > 0 || inquiryMeta.timedOut > 0 || inquiryMeta.pending > 0)) {
|
|
5783
|
+
reject({
|
|
5784
|
+
...responseContext,
|
|
5785
|
+
__error: `Inquiry '${inquiry}' did not complete successfully`,
|
|
5786
|
+
errored: true
|
|
5787
|
+
});
|
|
5788
|
+
return;
|
|
5789
|
+
}
|
|
5790
|
+
resolve(responseContext);
|
|
5791
|
+
};
|
|
5792
|
+
if (overallTimeoutMs > 0) {
|
|
5793
|
+
timeoutId = setTimeout(() => finalize(true), overallTimeoutMs);
|
|
5794
|
+
}
|
|
5795
|
+
for (const responder of responders) {
|
|
5796
|
+
const { task, descriptor } = responder;
|
|
5797
|
+
const inquiryId = (0, import_uuid3.v4)();
|
|
5798
|
+
startTimeByTask.set(task, Date.now());
|
|
5799
|
+
const resolverTask = this.createEphemeralMetaTask(
|
|
5800
|
+
`Resolve inquiry ${inquiry} for ${descriptor.localTaskName}`,
|
|
5801
|
+
(resultCtx) => {
|
|
5802
|
+
if (finalized) {
|
|
5803
|
+
return;
|
|
5804
|
+
}
|
|
5805
|
+
pending.delete(task);
|
|
5806
|
+
const status = statusByTask.get(task);
|
|
5807
|
+
if (status) {
|
|
5808
|
+
status.durationMs = Date.now() - (startTimeByTask.get(task) ?? startedAt);
|
|
5809
|
+
if (resultCtx?.errored || resultCtx?.failed) {
|
|
5810
|
+
status.status = "failed";
|
|
5811
|
+
status.error = String(
|
|
5812
|
+
resultCtx?.__error ?? resultCtx?.error ?? "Inquiry responder failed"
|
|
5813
|
+
);
|
|
5814
|
+
} else {
|
|
5815
|
+
status.status = "fulfilled";
|
|
5816
|
+
resultsByTask.set(task, resultCtx);
|
|
5817
|
+
}
|
|
5818
|
+
}
|
|
5819
|
+
if (pending.size === 0) {
|
|
5820
|
+
finalize(false);
|
|
5821
|
+
}
|
|
5822
|
+
},
|
|
5823
|
+
"Resolves distributed inquiry responder result",
|
|
5824
|
+
{ register: false }
|
|
5825
|
+
).doOn(`meta.node.graph_completed:${inquiryId}`);
|
|
5826
|
+
resolverTasks.push(resolverTask);
|
|
5827
|
+
const executionContext = {
|
|
5828
|
+
...context,
|
|
5829
|
+
__routineExecId: inquiryId,
|
|
5830
|
+
__isInquiry: true
|
|
5831
|
+
};
|
|
5832
|
+
if (perResponderTimeoutMs !== void 0) {
|
|
5833
|
+
executionContext.__timeout = perResponderTimeoutMs;
|
|
5834
|
+
}
|
|
5835
|
+
if (task.isMeta) {
|
|
5836
|
+
this.metaRunner?.run(task, executionContext);
|
|
5837
|
+
} else {
|
|
5838
|
+
this.runner?.run(task, executionContext);
|
|
5839
|
+
}
|
|
5840
|
+
}
|
|
5841
|
+
});
|
|
4786
5842
|
}
|
|
4787
5843
|
/**
|
|
4788
5844
|
* Executes the given task or graph routine within the provided context using the configured runner.
|
|
@@ -5819,6 +6875,7 @@ var CadenzaService = class {
|
|
|
5819
6875
|
};
|
|
5820
6876
|
CadenzaService.isBootstrapped = false;
|
|
5821
6877
|
CadenzaService.serviceCreated = false;
|
|
6878
|
+
CadenzaService.warnedInvalidMetaIntentResponderKeys = /* @__PURE__ */ new Set();
|
|
5822
6879
|
|
|
5823
6880
|
// src/index.ts
|
|
5824
6881
|
var import_core4 = require("@cadenza.io/core");
|