Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REF-3184] All my rx.background don't work on 0.5.5 #3554

Closed
fungalspores opened this issue Jun 25, 2024 · 5 comments · Fixed by #3696
Closed

[REF-3184] All my rx.background don't work on 0.5.5 #3554

fungalspores opened this issue Jun 25, 2024 · 5 comments · Fixed by #3696
Assignees
Labels
bug Something isn't working high priority linear Created by Linear-GitHub Sync
Milestone

Comments

@fungalspores
Copy link

fungalspores commented Jun 25, 2024

Hello everyone

All my rx.background don't work on 0.5.5

You can try make any foreach with rx.background and yield Anystate.do_this and it won't work

I can show my code to DM any contributors

REF-3184

@fungalspores fungalspores added the bug Something isn't working label Jun 25, 2024
@Lendemor Lendemor added high priority linear Created by Linear-GitHub Sync labels Jun 25, 2024
@Lendemor Lendemor changed the title All my rx.background don't work on 0.5.5 [REF-3184] All my rx.background don't work on 0.5.5 Jun 25, 2024
@Lendemor Lendemor modified the milestones: Open Source Bugs, v.40 Jun 25, 2024
@Lendemor Lendemor modified the milestones: v.40, v.41 Jun 30, 2024
@masenf
Copy link
Collaborator

masenf commented Jul 2, 2024

@fungalspores can you share your code with me, [email protected]. Or share a minimal reproducer here in this issue.

I'm not able to reproduce the issue with the following code

import asyncio
import reflex as rx


class MyTaskState(rx.State):
    counter: int = 0
    max_counter: int = 10
    running: bool = False
    _n_tasks: int = 0

    def foo(self):
        print("foo")

    @rx.background
    async def my_task(self):
        async with self:
            # The latest state values are always available inside the context
            if self._n_tasks > 0:
                # only allow 1 concurrent task
                return

            # State mutation is only allowed inside context block
            self._n_tasks += 1

        while True:
            async with self:
                # Check for stopping conditions inside context
                if self.counter >= self.max_counter:
                    self.running = False
                if not self.running:
                    self._n_tasks -= 1
                    return

                self.counter += 1
                yield MyTaskState.foo

            # Await long operations outside the context to avoid blocking UI
            await asyncio.sleep(0.5)

    def toggle_running(self):
        self.running = not self.running
        if self.running:
            return MyTaskState.my_task

    def clear_counter(self):
        self.counter = 0


def background_task_example():
    return rx.hstack(
        rx.heading(MyTaskState.counter, " /"),
        rx.chakra.number_input(
            value=MyTaskState.max_counter,
            on_change=MyTaskState.set_max_counter,
            width="8em",
        ),
        rx.button(
            rx.cond(~MyTaskState.running, "Start", "Stop"),
            on_click=MyTaskState.toggle_running,
        ),
        rx.button(
            "Reset",
            on_click=MyTaskState.clear_counter,
        ),
    )

I think I'm missing the part about the foreach, not sure how that looks for the issue you are hitting.

@seewindcn
Copy link
Contributor

about return MyTaskState.my_task code, I have another question:
In my memory, function toggle_running return MyTaskState.my_task, will send a message to web page, and then web page's applyEvent send back to server, and server run my_task in _process_background.
my question: can it be more direct no through the web? or is there a function maybe name run_tasks can use to direct run a backgroup task? @masenf

@Lendemor Lendemor modified the milestones: v.41, v.42 Jul 7, 2024
@fungalspores
Copy link
Author

@fungalspores can you share your code with me, [email protected]. Or share a minimal reproducer here in this issue.

I'm not able to reproduce the issue with the following code

import asyncio
import reflex as rx


class MyTaskState(rx.State):
    counter: int = 0
    max_counter: int = 10
    running: bool = False
    _n_tasks: int = 0

    def foo(self):
        print("foo")

    @rx.background
    async def my_task(self):
        async with self:
            # The latest state values are always available inside the context
            if self._n_tasks > 0:
                # only allow 1 concurrent task
                return

            # State mutation is only allowed inside context block
            self._n_tasks += 1

        while True:
            async with self:
                # Check for stopping conditions inside context
                if self.counter >= self.max_counter:
                    self.running = False
                if not self.running:
                    self._n_tasks -= 1
                    return

                self.counter += 1
                yield MyTaskState.foo

            # Await long operations outside the context to avoid blocking UI
            await asyncio.sleep(0.5)

    def toggle_running(self):
        self.running = not self.running
        if self.running:
            return MyTaskState.my_task

    def clear_counter(self):
        self.counter = 0


def background_task_example():
    return rx.hstack(
        rx.heading(MyTaskState.counter, " /"),
        rx.chakra.number_input(
            value=MyTaskState.max_counter,
            on_change=MyTaskState.set_max_counter,
            width="8em",
        ),
        rx.button(
            rx.cond(~MyTaskState.running, "Start", "Stop"),
            on_click=MyTaskState.toggle_running,
        ),
        rx.button(
            "Reset",
            on_click=MyTaskState.clear_counter,
        ),
    )

I think I'm missing the part about the foreach, not sure how that looks for the issue you are hitting.

I wrote to your mail and try added to discord friend for faster communication

@Lendemor Lendemor modified the milestones: v.42, v.43 Jul 14, 2024
@Ernelene
Copy link

I had a similar issue: I was able to resolve it by removing the nested async with self:

 @rx.background
 async def fetch_data(self):
        async with self:
            p = await self.get_state(PState)
            self.p_id = p.get_current_p_id 
            if self.p_id == "":
                return rx.redirect("/ws")
            wf = await self.fetch_flow()
            self.wf_id = wf
            while self.wf_status != "Completed":
                wf_status = await self.fetch_flow_run_id()
                async with self:
                    self.wf_status = wf_status["state"]
....

Previously I had an issue if the state not updating in my while -> so I added the extra async with self: in the while loop. Now with the new update the state did not want to update because of the extra async with self: so I removed it.
In my case if you add print statements you will see everything updating up to the second async with self and then not updating after it.

@masenf
Copy link
Collaborator

masenf commented Jul 17, 2024

@Ernelene thank you for the insight!

It appears this issue was introduced by #3508 where i added locking around the async with self to avoid concurrent access

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working high priority linear Created by Linear-GitHub Sync
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants