@bian-womp/spark-graph 0.3.16 → 0.3.17
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 +265 -77
- 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/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/utils.d.ts +51 -0
- package/lib/cjs/src/runtime/utils.d.ts.map +1 -1
- package/lib/esm/index.js +265 -78
- 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/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/utils.d.ts +51 -0
- package/lib/esm/src/runtime/utils.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/cjs/index.cjs
CHANGED
|
@@ -932,15 +932,166 @@ class EventEmitter {
|
|
|
932
932
|
}
|
|
933
933
|
}
|
|
934
934
|
|
|
935
|
+
const LOG_LEVEL_VALUES = {
|
|
936
|
+
debug: 0,
|
|
937
|
+
info: 1,
|
|
938
|
+
warn: 2,
|
|
939
|
+
error: 3,
|
|
940
|
+
silent: 4,
|
|
941
|
+
};
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* Shared utility functions for runtime components
|
|
945
|
+
*/
|
|
946
|
+
/**
|
|
947
|
+
* Type guard to check if a value is a Promise
|
|
948
|
+
*/
|
|
949
|
+
function isPromise(value) {
|
|
950
|
+
return !!value && typeof value.then === "function";
|
|
951
|
+
}
|
|
952
|
+
/**
|
|
953
|
+
* Unwrap a value that might be a Promise
|
|
954
|
+
*/
|
|
955
|
+
async function unwrapMaybePromise(value) {
|
|
956
|
+
return isPromise(value) ? await value : value;
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Shallow/deep-ish equality check to avoid unnecessary runs on identical values
|
|
960
|
+
*/
|
|
961
|
+
function valuesEqual(a, b) {
|
|
962
|
+
if (a === b)
|
|
963
|
+
return true;
|
|
964
|
+
if (typeof a !== typeof b)
|
|
965
|
+
return false;
|
|
966
|
+
if (a && b && typeof a === "object") {
|
|
967
|
+
try {
|
|
968
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
969
|
+
}
|
|
970
|
+
catch {
|
|
971
|
+
return false;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return false;
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* A reusable logger class that supports configurable log levels and prefixes.
|
|
978
|
+
* Can be instantiated with a default log level and optionally override per call.
|
|
979
|
+
*/
|
|
980
|
+
class LevelLogger {
|
|
981
|
+
constructor(defaultLevel = "info", prefix = "") {
|
|
982
|
+
this.defaultLevel = defaultLevel;
|
|
983
|
+
this.prefix = prefix;
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* Sets the prefix for log messages
|
|
987
|
+
*/
|
|
988
|
+
setPrefix(prefix) {
|
|
989
|
+
this.prefix = prefix;
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Gets the current prefix
|
|
993
|
+
*/
|
|
994
|
+
getPrefix() {
|
|
995
|
+
return this.prefix;
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* Sets the default log level for this logger instance
|
|
999
|
+
*/
|
|
1000
|
+
setLevel(level) {
|
|
1001
|
+
this.defaultLevel = level;
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Gets the current default log level
|
|
1005
|
+
*/
|
|
1006
|
+
getLevel() {
|
|
1007
|
+
return this.defaultLevel;
|
|
1008
|
+
}
|
|
1009
|
+
getLevelValue() {
|
|
1010
|
+
return LevelLogger.levelValues[this.defaultLevel];
|
|
1011
|
+
}
|
|
1012
|
+
/**
|
|
1013
|
+
* Logs a debug message
|
|
1014
|
+
*/
|
|
1015
|
+
debug(message, context, overrideLevel) {
|
|
1016
|
+
this.log("debug", message, context, overrideLevel);
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Logs an info message
|
|
1020
|
+
*/
|
|
1021
|
+
info(message, context, overrideLevel) {
|
|
1022
|
+
this.log("info", message, context, overrideLevel);
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* Logs a warning message
|
|
1026
|
+
*/
|
|
1027
|
+
warn(message, context, overrideLevel) {
|
|
1028
|
+
this.log("warn", message, context, overrideLevel);
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* Logs an error message
|
|
1032
|
+
*/
|
|
1033
|
+
error(message, context, overrideLevel) {
|
|
1034
|
+
this.log("error", message, context, overrideLevel);
|
|
1035
|
+
}
|
|
1036
|
+
/**
|
|
1037
|
+
* Core logging method that respects the log level and applies prefix
|
|
1038
|
+
*/
|
|
1039
|
+
log(requestedLevel, message, context, overrideLevel) {
|
|
1040
|
+
const effectiveLevel = overrideLevel ?? this.defaultLevel;
|
|
1041
|
+
// Silent level suppresses all logs
|
|
1042
|
+
if (effectiveLevel === "silent") {
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
const requestedValue = LevelLogger.levelValues[requestedLevel] ?? 1;
|
|
1046
|
+
const effectiveValue = LevelLogger.levelValues[effectiveLevel] ?? 1;
|
|
1047
|
+
// Only log if the requested level is >= effective level
|
|
1048
|
+
if (requestedValue >= effectiveValue) {
|
|
1049
|
+
const contextStr = context
|
|
1050
|
+
? ` ${Object.entries(context)
|
|
1051
|
+
.map(([k, v]) => `${k}=${JSON.stringify(v)}`)
|
|
1052
|
+
.join(" ")}`
|
|
1053
|
+
: "";
|
|
1054
|
+
const prefixedMessage = this.prefix
|
|
1055
|
+
? `${this.prefix} ${message}${contextStr}`
|
|
1056
|
+
: `${message}${contextStr}`;
|
|
1057
|
+
switch (requestedLevel) {
|
|
1058
|
+
case "debug":
|
|
1059
|
+
console.info(prefixedMessage);
|
|
1060
|
+
break;
|
|
1061
|
+
case "info":
|
|
1062
|
+
console.info(prefixedMessage);
|
|
1063
|
+
break;
|
|
1064
|
+
case "warn":
|
|
1065
|
+
console.warn(prefixedMessage);
|
|
1066
|
+
break;
|
|
1067
|
+
case "error":
|
|
1068
|
+
console.error(prefixedMessage);
|
|
1069
|
+
break;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
/**
|
|
1075
|
+
* Maps log levels to numeric values for comparison
|
|
1076
|
+
*/
|
|
1077
|
+
LevelLogger.levelValues = LOG_LEVEL_VALUES;
|
|
1078
|
+
|
|
935
1079
|
/**
|
|
936
1080
|
* RunContextManager component - manages run-context lifecycle
|
|
937
1081
|
*/
|
|
938
1082
|
class RunContextManager {
|
|
939
|
-
constructor(graph) {
|
|
1083
|
+
constructor(graph, logLevel) {
|
|
940
1084
|
this.graph = graph;
|
|
941
1085
|
this.runContexts = new Map();
|
|
942
1086
|
this.runContextCounter = 0;
|
|
943
1087
|
this.graph = graph;
|
|
1088
|
+
this.logger = new LevelLogger(logLevel ?? "info", "[RunContextManager]");
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Set the log level for this manager
|
|
1092
|
+
*/
|
|
1093
|
+
setLogLevel(logLevel) {
|
|
1094
|
+
this.logger.setLevel(logLevel);
|
|
944
1095
|
}
|
|
945
1096
|
/**
|
|
946
1097
|
* Create a new run-context for runFromHere
|
|
@@ -959,6 +1110,12 @@ class RunContextManager {
|
|
|
959
1110
|
resolve,
|
|
960
1111
|
};
|
|
961
1112
|
this.runContexts.set(id, ctx);
|
|
1113
|
+
this.logger.info("create-run-context", {
|
|
1114
|
+
id,
|
|
1115
|
+
startNodeId,
|
|
1116
|
+
skipPropagateValues: ctx.skipPropagateValues,
|
|
1117
|
+
propagate: ctx.propagate,
|
|
1118
|
+
});
|
|
962
1119
|
return id;
|
|
963
1120
|
}
|
|
964
1121
|
/**
|
|
@@ -981,41 +1138,101 @@ class RunContextManager {
|
|
|
981
1138
|
}
|
|
982
1139
|
startNodeRun(id, nodeId) {
|
|
983
1140
|
const ctx = this.runContexts.get(id);
|
|
984
|
-
if (!ctx)
|
|
1141
|
+
if (!ctx) {
|
|
1142
|
+
this.logger.debug("start-node-run-context-not-found", {
|
|
1143
|
+
runContextId: id,
|
|
1144
|
+
nodeId,
|
|
1145
|
+
});
|
|
985
1146
|
return;
|
|
1147
|
+
}
|
|
986
1148
|
ctx.pendingNodes++;
|
|
1149
|
+
this.logger.debug("start-node-run", {
|
|
1150
|
+
runContextId: id,
|
|
1151
|
+
nodeId,
|
|
1152
|
+
pendingNodes: ctx.pendingNodes,
|
|
1153
|
+
});
|
|
987
1154
|
}
|
|
988
1155
|
finishNodeRun(id, nodeId) {
|
|
989
1156
|
const ctx = this.runContexts.get(id);
|
|
990
|
-
if (!ctx)
|
|
1157
|
+
if (!ctx) {
|
|
1158
|
+
this.logger.debug("finish-node-run-context-not-found", {
|
|
1159
|
+
runContextId: id,
|
|
1160
|
+
nodeId,
|
|
1161
|
+
});
|
|
991
1162
|
return;
|
|
1163
|
+
}
|
|
992
1164
|
ctx.pendingNodes--;
|
|
1165
|
+
this.logger.debug("finish-node-run", {
|
|
1166
|
+
runContextId: id,
|
|
1167
|
+
nodeId,
|
|
1168
|
+
pendingNodes: ctx.pendingNodes,
|
|
1169
|
+
});
|
|
993
1170
|
this.finishRunContextIfPossible(id);
|
|
994
1171
|
}
|
|
995
1172
|
startEdgeConversion(id, edgeId) {
|
|
996
1173
|
const ctx = this.runContexts.get(id);
|
|
997
|
-
if (!ctx)
|
|
1174
|
+
if (!ctx) {
|
|
1175
|
+
this.logger.debug("start-edge-conversion-context-not-found", {
|
|
1176
|
+
runContextId: id,
|
|
1177
|
+
edgeId,
|
|
1178
|
+
});
|
|
998
1179
|
return;
|
|
1180
|
+
}
|
|
999
1181
|
ctx.pendingEdges++;
|
|
1182
|
+
this.logger.debug("start-edge-conversion", {
|
|
1183
|
+
runContextId: id,
|
|
1184
|
+
edgeId,
|
|
1185
|
+
pendingEdges: ctx.pendingEdges,
|
|
1186
|
+
});
|
|
1000
1187
|
}
|
|
1001
1188
|
finishEdgeConversion(id, edgeId) {
|
|
1002
1189
|
const ctx = this.runContexts.get(id);
|
|
1003
|
-
if (!ctx)
|
|
1190
|
+
if (!ctx) {
|
|
1191
|
+
this.logger.debug("finish-edge-conversion-context-not-found", {
|
|
1192
|
+
runContextId: id,
|
|
1193
|
+
edgeId,
|
|
1194
|
+
});
|
|
1004
1195
|
return;
|
|
1196
|
+
}
|
|
1005
1197
|
ctx.pendingEdges--;
|
|
1198
|
+
this.logger.debug("finish-edge-conversion", {
|
|
1199
|
+
runContextId: id,
|
|
1200
|
+
edgeId,
|
|
1201
|
+
pendingEdges: ctx.pendingEdges,
|
|
1202
|
+
});
|
|
1006
1203
|
this.finishRunContextIfPossible(id);
|
|
1007
1204
|
}
|
|
1008
1205
|
startHandleResolution(id, nodeId) {
|
|
1009
1206
|
const ctx = this.runContexts.get(id);
|
|
1010
|
-
if (!ctx)
|
|
1207
|
+
if (!ctx) {
|
|
1208
|
+
this.logger.debug("start-handle-resolution-context-not-found", {
|
|
1209
|
+
runContextId: id,
|
|
1210
|
+
nodeId,
|
|
1211
|
+
});
|
|
1011
1212
|
return;
|
|
1213
|
+
}
|
|
1012
1214
|
ctx.pendingResolvers++;
|
|
1215
|
+
this.logger.debug("start-handle-resolution", {
|
|
1216
|
+
runContextId: id,
|
|
1217
|
+
nodeId,
|
|
1218
|
+
pendingResolvers: ctx.pendingResolvers,
|
|
1219
|
+
});
|
|
1013
1220
|
}
|
|
1014
1221
|
finishHandleResolution(id, nodeId) {
|
|
1015
1222
|
const ctx = this.runContexts.get(id);
|
|
1016
|
-
if (!ctx)
|
|
1223
|
+
if (!ctx) {
|
|
1224
|
+
this.logger.debug("finish-handle-resolution-context-not-found", {
|
|
1225
|
+
runContextId: id,
|
|
1226
|
+
nodeId,
|
|
1227
|
+
});
|
|
1017
1228
|
return;
|
|
1229
|
+
}
|
|
1018
1230
|
ctx.pendingResolvers--;
|
|
1231
|
+
this.logger.debug("finish-handle-resolution", {
|
|
1232
|
+
runContextId: id,
|
|
1233
|
+
nodeId,
|
|
1234
|
+
pendingResolvers: ctx.pendingResolvers,
|
|
1235
|
+
});
|
|
1019
1236
|
this.finishRunContextIfPossible(id);
|
|
1020
1237
|
}
|
|
1021
1238
|
/**
|
|
@@ -1023,13 +1240,22 @@ class RunContextManager {
|
|
|
1023
1240
|
*/
|
|
1024
1241
|
finishRunContextIfPossible(id) {
|
|
1025
1242
|
const ctx = this.runContexts.get(id);
|
|
1026
|
-
if (!ctx)
|
|
1243
|
+
if (!ctx) {
|
|
1244
|
+
this.logger.debug("finish-run-context-not-found", {
|
|
1245
|
+
runContextId: id,
|
|
1246
|
+
});
|
|
1027
1247
|
return;
|
|
1248
|
+
}
|
|
1028
1249
|
if (ctx.pendingNodes > 0 ||
|
|
1029
1250
|
ctx.pendingEdges > 0 ||
|
|
1030
1251
|
ctx.pendingResolvers > 0) {
|
|
1031
1252
|
return; // Still has pending work
|
|
1032
1253
|
}
|
|
1254
|
+
this.logger.info("finish-run-context", {
|
|
1255
|
+
runContextId: id,
|
|
1256
|
+
startNodes: Array.from(ctx.startNodes),
|
|
1257
|
+
cancelledNodes: Array.from(ctx.cancelledNodes),
|
|
1258
|
+
});
|
|
1033
1259
|
// Clean up activeRunContexts from all nodes
|
|
1034
1260
|
this.graph.forEachNode((node) => {
|
|
1035
1261
|
this.graph.removeNodeRunContextId(node.nodeId, id);
|
|
@@ -1067,6 +1293,12 @@ class RunContextManager {
|
|
|
1067
1293
|
});
|
|
1068
1294
|
}
|
|
1069
1295
|
}
|
|
1296
|
+
this.logger.debug("cancel-node-in-run-contexts", {
|
|
1297
|
+
nodeId,
|
|
1298
|
+
includeDownstream,
|
|
1299
|
+
cancelledNodes: Array.from(toCancel),
|
|
1300
|
+
affectedRunContexts: Array.from(this.runContexts.keys()),
|
|
1301
|
+
});
|
|
1070
1302
|
// Mark nodes as cancelled in all run-contexts
|
|
1071
1303
|
for (const ctx of this.runContexts.values()) {
|
|
1072
1304
|
for (const id of toCancel) {
|
|
@@ -1082,6 +1314,11 @@ class RunContextManager {
|
|
|
1082
1314
|
* Resolve all pending run-context promises (for cleanup)
|
|
1083
1315
|
*/
|
|
1084
1316
|
resolveAll() {
|
|
1317
|
+
const count = this.runContexts.size;
|
|
1318
|
+
this.logger.info("resolve-all-run-contexts", {
|
|
1319
|
+
count,
|
|
1320
|
+
runContextIds: Array.from(this.runContexts.keys()),
|
|
1321
|
+
});
|
|
1085
1322
|
for (const ctx of this.runContexts.values()) {
|
|
1086
1323
|
if (ctx.resolve)
|
|
1087
1324
|
ctx.resolve();
|
|
@@ -1091,52 +1328,12 @@ class RunContextManager {
|
|
|
1091
1328
|
* Clear all run-contexts
|
|
1092
1329
|
*/
|
|
1093
1330
|
clear() {
|
|
1331
|
+
const count = this.runContexts.size;
|
|
1332
|
+
this.logger.info("clear-all-run-contexts", { count });
|
|
1094
1333
|
this.runContexts.clear();
|
|
1095
1334
|
}
|
|
1096
1335
|
}
|
|
1097
1336
|
|
|
1098
|
-
const LOG_LEVEL_VALUES = {
|
|
1099
|
-
debug: 0,
|
|
1100
|
-
info: 1,
|
|
1101
|
-
warn: 2,
|
|
1102
|
-
error: 3,
|
|
1103
|
-
silent: 4,
|
|
1104
|
-
};
|
|
1105
|
-
|
|
1106
|
-
/**
|
|
1107
|
-
* Shared utility functions for runtime components
|
|
1108
|
-
*/
|
|
1109
|
-
/**
|
|
1110
|
-
* Type guard to check if a value is a Promise
|
|
1111
|
-
*/
|
|
1112
|
-
function isPromise(value) {
|
|
1113
|
-
return !!value && typeof value.then === "function";
|
|
1114
|
-
}
|
|
1115
|
-
/**
|
|
1116
|
-
* Unwrap a value that might be a Promise
|
|
1117
|
-
*/
|
|
1118
|
-
async function unwrapMaybePromise(value) {
|
|
1119
|
-
return isPromise(value) ? await value : value;
|
|
1120
|
-
}
|
|
1121
|
-
/**
|
|
1122
|
-
* Shallow/deep-ish equality check to avoid unnecessary runs on identical values
|
|
1123
|
-
*/
|
|
1124
|
-
function valuesEqual(a, b) {
|
|
1125
|
-
if (a === b)
|
|
1126
|
-
return true;
|
|
1127
|
-
if (typeof a !== typeof b)
|
|
1128
|
-
return false;
|
|
1129
|
-
if (a && b && typeof a === "object") {
|
|
1130
|
-
try {
|
|
1131
|
-
return JSON.stringify(a) === JSON.stringify(b);
|
|
1132
|
-
}
|
|
1133
|
-
catch {
|
|
1134
|
-
return false;
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
return false;
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
1337
|
function tryHandleResolving(def, registry, environment) {
|
|
1141
1338
|
const out = new Map();
|
|
1142
1339
|
const pending = new Set();
|
|
@@ -2019,33 +2216,23 @@ class NodeExecutor {
|
|
|
2019
2216
|
progress: Math.max(0, Math.min(1, Number(p) || 0)),
|
|
2020
2217
|
});
|
|
2021
2218
|
});
|
|
2022
|
-
// Create log function that respects node's logLevel
|
|
2219
|
+
// Create log function that respects node's logLevel using LevelLogger
|
|
2220
|
+
const nodeLogLevel = node.logLevel ?? "info";
|
|
2221
|
+
const logger = new LevelLogger(nodeLogLevel, `[node:${runId || nodeId}:${node.typeId}]`);
|
|
2023
2222
|
const log = (level, message, context) => {
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
console.info(fullMessage);
|
|
2038
|
-
break;
|
|
2039
|
-
case "info":
|
|
2040
|
-
console.info(fullMessage);
|
|
2041
|
-
break;
|
|
2042
|
-
case "warn":
|
|
2043
|
-
console.warn(fullMessage);
|
|
2044
|
-
break;
|
|
2045
|
-
case "error":
|
|
2046
|
-
console.error(fullMessage);
|
|
2047
|
-
break;
|
|
2048
|
-
}
|
|
2223
|
+
switch (level) {
|
|
2224
|
+
case "debug":
|
|
2225
|
+
logger.debug(message, context);
|
|
2226
|
+
break;
|
|
2227
|
+
case "info":
|
|
2228
|
+
logger.info(message, context);
|
|
2229
|
+
break;
|
|
2230
|
+
case "warn":
|
|
2231
|
+
logger.warn(message, context);
|
|
2232
|
+
break;
|
|
2233
|
+
case "error":
|
|
2234
|
+
logger.error(message, context);
|
|
2235
|
+
break;
|
|
2049
2236
|
}
|
|
2050
2237
|
};
|
|
2051
2238
|
return {
|
|
@@ -2574,7 +2761,7 @@ class GraphRuntime {
|
|
|
2574
2761
|
// Initialize components
|
|
2575
2762
|
this.graph = new Graph();
|
|
2576
2763
|
this.eventEmitter = new EventEmitter();
|
|
2577
|
-
this.runContextManager = new RunContextManager(this.graph);
|
|
2764
|
+
this.runContextManager = new RunContextManager(this.graph, "debug");
|
|
2578
2765
|
this.handleResolver = new HandleResolver(this.graph, this.eventEmitter, this.runContextManager, this);
|
|
2579
2766
|
this.edgePropagator = new EdgePropagator(this.graph, this.eventEmitter, this.runContextManager, this.handleResolver, this);
|
|
2580
2767
|
// Create NodeExecutor with EdgePropagator and HandleResolver
|
|
@@ -5709,6 +5896,7 @@ exports.CompositeCategory = CompositeCategory;
|
|
|
5709
5896
|
exports.ComputeCategory = ComputeCategory;
|
|
5710
5897
|
exports.GraphBuilder = GraphBuilder;
|
|
5711
5898
|
exports.GraphRuntime = GraphRuntime;
|
|
5899
|
+
exports.LevelLogger = LevelLogger;
|
|
5712
5900
|
exports.LocalEngine = LocalEngine;
|
|
5713
5901
|
exports.Registry = Registry;
|
|
5714
5902
|
exports.buildValueConverter = buildValueConverter;
|