widgetti / solara

A Pure Python, React-style Framework for Scaling Your Jupyter and Web Apps
https://solara.dev
MIT License
1.65k stars 114 forks source link

task decorator & cancelled error #508

Open swelborn opened 3 months ago

swelborn commented 3 months ago

Hello! Nice work on this. very cool.

I am using (potentially misusing) the task decorator functionality, and I am getting the errors below. Using bleeding edge version. You can see it takes a few times of sliding the slider until it errors. Maybe because Im creating so many tasks? Tried wrapping different parts of the code in try/excepts to no avail.

from solara.lab import task
from reacton import use_state
import numpy as np
import solara

@task()
async def debounce_update(value):
    await asyncio.sleep(1)
    return value

@solara.component
def Page():
    im_idx, set_im_idx = use_state(0)
    plotly_im_idx, set_plotly_im_idx = use_state(0)

    def on_slider_change(value):
        set_im_idx(value)
        if debounce_update.pending:
            debounce_update.cancel()
        debounce_update(value)

    if debounce_update.finished:
        new_idx = debounce_update.value
        if new_idx == im_idx:
            set_plotly_im_idx(new_idx)

    slider = solara.SliderInt(
        label="Image Index",
        min=0,
        max=len(image_data) - 1,
        step=1,
        value=im_idx,
        on_value=on_slider_change,
    )

    with solara.Card() as main:
        solara.VBox([slider])
        if debounce_update.finished:
            print("finished")
        if debounce_update.cancelled:
            print("cancelled")
        if debounce_update.pending:
            print("pending")
        if debounce_update.error:
            print("ERRRRRROOOOOOOR")
    return main
Details

pending pending pending pending pending pending pending pending pending pending pending pending pending pending pending pending pending pending pending pending pending pending pending pending finished finished pending pending pending pending pending pending pending pending pending pending pending pending pending pending pending finished finished pending pending pending pending pending pending pending pending Future exception was never retrieved future: Traceback (most recent call last): File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/solara/tasks.py", line 235, in runs_in_thread thread_event_loop.run_until_complete(current_task) File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete return future.result() ^^^^^^^^^^^^^^^ File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/solara/tasks.py", line 292, in _async_run await runner() File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/solara/tasks.py", line 266, in runner self._last_value = value = await self.function(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/swelborn/Documents/gits/tomopyui/sol.py", line 36, in debounce_update await asyncio.sleep(1) File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/asyncio/tasks.py", line 649, in sleep return await future ^^^^^^^^^^^^ asyncio.exceptions.CancelledError Future exception was never retrieved future: Traceback (most recent call last): File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/solara/tasks.py", line 235, in runs_in_thread thread_event_loop.run_until_complete(current_task) File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete return future.result() ^^^^^^^^^^^^^^^ File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/solara/tasks.py", line 292, in _async_run await runner() File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/solara/tasks.py", line 266, in runner self._last_value = value = await self.function(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/swelborn/Documents/gits/tomopyui/sol.py", line 36, in debounce_update await asyncio.sleep(1) File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/asyncio/tasks.py", line 649, in sleep return await future ^^^^^^^^^^^^ asyncio.exceptions.CancelledError Future exception was never retrieved future: Traceback (most recent call last): File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/solara/tasks.py", line 235, in runs_in_thread thread_event_loop.run_until_complete(current_task) File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete return future.result() ^^^^^^^^^^^^^^^ File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/solara/tasks.py", line 292, in _async_run await runner() File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/solara/tasks.py", line 266, in runner self._last_value = value = await self.function(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/swelborn/Documents/gits/tomopyui/sol.py", line 36, in debounce_update await asyncio.sleep(1) File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/asyncio/tasks.py", line 649, in sleep return await future ^^^^^^^^^^^^ asyncio.exceptions.CancelledError finished finished

maartenbreddels commented 3 months ago

Hi,

thanks you for the report, and very interesting use case, I like it! I would say this is appropriate use, the only think you shouldn't do is:

        if debounce_update.pending:
            debounce_update.cancel()

Sine that is implicitly done if you restart the task.

The printing of the exception is due to the automatic cancelling, and something not easily fixed.

The workaround for now is to use:

@task(prefer_threaded=False)

Let me know if that solves your problem.

Regards,

Maarten

swelborn commented 3 months ago

That fixes it, and thanks for the info on implicit canceling on restart. Shall I close the issue or keep it open?

maartenbreddels commented 3 months ago

We can keep it open, since there is still an issue with the printing