@bian-womp/spark-graph 0.3.17 → 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.
@@ -1,7 +1,7 @@
1
1
  import { Registry } from "../../builder/Registry";
2
2
  import type { EventEmitter } from "./EventEmitter";
3
3
  import type { Graph } from "./Graph";
4
- import type { RunContextId, RunContextManager } from "./RunContextManager";
4
+ import type { RunContextManager } from "./RunContextManager";
5
5
  import type { IEdgePropagator, IHandleResolver } from "./interfaces";
6
6
  /**
7
7
  * HandleResolver component - manages dynamic handle resolution
@@ -15,22 +15,14 @@ export declare class HandleResolver implements IHandleResolver {
15
15
  private recomputeTokenByNode;
16
16
  private environment;
17
17
  private pendingResolutions;
18
- private pendingResolutionRunContexts;
18
+ private isRecomputing;
19
19
  constructor(graph: Graph, eventEmitter: EventEmitter, runContextManager: RunContextManager, edgePropagator: IEdgePropagator, registry?: Registry | undefined, environment?: Record<string, unknown>);
20
20
  setRegistry(registry: Registry): void;
21
21
  setEnvironment(environment: Record<string, unknown>): void;
22
- /**
23
- * Check if handle resolution is pending for a node
24
- */
25
- isResolvingHandles(nodeId: string): boolean;
26
22
  /**
27
23
  * Get the promise for pending handle resolution, or null if none
28
24
  */
29
25
  getPendingResolution(nodeId: string): Promise<void> | null;
30
- /**
31
- * Track additional run contexts for a pending resolution
32
- */
33
- trackRunContextsForPendingResolution(nodeId: string, runContextIds: Set<RunContextId>): void;
34
26
  /**
35
27
  * Schedule async recomputation of handles for a node
36
28
  */
@@ -1 +1 @@
1
- {"version":3,"file":"HandleResolver.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/components/HandleResolver.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAKrE;;GAEG;AACH,qBAAa,cAAe,YAAW,eAAe;IAOlD,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC;IAVnB,OAAO,CAAC,oBAAoB,CAA6B;IACzD,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,kBAAkB,CAAoC;IAC9D,OAAO,CAAC,4BAA4B,CAAwC;gBAGzD,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,iBAAiB,EAAE,iBAAiB,EACpC,cAAc,EAAE,eAAe,EACxC,QAAQ,CAAC,EAAE,QAAQ,YAAA,EAC3B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAKvC,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAIrC,cAAc,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI1D;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAI3C;;OAEG;IACH,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI1D;;OAEG;IACH,oCAAoC,CAClC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,GAAG,CAAC,YAAY,CAAC,GAC/B,IAAI;IAaP;;OAEG;IACH,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAoC9C,OAAO,CAAC,iBAAiB;IA+EzB;;OAEG;YACW,uBAAuB;CA0GtC"}
1
+ {"version":3,"file":"HandleResolver.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/components/HandleResolver.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAgB,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAKrE;;GAEG;AACH,qBAAa,cAAe,YAAW,eAAe;IAOlD,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC;IAVnB,OAAO,CAAC,oBAAoB,CAA6B;IACzD,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,kBAAkB,CAAoC;IAC9D,OAAO,CAAC,aAAa,CAA8B;gBAGhC,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,iBAAiB,EAAE,iBAAiB,EACpC,cAAc,EAAE,eAAe,EACxC,QAAQ,CAAC,EAAE,QAAQ,YAAA,EAC3B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAKvC,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAIrC,cAAc,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI1D;;OAEG;IACH,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI1D;;OAEG;IACH,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAqD9C,OAAO,CAAC,iBAAiB;IA+EzB;;OAEG;YACW,uBAAuB;CA0GtC"}
@@ -18,9 +18,7 @@ export interface INodeExecutor {
18
18
  */
19
19
  export interface IHandleResolver {
20
20
  scheduleRecomputeHandles(nodeId: string): void;
21
- isResolvingHandles(nodeId: string): boolean;
22
21
  getPendingResolution(nodeId: string): Promise<void> | null;
23
- trackRunContextsForPendingResolution(nodeId: string, runContextIds: Set<RunContextId>): void;
24
22
  }
25
23
  /**
26
24
  * Interface for runtime coordination operations
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/components/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,CACP,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,EACd,aAAa,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,GAChC,IAAI,CAAC;IACR,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;CAClE;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5C,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3D,oCAAoC,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;CAC9F;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,IAAI,OAAO,CAAC;IACpB,UAAU,IAAI,OAAO,GAAG,IAAI,CAAC;CAC9B"}
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/components/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,CACP,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,EACd,aAAa,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,GAChC,IAAI,CAAC;IACR,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;CAClE;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC5D;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,IAAI,OAAO,CAAC;IACpB,UAAU,IAAI,OAAO,GAAG,IAAI,CAAC;CAC9B"}
package/lib/esm/index.js CHANGED
@@ -1530,7 +1530,7 @@ class HandleResolver {
1530
1530
  this.recomputeTokenByNode = new Map();
1531
1531
  this.environment = {};
1532
1532
  this.pendingResolutions = new Map();
1533
- this.pendingResolutionRunContexts = new Map();
1533
+ this.isRecomputing = new Map();
1534
1534
  this.environment = environment ?? {};
1535
1535
  }
1536
1536
  setRegistry(registry) {
@@ -1539,33 +1539,12 @@ class HandleResolver {
1539
1539
  setEnvironment(environment) {
1540
1540
  this.environment = environment;
1541
1541
  }
1542
- /**
1543
- * Check if handle resolution is pending for a node
1544
- */
1545
- isResolvingHandles(nodeId) {
1546
- return this.pendingResolutions.has(nodeId);
1547
- }
1548
1542
  /**
1549
1543
  * Get the promise for pending handle resolution, or null if none
1550
1544
  */
1551
1545
  getPendingResolution(nodeId) {
1552
1546
  return this.pendingResolutions.get(nodeId) || null;
1553
1547
  }
1554
- /**
1555
- * Track additional run contexts for a pending resolution
1556
- */
1557
- trackRunContextsForPendingResolution(nodeId, runContextIds) {
1558
- if (!this.pendingResolutions.has(nodeId))
1559
- return;
1560
- const tracked = this.pendingResolutionRunContexts.get(nodeId) ?? new Set();
1561
- for (const runContextId of runContextIds) {
1562
- if (!tracked.has(runContextId)) {
1563
- this.runContextManager.startHandleResolution(runContextId, nodeId);
1564
- tracked.add(runContextId);
1565
- }
1566
- }
1567
- this.pendingResolutionRunContexts.set(nodeId, tracked);
1568
- }
1569
1548
  /**
1570
1549
  * Schedule async recomputation of handles for a node
1571
1550
  */
@@ -1576,27 +1555,43 @@ class HandleResolver {
1576
1555
  const node = this.graph.getNode(nodeId);
1577
1556
  if (!node)
1578
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
+ }
1579
1565
  // Track resolver start for all active run-contexts
1580
1566
  const activeRunContextIds = this.graph.getNodeRunContextIds(nodeId);
1581
- const trackedRunContextIds = new Set(activeRunContextIds);
1582
1567
  if (activeRunContextIds.size > 0) {
1583
1568
  for (const runContextId of activeRunContextIds) {
1584
1569
  this.runContextManager.startHandleResolution(runContextId, nodeId);
1585
1570
  }
1586
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;
1587
1576
  // Create and track the resolution promise
1588
1577
  const resolutionPromise = new Promise((resolve) => {
1589
1578
  setTimeout(async () => {
1590
- // Get all tracked run contexts (including any added during pending state)
1591
- const allTracked = this.pendingResolutionRunContexts.get(nodeId) ?? trackedRunContextIds;
1592
- await this.recomputeHandlesForNode(nodeId, allTracked.size > 0 ? allTracked : undefined);
1579
+ await this.recomputeHandlesForNode(nodeId, activeRunContextIds);
1593
1580
  this.pendingResolutions.delete(nodeId);
1594
- this.pendingResolutionRunContexts.delete(nodeId);
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
+ }
1595
1591
  resolve();
1596
1592
  }, 0);
1597
1593
  });
1598
1594
  this.pendingResolutions.set(nodeId, resolutionPromise);
1599
- this.pendingResolutionRunContexts.set(nodeId, trackedRunContextIds);
1600
1595
  }
1601
1596
  // Update resolved handles for a single node and refresh edge converters/types that touch it
1602
1597
  updateNodeHandles(nodeId, handles) {
@@ -2302,23 +2297,27 @@ class NodeExecutor {
2302
2297
  }
2303
2298
  // Check if handles are being resolved - wait for resolution before executing
2304
2299
  // Do this AFTER setting up run contexts so handle resolution can track them
2305
- if (this.handleResolver && this.handleResolver.isResolvingHandles(nodeId)) {
2306
- // Track run contexts for the pending resolution
2300
+ const pendingResolution = this.handleResolver.getPendingResolution(nodeId);
2301
+ if (pendingResolution) {
2307
2302
  if (runContextIds && runContextIds.size > 0) {
2308
- this.handleResolver.trackRunContextsForPendingResolution(nodeId, runContextIds);
2303
+ for (const id of runContextIds) {
2304
+ this.runContextManager.startHandleResolution(id, nodeId);
2305
+ }
2309
2306
  }
2310
- const pendingResolution = this.handleResolver.getPendingResolution(nodeId);
2311
- if (pendingResolution) {
2312
- // Wait for resolution to complete, then re-execute
2313
- pendingResolution.then(() => {
2314
- // Re-check node still exists and conditions
2315
- const nodeAfter = this.graph.getNode(nodeId);
2316
- if (nodeAfter) {
2317
- this.execute(nodeId, runContextIds);
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);
2318
2317
  }
2319
- });
2320
- return;
2321
- }
2318
+ }
2319
+ });
2320
+ return;
2322
2321
  }
2323
2322
  // Handle debouncing
2324
2323
  const now = Date.now();