@bian-womp/spark-graph 0.3.16 → 0.3.18
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/lib/cjs/index.cjs +306 -119
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/index.d.ts +1 -0
- package/lib/cjs/src/index.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/HandleResolver.d.ts +2 -10
- package/lib/cjs/src/runtime/components/HandleResolver.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/NodeExecutor.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/RunContextManager.d.ts +7 -1
- package/lib/cjs/src/runtime/components/RunContextManager.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/interfaces.d.ts +0 -2
- package/lib/cjs/src/runtime/components/interfaces.d.ts.map +1 -1
- package/lib/cjs/src/runtime/utils.d.ts +51 -0
- package/lib/cjs/src/runtime/utils.d.ts.map +1 -1
- package/lib/esm/index.js +306 -120
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/index.d.ts +1 -0
- package/lib/esm/src/index.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/HandleResolver.d.ts +2 -10
- package/lib/esm/src/runtime/components/HandleResolver.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/NodeExecutor.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/RunContextManager.d.ts +7 -1
- package/lib/esm/src/runtime/components/RunContextManager.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/interfaces.d.ts +0 -2
- package/lib/esm/src/runtime/components/interfaces.d.ts.map +1 -1
- package/lib/esm/src/runtime/utils.d.ts +51 -0
- package/lib/esm/src/runtime/utils.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/esm/index.js
CHANGED
|
@@ -930,15 +930,166 @@ class EventEmitter {
|
|
|
930
930
|
}
|
|
931
931
|
}
|
|
932
932
|
|
|
933
|
+
const LOG_LEVEL_VALUES = {
|
|
934
|
+
debug: 0,
|
|
935
|
+
info: 1,
|
|
936
|
+
warn: 2,
|
|
937
|
+
error: 3,
|
|
938
|
+
silent: 4,
|
|
939
|
+
};
|
|
940
|
+
|
|
941
|
+
/**
|
|
942
|
+
* Shared utility functions for runtime components
|
|
943
|
+
*/
|
|
944
|
+
/**
|
|
945
|
+
* Type guard to check if a value is a Promise
|
|
946
|
+
*/
|
|
947
|
+
function isPromise(value) {
|
|
948
|
+
return !!value && typeof value.then === "function";
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Unwrap a value that might be a Promise
|
|
952
|
+
*/
|
|
953
|
+
async function unwrapMaybePromise(value) {
|
|
954
|
+
return isPromise(value) ? await value : value;
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Shallow/deep-ish equality check to avoid unnecessary runs on identical values
|
|
958
|
+
*/
|
|
959
|
+
function valuesEqual(a, b) {
|
|
960
|
+
if (a === b)
|
|
961
|
+
return true;
|
|
962
|
+
if (typeof a !== typeof b)
|
|
963
|
+
return false;
|
|
964
|
+
if (a && b && typeof a === "object") {
|
|
965
|
+
try {
|
|
966
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
967
|
+
}
|
|
968
|
+
catch {
|
|
969
|
+
return false;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
return false;
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* A reusable logger class that supports configurable log levels and prefixes.
|
|
976
|
+
* Can be instantiated with a default log level and optionally override per call.
|
|
977
|
+
*/
|
|
978
|
+
class LevelLogger {
|
|
979
|
+
constructor(defaultLevel = "info", prefix = "") {
|
|
980
|
+
this.defaultLevel = defaultLevel;
|
|
981
|
+
this.prefix = prefix;
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Sets the prefix for log messages
|
|
985
|
+
*/
|
|
986
|
+
setPrefix(prefix) {
|
|
987
|
+
this.prefix = prefix;
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Gets the current prefix
|
|
991
|
+
*/
|
|
992
|
+
getPrefix() {
|
|
993
|
+
return this.prefix;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Sets the default log level for this logger instance
|
|
997
|
+
*/
|
|
998
|
+
setLevel(level) {
|
|
999
|
+
this.defaultLevel = level;
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Gets the current default log level
|
|
1003
|
+
*/
|
|
1004
|
+
getLevel() {
|
|
1005
|
+
return this.defaultLevel;
|
|
1006
|
+
}
|
|
1007
|
+
getLevelValue() {
|
|
1008
|
+
return LevelLogger.levelValues[this.defaultLevel];
|
|
1009
|
+
}
|
|
1010
|
+
/**
|
|
1011
|
+
* Logs a debug message
|
|
1012
|
+
*/
|
|
1013
|
+
debug(message, context, overrideLevel) {
|
|
1014
|
+
this.log("debug", message, context, overrideLevel);
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Logs an info message
|
|
1018
|
+
*/
|
|
1019
|
+
info(message, context, overrideLevel) {
|
|
1020
|
+
this.log("info", message, context, overrideLevel);
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Logs a warning message
|
|
1024
|
+
*/
|
|
1025
|
+
warn(message, context, overrideLevel) {
|
|
1026
|
+
this.log("warn", message, context, overrideLevel);
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Logs an error message
|
|
1030
|
+
*/
|
|
1031
|
+
error(message, context, overrideLevel) {
|
|
1032
|
+
this.log("error", message, context, overrideLevel);
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Core logging method that respects the log level and applies prefix
|
|
1036
|
+
*/
|
|
1037
|
+
log(requestedLevel, message, context, overrideLevel) {
|
|
1038
|
+
const effectiveLevel = overrideLevel ?? this.defaultLevel;
|
|
1039
|
+
// Silent level suppresses all logs
|
|
1040
|
+
if (effectiveLevel === "silent") {
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
const requestedValue = LevelLogger.levelValues[requestedLevel] ?? 1;
|
|
1044
|
+
const effectiveValue = LevelLogger.levelValues[effectiveLevel] ?? 1;
|
|
1045
|
+
// Only log if the requested level is >= effective level
|
|
1046
|
+
if (requestedValue >= effectiveValue) {
|
|
1047
|
+
const contextStr = context
|
|
1048
|
+
? ` ${Object.entries(context)
|
|
1049
|
+
.map(([k, v]) => `${k}=${JSON.stringify(v)}`)
|
|
1050
|
+
.join(" ")}`
|
|
1051
|
+
: "";
|
|
1052
|
+
const prefixedMessage = this.prefix
|
|
1053
|
+
? `${this.prefix} ${message}${contextStr}`
|
|
1054
|
+
: `${message}${contextStr}`;
|
|
1055
|
+
switch (requestedLevel) {
|
|
1056
|
+
case "debug":
|
|
1057
|
+
console.info(prefixedMessage);
|
|
1058
|
+
break;
|
|
1059
|
+
case "info":
|
|
1060
|
+
console.info(prefixedMessage);
|
|
1061
|
+
break;
|
|
1062
|
+
case "warn":
|
|
1063
|
+
console.warn(prefixedMessage);
|
|
1064
|
+
break;
|
|
1065
|
+
case "error":
|
|
1066
|
+
console.error(prefixedMessage);
|
|
1067
|
+
break;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Maps log levels to numeric values for comparison
|
|
1074
|
+
*/
|
|
1075
|
+
LevelLogger.levelValues = LOG_LEVEL_VALUES;
|
|
1076
|
+
|
|
933
1077
|
/**
|
|
934
1078
|
* RunContextManager component - manages run-context lifecycle
|
|
935
1079
|
*/
|
|
936
1080
|
class RunContextManager {
|
|
937
|
-
constructor(graph) {
|
|
1081
|
+
constructor(graph, logLevel) {
|
|
938
1082
|
this.graph = graph;
|
|
939
1083
|
this.runContexts = new Map();
|
|
940
1084
|
this.runContextCounter = 0;
|
|
941
1085
|
this.graph = graph;
|
|
1086
|
+
this.logger = new LevelLogger(logLevel ?? "info", "[RunContextManager]");
|
|
1087
|
+
}
|
|
1088
|
+
/**
|
|
1089
|
+
* Set the log level for this manager
|
|
1090
|
+
*/
|
|
1091
|
+
setLogLevel(logLevel) {
|
|
1092
|
+
this.logger.setLevel(logLevel);
|
|
942
1093
|
}
|
|
943
1094
|
/**
|
|
944
1095
|
* Create a new run-context for runFromHere
|
|
@@ -957,6 +1108,12 @@ class RunContextManager {
|
|
|
957
1108
|
resolve,
|
|
958
1109
|
};
|
|
959
1110
|
this.runContexts.set(id, ctx);
|
|
1111
|
+
this.logger.info("create-run-context", {
|
|
1112
|
+
id,
|
|
1113
|
+
startNodeId,
|
|
1114
|
+
skipPropagateValues: ctx.skipPropagateValues,
|
|
1115
|
+
propagate: ctx.propagate,
|
|
1116
|
+
});
|
|
960
1117
|
return id;
|
|
961
1118
|
}
|
|
962
1119
|
/**
|
|
@@ -979,41 +1136,101 @@ class RunContextManager {
|
|
|
979
1136
|
}
|
|
980
1137
|
startNodeRun(id, nodeId) {
|
|
981
1138
|
const ctx = this.runContexts.get(id);
|
|
982
|
-
if (!ctx)
|
|
1139
|
+
if (!ctx) {
|
|
1140
|
+
this.logger.debug("start-node-run-context-not-found", {
|
|
1141
|
+
runContextId: id,
|
|
1142
|
+
nodeId,
|
|
1143
|
+
});
|
|
983
1144
|
return;
|
|
1145
|
+
}
|
|
984
1146
|
ctx.pendingNodes++;
|
|
1147
|
+
this.logger.debug("start-node-run", {
|
|
1148
|
+
runContextId: id,
|
|
1149
|
+
nodeId,
|
|
1150
|
+
pendingNodes: ctx.pendingNodes,
|
|
1151
|
+
});
|
|
985
1152
|
}
|
|
986
1153
|
finishNodeRun(id, nodeId) {
|
|
987
1154
|
const ctx = this.runContexts.get(id);
|
|
988
|
-
if (!ctx)
|
|
1155
|
+
if (!ctx) {
|
|
1156
|
+
this.logger.debug("finish-node-run-context-not-found", {
|
|
1157
|
+
runContextId: id,
|
|
1158
|
+
nodeId,
|
|
1159
|
+
});
|
|
989
1160
|
return;
|
|
1161
|
+
}
|
|
990
1162
|
ctx.pendingNodes--;
|
|
1163
|
+
this.logger.debug("finish-node-run", {
|
|
1164
|
+
runContextId: id,
|
|
1165
|
+
nodeId,
|
|
1166
|
+
pendingNodes: ctx.pendingNodes,
|
|
1167
|
+
});
|
|
991
1168
|
this.finishRunContextIfPossible(id);
|
|
992
1169
|
}
|
|
993
1170
|
startEdgeConversion(id, edgeId) {
|
|
994
1171
|
const ctx = this.runContexts.get(id);
|
|
995
|
-
if (!ctx)
|
|
1172
|
+
if (!ctx) {
|
|
1173
|
+
this.logger.debug("start-edge-conversion-context-not-found", {
|
|
1174
|
+
runContextId: id,
|
|
1175
|
+
edgeId,
|
|
1176
|
+
});
|
|
996
1177
|
return;
|
|
1178
|
+
}
|
|
997
1179
|
ctx.pendingEdges++;
|
|
1180
|
+
this.logger.debug("start-edge-conversion", {
|
|
1181
|
+
runContextId: id,
|
|
1182
|
+
edgeId,
|
|
1183
|
+
pendingEdges: ctx.pendingEdges,
|
|
1184
|
+
});
|
|
998
1185
|
}
|
|
999
1186
|
finishEdgeConversion(id, edgeId) {
|
|
1000
1187
|
const ctx = this.runContexts.get(id);
|
|
1001
|
-
if (!ctx)
|
|
1188
|
+
if (!ctx) {
|
|
1189
|
+
this.logger.debug("finish-edge-conversion-context-not-found", {
|
|
1190
|
+
runContextId: id,
|
|
1191
|
+
edgeId,
|
|
1192
|
+
});
|
|
1002
1193
|
return;
|
|
1194
|
+
}
|
|
1003
1195
|
ctx.pendingEdges--;
|
|
1196
|
+
this.logger.debug("finish-edge-conversion", {
|
|
1197
|
+
runContextId: id,
|
|
1198
|
+
edgeId,
|
|
1199
|
+
pendingEdges: ctx.pendingEdges,
|
|
1200
|
+
});
|
|
1004
1201
|
this.finishRunContextIfPossible(id);
|
|
1005
1202
|
}
|
|
1006
1203
|
startHandleResolution(id, nodeId) {
|
|
1007
1204
|
const ctx = this.runContexts.get(id);
|
|
1008
|
-
if (!ctx)
|
|
1205
|
+
if (!ctx) {
|
|
1206
|
+
this.logger.debug("start-handle-resolution-context-not-found", {
|
|
1207
|
+
runContextId: id,
|
|
1208
|
+
nodeId,
|
|
1209
|
+
});
|
|
1009
1210
|
return;
|
|
1211
|
+
}
|
|
1010
1212
|
ctx.pendingResolvers++;
|
|
1213
|
+
this.logger.debug("start-handle-resolution", {
|
|
1214
|
+
runContextId: id,
|
|
1215
|
+
nodeId,
|
|
1216
|
+
pendingResolvers: ctx.pendingResolvers,
|
|
1217
|
+
});
|
|
1011
1218
|
}
|
|
1012
1219
|
finishHandleResolution(id, nodeId) {
|
|
1013
1220
|
const ctx = this.runContexts.get(id);
|
|
1014
|
-
if (!ctx)
|
|
1221
|
+
if (!ctx) {
|
|
1222
|
+
this.logger.debug("finish-handle-resolution-context-not-found", {
|
|
1223
|
+
runContextId: id,
|
|
1224
|
+
nodeId,
|
|
1225
|
+
});
|
|
1015
1226
|
return;
|
|
1227
|
+
}
|
|
1016
1228
|
ctx.pendingResolvers--;
|
|
1229
|
+
this.logger.debug("finish-handle-resolution", {
|
|
1230
|
+
runContextId: id,
|
|
1231
|
+
nodeId,
|
|
1232
|
+
pendingResolvers: ctx.pendingResolvers,
|
|
1233
|
+
});
|
|
1017
1234
|
this.finishRunContextIfPossible(id);
|
|
1018
1235
|
}
|
|
1019
1236
|
/**
|
|
@@ -1021,13 +1238,22 @@ class RunContextManager {
|
|
|
1021
1238
|
*/
|
|
1022
1239
|
finishRunContextIfPossible(id) {
|
|
1023
1240
|
const ctx = this.runContexts.get(id);
|
|
1024
|
-
if (!ctx)
|
|
1241
|
+
if (!ctx) {
|
|
1242
|
+
this.logger.debug("finish-run-context-not-found", {
|
|
1243
|
+
runContextId: id,
|
|
1244
|
+
});
|
|
1025
1245
|
return;
|
|
1246
|
+
}
|
|
1026
1247
|
if (ctx.pendingNodes > 0 ||
|
|
1027
1248
|
ctx.pendingEdges > 0 ||
|
|
1028
1249
|
ctx.pendingResolvers > 0) {
|
|
1029
1250
|
return; // Still has pending work
|
|
1030
1251
|
}
|
|
1252
|
+
this.logger.info("finish-run-context", {
|
|
1253
|
+
runContextId: id,
|
|
1254
|
+
startNodes: Array.from(ctx.startNodes),
|
|
1255
|
+
cancelledNodes: Array.from(ctx.cancelledNodes),
|
|
1256
|
+
});
|
|
1031
1257
|
// Clean up activeRunContexts from all nodes
|
|
1032
1258
|
this.graph.forEachNode((node) => {
|
|
1033
1259
|
this.graph.removeNodeRunContextId(node.nodeId, id);
|
|
@@ -1065,6 +1291,12 @@ class RunContextManager {
|
|
|
1065
1291
|
});
|
|
1066
1292
|
}
|
|
1067
1293
|
}
|
|
1294
|
+
this.logger.debug("cancel-node-in-run-contexts", {
|
|
1295
|
+
nodeId,
|
|
1296
|
+
includeDownstream,
|
|
1297
|
+
cancelledNodes: Array.from(toCancel),
|
|
1298
|
+
affectedRunContexts: Array.from(this.runContexts.keys()),
|
|
1299
|
+
});
|
|
1068
1300
|
// Mark nodes as cancelled in all run-contexts
|
|
1069
1301
|
for (const ctx of this.runContexts.values()) {
|
|
1070
1302
|
for (const id of toCancel) {
|
|
@@ -1080,6 +1312,11 @@ class RunContextManager {
|
|
|
1080
1312
|
* Resolve all pending run-context promises (for cleanup)
|
|
1081
1313
|
*/
|
|
1082
1314
|
resolveAll() {
|
|
1315
|
+
const count = this.runContexts.size;
|
|
1316
|
+
this.logger.info("resolve-all-run-contexts", {
|
|
1317
|
+
count,
|
|
1318
|
+
runContextIds: Array.from(this.runContexts.keys()),
|
|
1319
|
+
});
|
|
1083
1320
|
for (const ctx of this.runContexts.values()) {
|
|
1084
1321
|
if (ctx.resolve)
|
|
1085
1322
|
ctx.resolve();
|
|
@@ -1089,52 +1326,12 @@ class RunContextManager {
|
|
|
1089
1326
|
* Clear all run-contexts
|
|
1090
1327
|
*/
|
|
1091
1328
|
clear() {
|
|
1329
|
+
const count = this.runContexts.size;
|
|
1330
|
+
this.logger.info("clear-all-run-contexts", { count });
|
|
1092
1331
|
this.runContexts.clear();
|
|
1093
1332
|
}
|
|
1094
1333
|
}
|
|
1095
1334
|
|
|
1096
|
-
const LOG_LEVEL_VALUES = {
|
|
1097
|
-
debug: 0,
|
|
1098
|
-
info: 1,
|
|
1099
|
-
warn: 2,
|
|
1100
|
-
error: 3,
|
|
1101
|
-
silent: 4,
|
|
1102
|
-
};
|
|
1103
|
-
|
|
1104
|
-
/**
|
|
1105
|
-
* Shared utility functions for runtime components
|
|
1106
|
-
*/
|
|
1107
|
-
/**
|
|
1108
|
-
* Type guard to check if a value is a Promise
|
|
1109
|
-
*/
|
|
1110
|
-
function isPromise(value) {
|
|
1111
|
-
return !!value && typeof value.then === "function";
|
|
1112
|
-
}
|
|
1113
|
-
/**
|
|
1114
|
-
* Unwrap a value that might be a Promise
|
|
1115
|
-
*/
|
|
1116
|
-
async function unwrapMaybePromise(value) {
|
|
1117
|
-
return isPromise(value) ? await value : value;
|
|
1118
|
-
}
|
|
1119
|
-
/**
|
|
1120
|
-
* Shallow/deep-ish equality check to avoid unnecessary runs on identical values
|
|
1121
|
-
*/
|
|
1122
|
-
function valuesEqual(a, b) {
|
|
1123
|
-
if (a === b)
|
|
1124
|
-
return true;
|
|
1125
|
-
if (typeof a !== typeof b)
|
|
1126
|
-
return false;
|
|
1127
|
-
if (a && b && typeof a === "object") {
|
|
1128
|
-
try {
|
|
1129
|
-
return JSON.stringify(a) === JSON.stringify(b);
|
|
1130
|
-
}
|
|
1131
|
-
catch {
|
|
1132
|
-
return false;
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
return false;
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
1335
|
function tryHandleResolving(def, registry, environment) {
|
|
1139
1336
|
const out = new Map();
|
|
1140
1337
|
const pending = new Set();
|
|
@@ -1333,7 +1530,7 @@ class HandleResolver {
|
|
|
1333
1530
|
this.recomputeTokenByNode = new Map();
|
|
1334
1531
|
this.environment = {};
|
|
1335
1532
|
this.pendingResolutions = new Map();
|
|
1336
|
-
this.
|
|
1533
|
+
this.isRecomputing = new Map();
|
|
1337
1534
|
this.environment = environment ?? {};
|
|
1338
1535
|
}
|
|
1339
1536
|
setRegistry(registry) {
|
|
@@ -1342,33 +1539,12 @@ class HandleResolver {
|
|
|
1342
1539
|
setEnvironment(environment) {
|
|
1343
1540
|
this.environment = environment;
|
|
1344
1541
|
}
|
|
1345
|
-
/**
|
|
1346
|
-
* Check if handle resolution is pending for a node
|
|
1347
|
-
*/
|
|
1348
|
-
isResolvingHandles(nodeId) {
|
|
1349
|
-
return this.pendingResolutions.has(nodeId);
|
|
1350
|
-
}
|
|
1351
1542
|
/**
|
|
1352
1543
|
* Get the promise for pending handle resolution, or null if none
|
|
1353
1544
|
*/
|
|
1354
1545
|
getPendingResolution(nodeId) {
|
|
1355
1546
|
return this.pendingResolutions.get(nodeId) || null;
|
|
1356
1547
|
}
|
|
1357
|
-
/**
|
|
1358
|
-
* Track additional run contexts for a pending resolution
|
|
1359
|
-
*/
|
|
1360
|
-
trackRunContextsForPendingResolution(nodeId, runContextIds) {
|
|
1361
|
-
if (!this.pendingResolutions.has(nodeId))
|
|
1362
|
-
return;
|
|
1363
|
-
const tracked = this.pendingResolutionRunContexts.get(nodeId) ?? new Set();
|
|
1364
|
-
for (const runContextId of runContextIds) {
|
|
1365
|
-
if (!tracked.has(runContextId)) {
|
|
1366
|
-
this.runContextManager.startHandleResolution(runContextId, nodeId);
|
|
1367
|
-
tracked.add(runContextId);
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
this.pendingResolutionRunContexts.set(nodeId, tracked);
|
|
1371
|
-
}
|
|
1372
1548
|
/**
|
|
1373
1549
|
* Schedule async recomputation of handles for a node
|
|
1374
1550
|
*/
|
|
@@ -1379,27 +1555,43 @@ class HandleResolver {
|
|
|
1379
1555
|
const node = this.graph.getNode(nodeId);
|
|
1380
1556
|
if (!node)
|
|
1381
1557
|
return;
|
|
1558
|
+
// If already recomputing, increment token to mark that a new recompute is needed
|
|
1559
|
+
// but don't schedule another concurrent execution
|
|
1560
|
+
if (this.isRecomputing.get(nodeId)) {
|
|
1561
|
+
const currentToken = this.recomputeTokenByNode.get(nodeId) ?? 0;
|
|
1562
|
+
this.recomputeTokenByNode.set(nodeId, currentToken + 1);
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1382
1565
|
// Track resolver start for all active run-contexts
|
|
1383
1566
|
const activeRunContextIds = this.graph.getNodeRunContextIds(nodeId);
|
|
1384
|
-
const trackedRunContextIds = new Set(activeRunContextIds);
|
|
1385
1567
|
if (activeRunContextIds.size > 0) {
|
|
1386
1568
|
for (const runContextId of activeRunContextIds) {
|
|
1387
1569
|
this.runContextManager.startHandleResolution(runContextId, nodeId);
|
|
1388
1570
|
}
|
|
1389
1571
|
}
|
|
1572
|
+
// Mark as recomputing
|
|
1573
|
+
this.isRecomputing.set(nodeId, true);
|
|
1574
|
+
// Capture initial token before starting (will be incremented in recomputeHandlesForNode)
|
|
1575
|
+
const initialToken = this.recomputeTokenByNode.get(nodeId) ?? 0;
|
|
1390
1576
|
// Create and track the resolution promise
|
|
1391
1577
|
const resolutionPromise = new Promise((resolve) => {
|
|
1392
1578
|
setTimeout(async () => {
|
|
1393
|
-
|
|
1394
|
-
const allTracked = this.pendingResolutionRunContexts.get(nodeId) ?? trackedRunContextIds;
|
|
1395
|
-
await this.recomputeHandlesForNode(nodeId, allTracked.size > 0 ? allTracked : undefined);
|
|
1579
|
+
await this.recomputeHandlesForNode(nodeId, activeRunContextIds);
|
|
1396
1580
|
this.pendingResolutions.delete(nodeId);
|
|
1397
|
-
this.
|
|
1581
|
+
this.isRecomputing.delete(nodeId);
|
|
1582
|
+
// Check if a new recompute was requested while we were running
|
|
1583
|
+
// (token was incremented by another scheduleRecomputeHandles call)
|
|
1584
|
+
const finalToken = this.recomputeTokenByNode.get(nodeId) ?? 0;
|
|
1585
|
+
// After recomputeHandlesForNode, token should be initialToken + 1
|
|
1586
|
+
// If finalToken > initialToken + 1, a new recompute was requested
|
|
1587
|
+
if (finalToken > initialToken + 1) {
|
|
1588
|
+
// A new recompute was requested, schedule it now
|
|
1589
|
+
this.scheduleRecomputeHandles(nodeId);
|
|
1590
|
+
}
|
|
1398
1591
|
resolve();
|
|
1399
1592
|
}, 0);
|
|
1400
1593
|
});
|
|
1401
1594
|
this.pendingResolutions.set(nodeId, resolutionPromise);
|
|
1402
|
-
this.pendingResolutionRunContexts.set(nodeId, trackedRunContextIds);
|
|
1403
1595
|
}
|
|
1404
1596
|
// Update resolved handles for a single node and refresh edge converters/types that touch it
|
|
1405
1597
|
updateNodeHandles(nodeId, handles) {
|
|
@@ -2017,33 +2209,23 @@ class NodeExecutor {
|
|
|
2017
2209
|
progress: Math.max(0, Math.min(1, Number(p) || 0)),
|
|
2018
2210
|
});
|
|
2019
2211
|
});
|
|
2020
|
-
// Create log function that respects node's logLevel
|
|
2212
|
+
// Create log function that respects node's logLevel using LevelLogger
|
|
2213
|
+
const nodeLogLevel = node.logLevel ?? "info";
|
|
2214
|
+
const logger = new LevelLogger(nodeLogLevel, `[node:${runId || nodeId}:${node.typeId}]`);
|
|
2021
2215
|
const log = (level, message, context) => {
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
console.info(fullMessage);
|
|
2036
|
-
break;
|
|
2037
|
-
case "info":
|
|
2038
|
-
console.info(fullMessage);
|
|
2039
|
-
break;
|
|
2040
|
-
case "warn":
|
|
2041
|
-
console.warn(fullMessage);
|
|
2042
|
-
break;
|
|
2043
|
-
case "error":
|
|
2044
|
-
console.error(fullMessage);
|
|
2045
|
-
break;
|
|
2046
|
-
}
|
|
2216
|
+
switch (level) {
|
|
2217
|
+
case "debug":
|
|
2218
|
+
logger.debug(message, context);
|
|
2219
|
+
break;
|
|
2220
|
+
case "info":
|
|
2221
|
+
logger.info(message, context);
|
|
2222
|
+
break;
|
|
2223
|
+
case "warn":
|
|
2224
|
+
logger.warn(message, context);
|
|
2225
|
+
break;
|
|
2226
|
+
case "error":
|
|
2227
|
+
logger.error(message, context);
|
|
2228
|
+
break;
|
|
2047
2229
|
}
|
|
2048
2230
|
};
|
|
2049
2231
|
return {
|
|
@@ -2115,23 +2297,27 @@ class NodeExecutor {
|
|
|
2115
2297
|
}
|
|
2116
2298
|
// Check if handles are being resolved - wait for resolution before executing
|
|
2117
2299
|
// Do this AFTER setting up run contexts so handle resolution can track them
|
|
2118
|
-
|
|
2119
|
-
|
|
2300
|
+
const pendingResolution = this.handleResolver.getPendingResolution(nodeId);
|
|
2301
|
+
if (pendingResolution) {
|
|
2120
2302
|
if (runContextIds && runContextIds.size > 0) {
|
|
2121
|
-
|
|
2303
|
+
for (const id of runContextIds) {
|
|
2304
|
+
this.runContextManager.startHandleResolution(id, nodeId);
|
|
2305
|
+
}
|
|
2122
2306
|
}
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
//
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2307
|
+
// Wait for resolution to complete, then re-execute
|
|
2308
|
+
pendingResolution.then(() => {
|
|
2309
|
+
// Re-check node still exists and conditions
|
|
2310
|
+
const nodeAfter = this.graph.getNode(nodeId);
|
|
2311
|
+
if (nodeAfter) {
|
|
2312
|
+
this.execute(nodeId, runContextIds);
|
|
2313
|
+
}
|
|
2314
|
+
if (runContextIds && runContextIds.size > 0) {
|
|
2315
|
+
for (const id of runContextIds) {
|
|
2316
|
+
this.runContextManager.finishHandleResolution(id, nodeId);
|
|
2131
2317
|
}
|
|
2132
|
-
}
|
|
2133
|
-
|
|
2134
|
-
|
|
2318
|
+
}
|
|
2319
|
+
});
|
|
2320
|
+
return;
|
|
2135
2321
|
}
|
|
2136
2322
|
// Handle debouncing
|
|
2137
2323
|
const now = Date.now();
|
|
@@ -2572,7 +2758,7 @@ class GraphRuntime {
|
|
|
2572
2758
|
// Initialize components
|
|
2573
2759
|
this.graph = new Graph();
|
|
2574
2760
|
this.eventEmitter = new EventEmitter();
|
|
2575
|
-
this.runContextManager = new RunContextManager(this.graph);
|
|
2761
|
+
this.runContextManager = new RunContextManager(this.graph, "debug");
|
|
2576
2762
|
this.handleResolver = new HandleResolver(this.graph, this.eventEmitter, this.runContextManager, this);
|
|
2577
2763
|
this.edgePropagator = new EdgePropagator(this.graph, this.eventEmitter, this.runContextManager, this.handleResolver, this);
|
|
2578
2764
|
// Create NodeExecutor with EdgePropagator and HandleResolver
|
|
@@ -5700,5 +5886,5 @@ function buildValueConverter(config) {
|
|
|
5700
5886
|
};
|
|
5701
5887
|
}
|
|
5702
5888
|
|
|
5703
|
-
export { BaseCompareOperation, BaseLogicOperation, BaseMathOperation, CompositeCategory, ComputeCategory, GraphBuilder, GraphRuntime, LocalEngine, Registry, buildValueConverter, computeGraphCenter, createAsyncGraphDef, createAsyncGraphRegistry, createProgressGraphDef, createProgressGraphRegistry, createSimpleGraphDef, createSimpleGraphRegistry, createValidationGraphDef, createValidationGraphRegistry, findMatchingPaths, generateId, getInputHandleMetadata, getInputTypeId, getTypedOutputTypeId, getTypedOutputValue, getValueAtPath, installLogging, isInputPrivate, isTypedOutput, mergeGraphDefinitions, mergeInputHandleDescriptors, mergeInputsOutputs, mergeRuntimeState, mergeSnapshotData, offsetImportedPositions, parseJsonPath, registerDelayNode, registerProgressNodes, setValueAtPath, setValueAtPathWithCreation, typed };
|
|
5889
|
+
export { BaseCompareOperation, BaseLogicOperation, BaseMathOperation, CompositeCategory, ComputeCategory, GraphBuilder, GraphRuntime, LevelLogger, LocalEngine, Registry, buildValueConverter, computeGraphCenter, createAsyncGraphDef, createAsyncGraphRegistry, createProgressGraphDef, createProgressGraphRegistry, createSimpleGraphDef, createSimpleGraphRegistry, createValidationGraphDef, createValidationGraphRegistry, findMatchingPaths, generateId, getInputHandleMetadata, getInputTypeId, getTypedOutputTypeId, getTypedOutputValue, getValueAtPath, installLogging, isInputPrivate, isTypedOutput, mergeGraphDefinitions, mergeInputHandleDescriptors, mergeInputsOutputs, mergeRuntimeState, mergeSnapshotData, offsetImportedPositions, parseJsonPath, registerDelayNode, registerProgressNodes, setValueAtPath, setValueAtPathWithCreation, typed };
|
|
5704
5890
|
//# sourceMappingURL=index.js.map
|