Description of the bug
I probably triggered this issue as a side effect of #24399 since that issue can lead to a situation where a cached signal detects that the underlying value has changed only when it's being read. I still suspect that the issue can also happen in other edge cases where something else happens that reads the cached signal before the regular cached signal invalidation happens.
java.lang.IllegalStateException: Infinite loop detected between effect updates. This effect is deactivated.
at com.vaadin.flow.signals.impl.Effect.onDependencyChange(Effect.java:225) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.Effect$1.invoke(Effect.java:210) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.CachedSignal$2$1.invoke(CachedSignal.java:179) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.AbstractSharedSignal$1$1.invoke(AbstractSharedSignal.java:506) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.impl.SignalTree.lambda$notifyObservers$1(SignalTree.java:292) ~[flow-server-25.1.5.jar:25.1.5]
at java.base/java.util.Map.forEach(Map.java:733) ~[na:na]
at com.vaadin.flow.signals.shared.impl.SignalTree.lambda$notifyObservers$6da5674f$1(SignalTree.java:278) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.impl.SignalTree.runWithLock(SignalTree.java:210) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.impl.SignalTree.notifyObservers(SignalTree.java:277) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.impl.SynchronousSignalTree$1.publishChanges(SynchronousSignalTree.java:89) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.impl.SignalTree.lambda$commitSingleCommand$5e536215$1(SignalTree.java:339) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.impl.SignalTree.runWithLock(SignalTree.java:210) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.impl.SignalTree.commitSingleCommand(SignalTree.java:335) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.Transaction$ImmediateTransaction.include(Transaction.java:64) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.Transaction$RepeatableReadTransaction.include(Transaction.java:110) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.Transaction.include(Transaction.java:478) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.AbstractSharedSignal.submit(AbstractSharedSignal.java:324) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.AbstractSharedSignal.submitVoidOperation(AbstractSharedSignal.java:358) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.AbstractSharedSignal.submit(AbstractSharedSignal.java:414) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.CachedSignal.getValidState(CachedSignal.java:222) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.CachedSignal.extractValue(CachedSignal.java:257) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.shared.AbstractSharedSignal.get(AbstractSharedSignal.java:189) ~[flow-server-25.1.5.jar:25.1.5]
at com.example.demo.MainView.lambda$9(MainView.java:69) ~[classes/:na]
at com.vaadin.flow.dom.ElementEffect$1.execute(ElementEffect.java:259) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.dom.ElementEffect.executeAction(ElementEffect.java:125) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.Effect.lambda$new$ac508a99$1(Effect.java:141) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.UsageTracker.lambda$track$0(UsageTracker.java:221) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.UsageTracker.track(UsageTracker.java:247) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.UsageTracker.track(UsageTracker.java:220) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.Effect.revalidate(Effect.java:187) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.Effect.invalidate(Effect.java:260) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.signals.impl.Effect.lambda$scheduleInvalidate$2(Effect.java:247) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.component.UI.accessSynchronously(UI.java:504) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.component.UI$2.execute(UI.java:575) ~[flow-server-25.1.5.jar:25.1.5]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) ~[na:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) ~[na:na]
at com.vaadin.flow.server.VaadinService.runPendingAccessTasks(VaadinService.java:2340) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.server.VaadinSession.unlock(VaadinSession.java:790) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.server.VaadinService.ensureAccessQueuePurged(VaadinService.java:2304) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.server.VaadinService.accessSession(VaadinService.java:2271) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.server.VaadinSession.access(VaadinSession.java:1095) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.component.UI.access(UI.java:572) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.component.UI.access(UI.java:555) ~[flow-server-25.1.5.jar:25.1.5]
at com.vaadin.flow.dom.ElementEffect.lambda$enableEffect$0(ElementEffect.java:307) ~[flow-server-25.1.5.jar:25.1.5]
Expected behavior
Effect invocations that are indirectly triggered by an effect reading a cached signal should somehow be ignored for the purpose of detecting infinite loops between effects.
Minimal reproducible example
I do unfortunately not have an easily shared reliable reproduction case
Versions
- Vaadin / Flow version: Vaadin 25.1.5
Description of the bug
I probably triggered this issue as a side effect of #24399 since that issue can lead to a situation where a cached signal detects that the underlying value has changed only when it's being read. I still suspect that the issue can also happen in other edge cases where something else happens that reads the cached signal before the regular cached signal invalidation happens.
Expected behavior
Effect invocations that are indirectly triggered by an effect reading a cached signal should somehow be ignored for the purpose of detecting infinite loops between effects.
Minimal reproducible example
I do unfortunately not have an easily shared reliable reproduction case
Versions