8607d6a52a
Track pending starts, pre-claim children, and teardown removed from routing. Bound cleanup and cancel setup/update waits while preserving settled remote descriptors. Co-authored-by: Gille <4317663+helix4u@users.noreply.github.com> Co-authored-by: ChanPark03 <parkchan0302@gmail.com>
111 lines
2.6 KiB
TypeScript
111 lines
2.6 KiB
TypeScript
export type BackendConnectionAttempt<TConnection> = {
|
|
generation: number
|
|
promise: Promise<TConnection> | null
|
|
}
|
|
|
|
export type BackendProcessOwner<TProcess> = {
|
|
generation: number
|
|
process: TProcess
|
|
}
|
|
|
|
export function createBackendConnectionState<TProcess, TConnection>() {
|
|
let generation = 0
|
|
let process: TProcess | null = null
|
|
let promise: Promise<TConnection> | null = null
|
|
let pendingPromise: Promise<TConnection> | null = null
|
|
|
|
return {
|
|
startAttempt(): BackendConnectionAttempt<TConnection> {
|
|
return { generation, promise: null }
|
|
},
|
|
|
|
setPromise(attempt: BackendConnectionAttempt<TConnection>, nextPromise: Promise<TConnection>): boolean {
|
|
if (attempt.generation !== generation) {
|
|
return false
|
|
}
|
|
|
|
attempt.promise = nextPromise
|
|
promise = nextPromise
|
|
pendingPromise = nextPromise
|
|
|
|
void nextPromise.then(
|
|
() => {
|
|
if (attempt.generation === generation && promise === nextPromise) {
|
|
pendingPromise = null
|
|
}
|
|
},
|
|
() => {
|
|
if (attempt.generation === generation && promise === nextPromise) {
|
|
pendingPromise = null
|
|
}
|
|
}
|
|
)
|
|
|
|
return true
|
|
},
|
|
|
|
isCurrentAttempt(attempt: BackendConnectionAttempt<TConnection>): boolean {
|
|
return attempt.generation === generation
|
|
},
|
|
|
|
attachProcess(
|
|
attempt: BackendConnectionAttempt<TConnection>,
|
|
nextProcess: TProcess
|
|
): BackendProcessOwner<TProcess> | null {
|
|
if (attempt.generation !== generation) {
|
|
return null
|
|
}
|
|
|
|
process = nextProcess
|
|
|
|
return { generation, process: nextProcess }
|
|
},
|
|
|
|
clearForCurrentProcess(owner: BackendProcessOwner<TProcess>): boolean {
|
|
if (owner.generation !== generation || owner.process !== process) {
|
|
return false
|
|
}
|
|
|
|
process = null
|
|
promise = null
|
|
pendingPromise = null
|
|
|
|
return true
|
|
},
|
|
|
|
clearPromiseForAttempt(attempt: BackendConnectionAttempt<TConnection>): boolean {
|
|
if (attempt.generation !== generation || (promise !== null && attempt.promise !== promise)) {
|
|
return false
|
|
}
|
|
|
|
promise = null
|
|
pendingPromise = null
|
|
|
|
return true
|
|
},
|
|
|
|
getProcess(): TProcess | null {
|
|
return process
|
|
},
|
|
|
|
getPromise(): Promise<TConnection> | null {
|
|
return promise
|
|
},
|
|
|
|
getPendingPromise(): Promise<TConnection> | null {
|
|
return pendingPromise
|
|
},
|
|
|
|
invalidate(): TProcess | null {
|
|
const currentProcess = process
|
|
|
|
generation += 1
|
|
process = null
|
|
promise = null
|
|
pendingPromise = null
|
|
|
|
return currentProcess
|
|
}
|
|
}
|
|
}
|