(
self: Atom.Atom<AsyncResult.AsyncResult<A, E>>,
opts: AtomQueryOptions = {}
)
| 349 | // We only guarantee that a *genuine* new/parallel/future observer is never stuck on a departed |
| 350 | // observer's interrupt: per family atom we count live computes (`inFlight`), so "stuck" = a `waiting` |
| 351 | // result with `inFlight === 0` (nothing is actually fetching). On mount a stuck atom triggers one |
| 352 | // fresh fetch instead of adopting the dangling `waiting`; a genuinely in-flight fetch (`inFlight > 0`) |
| 353 | // is joined, not superseded (dedup / re-entrancy preserved). `recovering` dedupes concurrent mounts |
| 354 | // so exactly one recovery fetch is issued until a fetch is running again. |
| 355 | export interface QueryFetchState { |
| 356 | inFlight: number |
| 357 | recovering: boolean |
| 358 | } |
| 359 | export const queryFetchStates = new WeakMap<Atom.Atom<any>, QueryFetchState>() |
| 360 | |
| 361 | const recoverStuckWaitingOnMount = |
| 362 | <A, E>(familyAtom: Atom.Atom<AsyncResult.AsyncResult<A, E>>) => |
| 363 | (wrapped: Atom.Atom<AsyncResult.AsyncResult<A, E>>): Atom.Atom<AsyncResult.AsyncResult<A, E>> => |
| 364 | Atom.transform(wrapped, (get) => { |
| 365 | const current = get.once(wrapped) |
| 366 | get.subscribe(wrapped, (value) => get.setSelf(value)) |
| 367 | const state = queryFetchStates.get(familyAtom) |
| 368 | const waiting = current?.waiting === true |
| 369 | // Stuck: the result says `waiting` yet nothing is in-flight — an interrupt was hidden and left |
| 370 | // `waiting` dangling. Treat it as not-yet-fetched and refetch; a live fetch (`inFlight > 0`) is |
| 371 | // joined, not superseded. `recovering` prevents concurrent mounts from issuing more than one |
searching dependent graphs…