@bian-womp/spark-graph 0.3.35 → 0.3.37
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 +99 -28
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/runtime/components/Graph.d.ts +4 -13
- package/lib/cjs/src/runtime/components/Graph.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/HandleResolver.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/NodeExecutor.d.ts +5 -0
- package/lib/cjs/src/runtime/components/NodeExecutor.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/RunContextManager.d.ts +11 -0
- package/lib/cjs/src/runtime/components/RunContextManager.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/types.d.ts +13 -4
- package/lib/cjs/src/runtime/components/types.d.ts.map +1 -1
- package/lib/esm/index.js +99 -28
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/runtime/components/Graph.d.ts +4 -13
- package/lib/esm/src/runtime/components/Graph.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/HandleResolver.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/NodeExecutor.d.ts +5 -0
- package/lib/esm/src/runtime/components/NodeExecutor.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/RunContextManager.d.ts +11 -0
- package/lib/esm/src/runtime/components/RunContextManager.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/types.d.ts +13 -4
- package/lib/esm/src/runtime/components/types.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/cjs/index.cjs
CHANGED
|
@@ -1148,6 +1148,7 @@ class RunContextManager {
|
|
|
1148
1148
|
pendingNodes: 0,
|
|
1149
1149
|
pendingEdges: 0,
|
|
1150
1150
|
pendingResolvers: 0,
|
|
1151
|
+
pendingQueued: 0,
|
|
1151
1152
|
skipPropagateValues: options?.skipPropagateValues ?? false,
|
|
1152
1153
|
propagate: options?.propagate ?? true,
|
|
1153
1154
|
resolve,
|
|
@@ -1179,6 +1180,47 @@ class RunContextManager {
|
|
|
1179
1180
|
hasActiveRunContexts() {
|
|
1180
1181
|
return this.runContexts.size > 0;
|
|
1181
1182
|
}
|
|
1183
|
+
/**
|
|
1184
|
+
* Increment queued work count for a run-context.
|
|
1185
|
+
* Used by asyncConcurrency: "queue" to keep contexts alive while work is queued.
|
|
1186
|
+
*/
|
|
1187
|
+
incrementQueued(id, nodeId) {
|
|
1188
|
+
const ctx = this.runContexts.get(id);
|
|
1189
|
+
if (!ctx) {
|
|
1190
|
+
this.logger.debug("increment-queued-context-not-found", {
|
|
1191
|
+
runContextId: id,
|
|
1192
|
+
nodeId,
|
|
1193
|
+
});
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
ctx.pendingQueued++;
|
|
1197
|
+
this.logger.debug("increment-queued", {
|
|
1198
|
+
runContextId: id,
|
|
1199
|
+
nodeId,
|
|
1200
|
+
pendingQueued: ctx.pendingQueued,
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* Decrement queued work count for a run-context.
|
|
1205
|
+
* Called when queued work is either started or dropped.
|
|
1206
|
+
*/
|
|
1207
|
+
decrementQueued(id, nodeId) {
|
|
1208
|
+
const ctx = this.runContexts.get(id);
|
|
1209
|
+
if (!ctx) {
|
|
1210
|
+
this.logger.debug("decrement-queued-context-not-found", {
|
|
1211
|
+
runContextId: id,
|
|
1212
|
+
nodeId,
|
|
1213
|
+
});
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
ctx.pendingQueued--;
|
|
1217
|
+
this.logger.debug("decrement-queued", {
|
|
1218
|
+
runContextId: id,
|
|
1219
|
+
nodeId,
|
|
1220
|
+
pendingQueued: ctx.pendingQueued,
|
|
1221
|
+
});
|
|
1222
|
+
this.finishRunContextIfPossible(id);
|
|
1223
|
+
}
|
|
1182
1224
|
startNodeRun(id, nodeId) {
|
|
1183
1225
|
const ctx = this.runContexts.get(id);
|
|
1184
1226
|
if (!ctx) {
|
|
@@ -1291,7 +1333,8 @@ class RunContextManager {
|
|
|
1291
1333
|
}
|
|
1292
1334
|
if (ctx.pendingNodes > 0 ||
|
|
1293
1335
|
ctx.pendingEdges > 0 ||
|
|
1294
|
-
ctx.pendingResolvers > 0
|
|
1336
|
+
ctx.pendingResolvers > 0 ||
|
|
1337
|
+
ctx.pendingQueued > 0) {
|
|
1295
1338
|
return; // Still has pending work
|
|
1296
1339
|
}
|
|
1297
1340
|
this.logger.info("finish-run-context", {
|
|
@@ -1842,8 +1885,6 @@ class HandleResolver {
|
|
|
1842
1885
|
if ((this.recomputeTokenByNode.get(nodeId) ?? 0) !== token)
|
|
1843
1886
|
return;
|
|
1844
1887
|
const before = this.graph.getResolvedHandles(nodeId);
|
|
1845
|
-
if (!before)
|
|
1846
|
-
return;
|
|
1847
1888
|
// Re-fetch desc to ensure we have the latest (node might have been updated)
|
|
1848
1889
|
const nodeDesc = this.registry.nodes.get(node.typeId);
|
|
1849
1890
|
if (!nodeDesc)
|
|
@@ -1872,8 +1913,9 @@ class HandleResolver {
|
|
|
1872
1913
|
...resolved?.inputDefaults,
|
|
1873
1914
|
};
|
|
1874
1915
|
const after = { inputs, outputs, inputDefaults };
|
|
1875
|
-
//
|
|
1876
|
-
|
|
1916
|
+
// If we have prior handles, skip update when unchanged; for new nodes (no before),
|
|
1917
|
+
// always write the resolved handles.
|
|
1918
|
+
if (before && JSON.stringify(before) === JSON.stringify(after))
|
|
1877
1919
|
return;
|
|
1878
1920
|
// Call GraphRuntime's updateNodeHandles to update edges and re-propagate values
|
|
1879
1921
|
// Note: updateNodeHandles will set the resolved handles internally
|
|
@@ -2460,8 +2502,8 @@ class NodeExecutor {
|
|
|
2460
2502
|
}
|
|
2461
2503
|
// Handle debouncing
|
|
2462
2504
|
const now = Date.now();
|
|
2463
|
-
if (this.shouldDebounce(
|
|
2464
|
-
this.handleDebouncedSchedule(node, nodeId, now);
|
|
2505
|
+
if (this.shouldDebounce(node, now)) {
|
|
2506
|
+
this.handleDebouncedSchedule(node, nodeId, now, runContextIds);
|
|
2465
2507
|
return;
|
|
2466
2508
|
}
|
|
2467
2509
|
// Prepare execution plan
|
|
@@ -2472,7 +2514,7 @@ class NodeExecutor {
|
|
|
2472
2514
|
/**
|
|
2473
2515
|
* Check if execution should be debounced
|
|
2474
2516
|
*/
|
|
2475
|
-
shouldDebounce(
|
|
2517
|
+
shouldDebounce(node, now) {
|
|
2476
2518
|
const policy = node.policy ?? {};
|
|
2477
2519
|
const lastScheduledAt = node.lastScheduledAt;
|
|
2478
2520
|
return !!(policy.debounceMs &&
|
|
@@ -2482,13 +2524,23 @@ class NodeExecutor {
|
|
|
2482
2524
|
/**
|
|
2483
2525
|
* Handle debounced scheduling by replacing the latest queued item
|
|
2484
2526
|
*/
|
|
2485
|
-
handleDebouncedSchedule(node, nodeId, now) {
|
|
2527
|
+
handleDebouncedSchedule(node, nodeId, now, runContextIds) {
|
|
2528
|
+
// Decrement pendingQueued for any existing queued items before replacing
|
|
2529
|
+
if (node.queue.length > 0) {
|
|
2530
|
+
this.decrementQueuedForPlans(node.queue, nodeId);
|
|
2531
|
+
}
|
|
2486
2532
|
const effectiveInputs = this.getEffectiveInputs(nodeId);
|
|
2487
2533
|
const runSeq = this.graph.incrementNodeRunSeq(nodeId);
|
|
2488
|
-
const
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2534
|
+
const runId = `${nodeId}:${runSeq}:${now}`;
|
|
2535
|
+
const policySnapshot = node.policy ? { ...node.policy } : undefined;
|
|
2536
|
+
const plan = {
|
|
2537
|
+
runId,
|
|
2538
|
+
effectiveInputs,
|
|
2539
|
+
runContextIdsForRun: runContextIds,
|
|
2540
|
+
timestamp: now,
|
|
2541
|
+
policy: policySnapshot,
|
|
2542
|
+
};
|
|
2543
|
+
this.graph.replaceNodeQueue(nodeId, [plan]);
|
|
2492
2544
|
}
|
|
2493
2545
|
/**
|
|
2494
2546
|
* Prepare execution plan with all necessary information
|
|
@@ -2547,12 +2599,19 @@ class NodeExecutor {
|
|
|
2547
2599
|
const currentNode = this.graph.getNode(nodeId);
|
|
2548
2600
|
if (!currentNode)
|
|
2549
2601
|
return;
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2602
|
+
// Keep the originating run-context alive while work is queued by
|
|
2603
|
+
// incrementing queued counters for the plan's run-contexts.
|
|
2604
|
+
if (plan.runContextIdsForRun) {
|
|
2605
|
+
for (const rcId of plan.runContextIdsForRun) {
|
|
2606
|
+
this.runContextManager.incrementQueued(rcId, nodeId);
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
this.graph.addToNodeQueue(nodeId, plan);
|
|
2554
2610
|
if (currentNode.queue.length > maxQ) {
|
|
2555
|
-
this.graph.shiftNodeQueue(nodeId);
|
|
2611
|
+
const dropped = this.graph.shiftNodeQueue(nodeId);
|
|
2612
|
+
if (dropped) {
|
|
2613
|
+
this.decrementQueuedForPlans(dropped, nodeId);
|
|
2614
|
+
}
|
|
2556
2615
|
}
|
|
2557
2616
|
this.processQueue(node, nodeId);
|
|
2558
2617
|
}
|
|
@@ -2570,18 +2629,12 @@ class NodeExecutor {
|
|
|
2570
2629
|
if (!next)
|
|
2571
2630
|
return;
|
|
2572
2631
|
this.graph.setNodeLatestRunId(nodeId, next.runId);
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
runId: next.runId,
|
|
2577
|
-
effectiveInputs: next.inputs,
|
|
2578
|
-
runContextIdsForRun: activeRunContextIds.size > 0 ? activeRunContextIds : undefined,
|
|
2579
|
-
timestamp: Date.now(),
|
|
2580
|
-
policy: policySnapshot,
|
|
2581
|
-
};
|
|
2582
|
-
this.startRun(node, nodeId, plan, () => {
|
|
2632
|
+
// Start the run first (which increments pendingNodes), then decrement
|
|
2633
|
+
// pendingQueued to ensure the run context stays alive.
|
|
2634
|
+
this.startRun(node, nodeId, next, () => {
|
|
2583
2635
|
setTimeout(processNext, 0);
|
|
2584
2636
|
});
|
|
2637
|
+
this.decrementQueuedForPlans(next, nodeId);
|
|
2585
2638
|
};
|
|
2586
2639
|
processNext();
|
|
2587
2640
|
}
|
|
@@ -2612,6 +2665,20 @@ class NodeExecutor {
|
|
|
2612
2665
|
}
|
|
2613
2666
|
}
|
|
2614
2667
|
}
|
|
2668
|
+
/**
|
|
2669
|
+
* Decrement pendingQueued counters for plans' run-contexts.
|
|
2670
|
+
* Used when queued work is being started, dropped, or cancelled.
|
|
2671
|
+
*/
|
|
2672
|
+
decrementQueuedForPlans(plans, nodeId) {
|
|
2673
|
+
const plansArray = Array.isArray(plans) ? plans : [plans];
|
|
2674
|
+
for (const plan of plansArray) {
|
|
2675
|
+
if (plan.runContextIdsForRun) {
|
|
2676
|
+
for (const rcId of plan.runContextIdsForRun) {
|
|
2677
|
+
this.runContextManager.decrementQueued(rcId, nodeId);
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2615
2682
|
/**
|
|
2616
2683
|
* Create execution controller and update node stats
|
|
2617
2684
|
*/
|
|
@@ -2840,6 +2907,10 @@ class NodeExecutor {
|
|
|
2840
2907
|
}
|
|
2841
2908
|
this.graph.clearNodeControllers(nodeId);
|
|
2842
2909
|
this.graph.updateNodeStats(nodeId, { active: 0 });
|
|
2910
|
+
// Decrement pendingQueued for any queued items before clearing the queue
|
|
2911
|
+
if (node.queue.length > 0) {
|
|
2912
|
+
this.decrementQueuedForPlans(node.queue, nodeId);
|
|
2913
|
+
}
|
|
2843
2914
|
this.graph.clearNodeQueue(nodeId);
|
|
2844
2915
|
}
|
|
2845
2916
|
/**
|