4 ms·
I didn’t have time to work up a repro, but the issue is a classic one with the basic algorithm you use for your ComputeSignal graph. The issue is that during th
by jitl 2y ago
I didn’t have time to work up a repro, but the issue is a classic one with the basic algorithm you use for your ComputeSignal graph. The issue is that during the fan-out after a change at a root, a ComputeSignal that’s recomputing can read a stale out of date value from a ComputeSignal that has not yet recomputed for the change.
The simplest solution to implement is to do two phase propagation, the first phase marks all ComputeSignal as “dirty” so any read of them must re-compute. Then in the second phase you do what you’re already doing which is to walk down, re-computing, and stop at ComputeSignals that didn’t change. There are other approaches like using a logical clock that have different balances between time complexity at write time and time complexity at read time.
Besides the correctness issue, the eager depth first strategy can re-compute the same ComputeSignal multiple times for a single change to a root. This can also be solved with the dirty phase, because once a dirty ComputeSignal becomes clean you don’t need to re-compute it again during that write’s fan-out.
- jitl 2y agoShiny from the above commenter is a good example of the dirty / “invalidate” style of algorithm. https://github.com/posit-dev/py-shiny/blob/main/shiny/reactive/_reactives.py https://github.com/posit-dev/py-shiny/blob/main/shiny/reacti... https://github.com/posit-dev/py-shiny/blob/main/shiny/reactive/_core.py https://github.com/posit-dev/py-shiny/blob/main/shiny/reacti...