Skip to content

Commit

Permalink
fix: async tasks could lose the app context
Browse files Browse the repository at this point in the history
We set and unset the app context in various places, which can cause
an async task to run when the context is not set.
In the case of setting a reactive variable, this will cause it
to assume the global context, which does not lead to a rerender.
  • Loading branch information
maartenbreddels committed Jun 23, 2023
1 parent a5d6b43 commit 99036cb
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 14 deletions.
9 changes: 4 additions & 5 deletions solara/server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,11 +472,10 @@ def on_msg(msg):
context = get_current_context()
import ipyvuetify

with context:
container = ipyvuetify.Html(tag="div")
context.container = container
load_app_widget(None, app, path)
comm.send({"method": "finished", "widget_id": context.container._model_id})
container = ipyvuetify.Html(tag="div")
context.container = container
load_app_widget(None, app, path)
comm.send({"method": "finished", "widget_id": context.container._model_id})
elif method == "check":
context = get_current_context()
elif method == "reload":
Expand Down
16 changes: 7 additions & 9 deletions solara/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,11 @@ async def app_loop(ws: websocket.WebsocketWrapper, session_id: str, connection_i
run_context = contextlib.nullcontext()

kernel = context.kernel
with run_context:
with run_context, context:
if user:
with context:
from solara_enterprise.auth import user as solara_user
from solara_enterprise.auth import user as solara_user

solara_user.set(user)
solara_user.set(user)

while True:
try:
Expand All @@ -144,11 +143,10 @@ async def app_loop(ws: websocket.WebsocketWrapper, session_id: str, connection_i
else:
msg = deserialize_binary_message(message)
t1 = time.time()
with context:
process_kernel_messages(kernel, msg)
t2 = time.time()
if settings.main.timing:
print(f"timing: total={t2-t0:.3f}s, deserialize={t1-t0:.3f}s, kernel={t2-t1:.3f}s") # noqa: T201
process_kernel_messages(kernel, msg)
t2 = time.time()
if settings.main.timing:
print(f"timing: total={t2-t0:.3f}s, deserialize={t1-t0:.3f}s, kernel={t2-t1:.3f}s") # noqa: T201


def process_kernel_messages(kernel: Kernel, msg: Dict):
Expand Down
29 changes: 29 additions & 0 deletions tests/integration/async_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import asyncio
from pathlib import Path

import playwright.sync_api

import solara
import solara.server.starlette

HERE = Path(__file__).parent


@solara.component
def Page():
def run_async():
async def some_task():
await asyncio.sleep(0.01)
label.value = "asyncio run"

asyncio.create_task(some_task())

label = solara.use_reactive("initial")
solara.Button(label.value, on_click=run_async)


def test_async_callback(page_session: playwright.sync_api.Page, solara_app, extra_include_path, solara_server):
with extra_include_path(HERE), solara_app("async_test"):
page_session.goto(solara_server.base_url + "/")
page_session.locator("text=initial").click()
page_session.locator("text=asyncio run").wait_for()

0 comments on commit 99036cb

Please sign in to comment.