57 lines
1.8 KiB
TypeScript
57 lines
1.8 KiB
TypeScript
/**
|
|
* Shared capacity-wake primitive for bridge poll loops.
|
|
*
|
|
* Both replBridge.ts and bridgeMain.ts need to sleep while "at capacity"
|
|
* but wake early when either (a) the outer loop signal aborts (shutdown),
|
|
* or (b) capacity frees up (session done / transport lost). This module
|
|
* encapsulates the mutable wake-controller + two-signal merger that both
|
|
* poll loops previously duplicated byte-for-byte.
|
|
*/
|
|
|
|
export type CapacitySignal = { signal: AbortSignal; cleanup: () => void }
|
|
|
|
export type CapacityWake = {
|
|
/**
|
|
* Create a signal that aborts when either the outer loop signal or the
|
|
* capacity-wake controller fires. Returns the merged signal and a cleanup
|
|
* function that removes listeners when the sleep resolves normally
|
|
* (without abort).
|
|
*/
|
|
signal(): CapacitySignal
|
|
/**
|
|
* Abort the current at-capacity sleep and arm a fresh controller so the
|
|
* poll loop immediately re-checks for new work.
|
|
*/
|
|
wake(): void
|
|
}
|
|
|
|
export function createCapacityWake(outerSignal: AbortSignal): CapacityWake {
|
|
let wakeController = new AbortController()
|
|
|
|
function wake(): void {
|
|
wakeController.abort()
|
|
wakeController = new AbortController()
|
|
}
|
|
|
|
function signal(): CapacitySignal {
|
|
const merged = new AbortController()
|
|
const abort = (): void => merged.abort()
|
|
if (outerSignal.aborted || wakeController.signal.aborted) {
|
|
merged.abort()
|
|
return { signal: merged.signal, cleanup: () => {} }
|
|
}
|
|
outerSignal.addEventListener('abort', abort, { once: true })
|
|
const capSig = wakeController.signal
|
|
capSig.addEventListener('abort', abort, { once: true })
|
|
return {
|
|
signal: merged.signal,
|
|
cleanup: () => {
|
|
outerSignal.removeEventListener('abort', abort)
|
|
capSig.removeEventListener('abort', abort)
|
|
},
|
|
}
|
|
}
|
|
|
|
return { signal, wake }
|
|
}
|