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

"Server is busy" caused by slow build of flow. #3878

Closed
9n opened this issue Sep 22, 2024 · 2 comments · Fixed by #3895
Closed

"Server is busy" caused by slow build of flow. #3878

9n opened this issue Sep 22, 2024 · 2 comments · Fixed by #3895
Assignees
Labels
bug Something isn't working

Comments

@9n
Copy link
Contributor

9n commented Sep 22, 2024

截图 2024-09-22 12-17-53

A slow flow build will block the entire server, I experienced this issue in 1.0.17 and 1.0.18.

I notice an similar issue #3812 was fixed in 1.0.18, but I can't find out which commit fixed #3812 (maybe the eventmanager?), and I think this is a different one.

By digging into the code, I find below code try to run build in a dedicated thread to void blocking the entire asgi server:

build_task = asyncio.create_task(await asyncio.to_thread(_build_vertex, vertex_id, graph, event_manager))

I think it should be build_task = asyncio.create_task(asyncio.to_thread(asyncio.run, _build_vertex(vertex_id, graph, event_manager))). Because _build_vertex is async.

I'm new to python, am I missing something?

@dosubot dosubot bot added the bug Something isn't working label Sep 22, 2024
Copy link

dosubot bot commented Sep 22, 2024

Hey @9n! 👋 I'm here to help you with any bugs, questions, or contributions. Let's tackle this together!

To resolve the "Server is busy" issue caused by a slow build of flow in versions 1.0.17 and 1.0.18, you can modify the asynchronous task creation in the Langflow repository. Your proposed modification to the asynchronous task creation is incorrect because asyncio.run is meant to run the top-level entry point of an asyncio program and cannot be used within an already running event loop.

The original implementation is appropriate for non-blocking behavior in an ASGI context:

build_task = asyncio.create_task(await asyncio.to_thread(_build_vertex, vertex_id, graph, event_manager))

This code correctly runs the _build_vertex function in a separate thread to prevent blocking the ASGI server.

Additionally, starting from version 0.5, Langflow introduces the sync flag, which allows users to opt for asynchronous processing of their flows. This can help free up resources and provide better control over long-running tasks. You can include the sync flag in the payload of your POST request to the /api/v1/process/<your_flow_id> endpoint. When set to false, the API will initiate an asynchronous task instead of processing the flow synchronously.

Example API request with the sync flag:

curl -X POST \
  http://localhost:3000/api/v1/process/<your_flow_id> \
  -H 'Content-Type: application/json' \
  -H 'x-api-key: <your_api_key>' \
  -d '{"inputs": {"text": ""}, "tweaks": {}, "sync": false}'

You can check the status of an asynchronous task by making a GET request to the /task/{task_id} endpoint:

curl -X GET \
  http://localhost:3000/api/v1/task/<task_id> \
  -H 'x-api-key: <your_api_key>'

This modification ensures that if the task fails to run in Celery, it will fall back to running the task locally, which can help mitigate the "Server is busy" issue [1][2].

To continue talking to Dosu, mention @dosu.

@9n
Copy link
Contributor Author

9n commented Sep 23, 2024

I have checked this issue out carefully, and I'm pretty sure it DOES exist.

There is a easy way to reproduce it:

  1. open 2 separate browser window to visit langflow
  2. In window 1, do 3 - 7:
  3. create a blank flow
  4. drag a "Text Input" component to the canvas
  5. edit the source code of "Text Input" component
  6. add time.sleep(100) to the first line of text_response method like below
    def text_response(self) -> Message:
    +   import time
    +   time.sleep(100)
        message = Message(
            text=self.input_value,
        )
        return message
  7. click the run button to build the component and wait for a while
  8. you will see Server is busy popup in window 2

In v1.0.18, there is a optimization in frontend that do not check health when running a build, so that window 1 will not popup Server is busy.
But in the backend the entire ASGI server is blocked, and can't process any request.

And code below should fix the issue, I have tried:
build_task = asyncio.create_task(asyncio.to_thread(asyncio.run, _build_vertex(vertex_id, graph, event_manager)))

9n pushed a commit to 9n/langflow that referenced this issue Sep 24, 2024
9n added a commit to 9n/langflow that referenced this issue Sep 24, 2024
9n added a commit to 9n/langflow that referenced this issue Sep 24, 2024
@ogabrielluiz ogabrielluiz linked a pull request Sep 24, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants