/ bridge / capacityWake.ts
capacityWake.ts
 1  /**
 2   * Shared capacity-wake primitive for bridge poll loops.
 3   *
 4   * Both replBridge.ts and bridgeMain.ts need to sleep while "at capacity"
 5   * but wake early when either (a) the outer loop signal aborts (shutdown),
 6   * or (b) capacity frees up (session done / transport lost). This module
 7   * encapsulates the mutable wake-controller + two-signal merger that both
 8   * poll loops previously duplicated byte-for-byte.
 9   */
10  
11  export type CapacitySignal = { signal: AbortSignal; cleanup: () => void }
12  
13  export type CapacityWake = {
14    /**
15     * Create a signal that aborts when either the outer loop signal or the
16     * capacity-wake controller fires. Returns the merged signal and a cleanup
17     * function that removes listeners when the sleep resolves normally
18     * (without abort).
19     */
20    signal(): CapacitySignal
21    /**
22     * Abort the current at-capacity sleep and arm a fresh controller so the
23     * poll loop immediately re-checks for new work.
24     */
25    wake(): void
26  }
27  
28  export function createCapacityWake(outerSignal: AbortSignal): CapacityWake {
29    let wakeController = new AbortController()
30  
31    function wake(): void {
32      wakeController.abort()
33      wakeController = new AbortController()
34    }
35  
36    function signal(): CapacitySignal {
37      const merged = new AbortController()
38      const abort = (): void => merged.abort()
39      if (outerSignal.aborted || wakeController.signal.aborted) {
40        merged.abort()
41        return { signal: merged.signal, cleanup: () => {} }
42      }
43      outerSignal.addEventListener('abort', abort, { once: true })
44      const capSig = wakeController.signal
45      capSig.addEventListener('abort', abort, { once: true })
46      return {
47        signal: merged.signal,
48        cleanup: () => {
49          outerSignal.removeEventListener('abort', abort)
50          capSig.removeEventListener('abort', abort)
51        },
52      }
53    }
54  
55    return { signal, wake }
56  }