@bian-womp/spark-graph 0.3.6 → 0.3.8
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 +69 -6
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/runtime/GraphRuntime.d.ts +4 -0
- package/lib/cjs/src/runtime/GraphRuntime.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/EdgePropagator.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/NodeExecutor.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/types.d.ts +3 -1
- package/lib/cjs/src/runtime/components/types.d.ts.map +1 -1
- package/lib/esm/index.js +69 -6
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/runtime/GraphRuntime.d.ts +4 -0
- package/lib/esm/src/runtime/GraphRuntime.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/EdgePropagator.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/NodeExecutor.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/types.d.ts +3 -1
- package/lib/esm/src/runtime/components/types.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/cjs/index.cjs
CHANGED
|
@@ -1238,14 +1238,35 @@ class EdgePropagator {
|
|
|
1238
1238
|
const processedValue = this.processArrayInput(edge, value);
|
|
1239
1239
|
// Check if value changed
|
|
1240
1240
|
const prev = dstNode.inputs[edge.target.handle];
|
|
1241
|
-
|
|
1242
|
-
|
|
1241
|
+
const valueChanged = !valuesEqual(prev, processedValue);
|
|
1242
|
+
// Check if we should execute even if value is same:
|
|
1243
|
+
// 1. If node has rerunOnSameInput policy (from node params or registry)
|
|
1244
|
+
// 2. If input was set after last successful run (stale input detection)
|
|
1245
|
+
const registry = this.graph.getRegistry();
|
|
1246
|
+
const desc = registry?.nodes.get(dstNode.typeId);
|
|
1247
|
+
const nodeRerunPolicy = dstNode.policy?.rerunOnSameInput === true;
|
|
1248
|
+
const descRerunPolicy = desc?.policy?.rerunOnSameInput === true;
|
|
1249
|
+
const shouldRerunOnSameInput = nodeRerunPolicy || descRerunPolicy;
|
|
1250
|
+
const inputWasSetAfterLastRun = dstNode.lastInputAt?.[edge.target.handle] &&
|
|
1251
|
+
dstNode.lastSuccessAt &&
|
|
1252
|
+
dstNode.lastInputAt[edge.target.handle] > dstNode.lastSuccessAt;
|
|
1253
|
+
const shouldExecute = valueChanged || shouldRerunOnSameInput || inputWasSetAfterLastRun;
|
|
1254
|
+
if (!shouldExecute) {
|
|
1255
|
+
return; // No change and no reason to rerun
|
|
1243
1256
|
}
|
|
1244
1257
|
// Set input value (respecting skipPropagateValues)
|
|
1245
1258
|
const shouldSetValue = this.shouldSetInputValue(effectiveRunContexts);
|
|
1246
|
-
if (shouldSetValue) {
|
|
1259
|
+
if (shouldSetValue && valueChanged) {
|
|
1247
1260
|
this.setTargetInput(edge, dstNode, processedValue);
|
|
1248
1261
|
}
|
|
1262
|
+
else if (shouldSetValue && !valueChanged) {
|
|
1263
|
+
// Even if value didn't change, update timestamp if we're forcing execution
|
|
1264
|
+
const now = Date.now();
|
|
1265
|
+
if (!dstNode.lastInputAt) {
|
|
1266
|
+
dstNode.lastInputAt = {};
|
|
1267
|
+
}
|
|
1268
|
+
dstNode.lastInputAt[edge.target.handle] = now;
|
|
1269
|
+
}
|
|
1249
1270
|
// Schedule downstream execution
|
|
1250
1271
|
this.executeDownstream(edge.target.nodeId, effectiveRunContexts);
|
|
1251
1272
|
}
|
|
@@ -1302,7 +1323,13 @@ class EdgePropagator {
|
|
|
1302
1323
|
* Set target input value and emit event
|
|
1303
1324
|
*/
|
|
1304
1325
|
setTargetInput(edge, dstNode, value) {
|
|
1326
|
+
const now = Date.now();
|
|
1305
1327
|
dstNode.inputs[edge.target.handle] = value;
|
|
1328
|
+
// Track when this input was set
|
|
1329
|
+
if (!dstNode.lastInputAt) {
|
|
1330
|
+
dstNode.lastInputAt = {};
|
|
1331
|
+
}
|
|
1332
|
+
dstNode.lastInputAt[edge.target.handle] = now;
|
|
1306
1333
|
this.eventEmitter.emit("value", {
|
|
1307
1334
|
nodeId: edge.target.nodeId,
|
|
1308
1335
|
handle: edge.target.handle,
|
|
@@ -1879,11 +1906,15 @@ class NodeExecutor {
|
|
|
1879
1906
|
: undefined;
|
|
1880
1907
|
if (!hadError)
|
|
1881
1908
|
node.stats.lastError = undefined;
|
|
1882
|
-
//
|
|
1909
|
+
// Track successful completion time (for detecting stale inputs)
|
|
1883
1910
|
const isCancelled = controller.signal.aborted &&
|
|
1884
1911
|
(controller.signal.reason === "snapshot" ||
|
|
1885
1912
|
controller.signal.reason === "node-deleted" ||
|
|
1886
1913
|
controller.signal.reason === "user-cancelled");
|
|
1914
|
+
if (!hadError && !isCancelled) {
|
|
1915
|
+
node.lastSuccessAt = Date.now();
|
|
1916
|
+
}
|
|
1917
|
+
// Only emit node-done if not cancelled (cancellation events emitted separately)
|
|
1887
1918
|
if (!isCancelled) {
|
|
1888
1919
|
this.eventEmitter.emit("stats", {
|
|
1889
1920
|
kind: "node-done",
|
|
@@ -2051,6 +2082,8 @@ class GraphRuntime {
|
|
|
2051
2082
|
progress: 0,
|
|
2052
2083
|
},
|
|
2053
2084
|
activeRunContextIds: new Set(),
|
|
2085
|
+
lastInputAt: {},
|
|
2086
|
+
lastSuccessAt: undefined,
|
|
2054
2087
|
};
|
|
2055
2088
|
gr.graph.setNode(n.nodeId, rn);
|
|
2056
2089
|
}
|
|
@@ -2157,8 +2190,27 @@ class GraphRuntime {
|
|
|
2157
2190
|
const node = this.graph.getNode(nodeId);
|
|
2158
2191
|
if (!node)
|
|
2159
2192
|
return;
|
|
2193
|
+
// If event is an invalidate event, re-run the node with same inputs
|
|
2194
|
+
if (this.isInvalidateEvent(event)) {
|
|
2195
|
+
// Check if node has all inbound inputs (required for execution)
|
|
2196
|
+
if (this.graph.allInboundHaveValue(nodeId)) {
|
|
2197
|
+
this.execute(nodeId);
|
|
2198
|
+
}
|
|
2199
|
+
return;
|
|
2200
|
+
}
|
|
2201
|
+
// Forward event to node's onExternalEvent handler for custom actions
|
|
2160
2202
|
node.runtime.onExternalEvent?.(event, node.state);
|
|
2161
2203
|
}
|
|
2204
|
+
/**
|
|
2205
|
+
* Check if an event is an invalidate event that should trigger re-execution
|
|
2206
|
+
*/
|
|
2207
|
+
isInvalidateEvent(event) {
|
|
2208
|
+
if (!event || typeof event !== "object")
|
|
2209
|
+
return false;
|
|
2210
|
+
// Check if event has action === "invalidate"
|
|
2211
|
+
const e = event;
|
|
2212
|
+
return e.action === "invalidate";
|
|
2213
|
+
}
|
|
2162
2214
|
cancelNodeRuns(nodeIds) {
|
|
2163
2215
|
this.nodeExecutor.cancelNodeRuns(nodeIds);
|
|
2164
2216
|
}
|
|
@@ -2385,6 +2437,8 @@ class GraphRuntime {
|
|
|
2385
2437
|
progress: 0,
|
|
2386
2438
|
},
|
|
2387
2439
|
activeRunContextIds: new Set(),
|
|
2440
|
+
lastInputAt: {},
|
|
2441
|
+
lastSuccessAt: undefined,
|
|
2388
2442
|
};
|
|
2389
2443
|
this.graph.setNode(n.nodeId, newNode);
|
|
2390
2444
|
const effectiveInputs = this.nodeExecutor.getEffectiveInputs(newNode.nodeId);
|
|
@@ -2531,8 +2585,17 @@ class GraphRuntime {
|
|
|
2531
2585
|
const afterTargetSet = afterMap.get(handle) ?? new Set();
|
|
2532
2586
|
if (!setsEqual(beforeTargetSet, afterTargetSet)) {
|
|
2533
2587
|
const val = this.getOutput(nodeId, handle);
|
|
2534
|
-
if (val !== undefined)
|
|
2535
|
-
|
|
2588
|
+
if (val !== undefined) {
|
|
2589
|
+
let runContextIdsToUse = undefined;
|
|
2590
|
+
if (this.runMode === "manual") {
|
|
2591
|
+
runContextIdsToUse = new Set([
|
|
2592
|
+
this.runContextManager.createRunContext(nodeId, undefined, {
|
|
2593
|
+
propagate: false,
|
|
2594
|
+
}),
|
|
2595
|
+
]);
|
|
2596
|
+
}
|
|
2597
|
+
this.propagate(nodeId, handle, val, runContextIdsToUse);
|
|
2598
|
+
}
|
|
2536
2599
|
}
|
|
2537
2600
|
}
|
|
2538
2601
|
}
|