From 165fe1d388af46c92ba4e2585d998d20b3261f88 Mon Sep 17 00:00:00 2001 From: Josh Taillon Date: Fri, 2 Oct 2026 15:20:37 -0400 Subject: [PATCH] docs(py): Explain why on_response() is safe without a lock The docstring said Shiny serializes effects behind a process-wide reactive.lock(). Shiny no longer takes that lock (posit-dev/py-shiny#2508) and is deprecating it (posit-dev/py-shiny#2520). State the guarantees that keep this method safe in both the current and the upcoming Shiny. --- pkg-py/src/shinychat/_history.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pkg-py/src/shinychat/_history.py b/pkg-py/src/shinychat/_history.py index 8e2f57871..f8c67ffcf 100644 --- a/pkg-py/src/shinychat/_history.py +++ b/pkg-py/src/shinychat/_history.py @@ -511,9 +511,12 @@ async def on_response(self) -> None: The server-side message accumulator and recorded turns are read before writing the record. Reads and writes are separated by awaits (``store.put``, eviction, bookmark mint), but this is safe without an - explicit lock because Shiny serializes reactive flushes behind a - single process-wide ``reactive.lock()`` for the full duration of - effect execution. + explicit lock. Shiny never starts a run of an effect while its previous + run is still going, so two calls from ``_save_on_response`` can't + overlap. The other effects that change ``self.record`` are triggered by + client inputs, and Shiny holds input changes until all of the session's + effects have finished, so they can't run while this one is paused at an + ``await``. """ if self.partition is None: raise RuntimeError("HistoryController not initialized")