Unified · Split
| @@ -5816,23 +5816,28 @@ export const createExecutor = <const TPlugins extends readonly AnyPlugin[] = rea · 5815 unmodified lines | ||
| 5816 | 5816 | // handler at construction), so an abandoned read cannot |
| 5817 | 5817 | // unhandled-reject; a fiber interrupted before it ever ran issues no |
| 5818 | 5818 | // read at all. |
| 5819 | − // Launch order is dominant-first by construction, best-effort under | |
| 5820 | − // the scheduler. The dominant tool-row read is forked FIRST with | |
| 5821 | − // `startImmediately: true`: an immediate fork evaluates the child | |
| 5822 | − // INLINE (`forkUnsafe` calls `child.evaluate` on the spot), so the | |
| 5823 | − // read is normally issued before the speculative forks below are | |
| 5824 | − // even scheduled (a plain fork only queues its child on the | |
| 5825 | − // dispatcher for the next tick). The one exception is deliberate: if | |
| 5826 | − // the child's own operation budget (`MaxOpsBeforeYield`) expires | |
| 5827 | − // inside the launch window, the inline segment parks and a | |
| 5828 | − // speculative read may launch first. That reversal is materially | |
| 5829 | − // free, so it is NOT suppressed: on a synchronous driver the reads | |
| 5830 | − // serialize whichever order they start (same wall time), and on an | |
| 5831 | − // asynchronous driver every read suspends at its first await and | |
| 5832 | − // they overlap regardless of order. Suppressing the yield (a | |
| 5833 | − // fiber-lifetime `PreventSchedulerYield`) is NOT an option here — | |
| 5834 | − // the ref is inherited by everything the child runs and provably | |
| 5835 | − // keeps effect timeouts from firing across CPU-bound stretches. | |
| 5819 | + // Launch order is dominant-first. The dominant tool-row read is | |
| 5820 | + // forked FIRST with `startImmediately: true`: an immediate fork | |
| 5821 | + // evaluates the child INLINE (`forkUnsafe` calls `child.evaluate` on | |
| 5822 | + // the spot), and a forked fiber enters its run loop with a FRESH | |
| 5823 | + // operation count (`runLoop` zeroes `currentOpCount`), so the few | |
| 5824 | + // dozen operations between fork and the driver-promise suspension | |
| 5825 | + // cannot reach the cooperative-yield budget (`MaxOpsBeforeYield` | |
| 5826 | + // defaults to 2048) — the read is issued before the speculative | |
| 5827 | + // forks below are even scheduled (a plain fork only queues its child | |
| 5828 | + // on the dispatcher for the next tick). Dominant-first matters | |
| 5829 | + // beyond taste: cloud's postgres pool is `max: 1`, so queries | |
| 5830 | + // pipeline through one connection in issue order — a speculative | |
| 5831 | + // query issued first would sit ahead of the read every branch needs, | |
| 5832 | + // and a slow or lock-blocked speculative query would gate it. Under | |
| 5833 | + // a pathologically small budget override (single digits — a test | |
| 5834 | + // harness setting; 1-2 deadlocks the effect run loop itself) the | |
| 5835 | + // inline launch can park early and a speculative read may issue | |
| 5836 | + // first; that bounded case is accepted rather than suppressed, | |
| 5837 | + // because the only known suppression (a fiber-lifetime | |
| 5838 | + // `PreventSchedulerYield`) is inherited by everything the child runs | |
| 5839 | + // and provably keeps effect timeouts from firing across CPU-bound | |
| 5840 | + // stretches. | |
| 5836 | 5841 | const toolRowFiber = yield* Effect.forkChild( |
| 5837 | 5842 | core.findFirst("tool", { |
| 5838 | 5843 | where: (b: AnyCb) => |