fix: display errors when webhook background tasks fail (#7572)
* 📝 (base.py): improve naming convention for task names in Graph class 🔧 (base.py): add error logging functionality in _execute_tasks method 🔧 (utils.py): update data parameter type in log_vertex_build function 🔧 (index.tsx): remove unused setCurrentFlow function call in StoreCardComponent 🔧 (use-get-builds-polling-mutation.ts): add error handling and display logic for build failures 🔧 (flowSidebarComponent/index.tsx): make showLegacy prop optional in FlowSidebarComponentProps interface 🔧 (index.tsx): remove commented out code related to branding in FlowPage component * [autofix.ci] apply automated fixes * fix: update URL construction in CopyFieldAreaComponent to handle undefined endpointName - Modified the URL construction logic to use currentFlow.id when endpointName is not provided, ensuring a valid URL is always generated. * 🔧 (base.py): add error logging method for vertex build failures - Introduced `_log_vertex_build_from_exception` method to handle and log exceptions during vertex building, improving error reporting and output structure. - Updated `_execute_tasks` method to utilize the new logging method for better exception handling. * 🐛 (use-get-builds-polling-mutation.ts): fix error display count to only show errors once per build failure instead of multiple times * 📝 (embedding_model.py): improve formatting of the info message for the 'dimensions' input to enhance readability and clarity * [autofix.ci] apply automated fixes * fix: add webhook component handling in task execution --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
parent
c34b30718e
commit
eed7dee8bf
7 changed files with 114 additions and 62 deletions
|
|
@ -58,7 +58,8 @@ class EmbeddingModelComponent(LCEmbeddingsModel):
|
|||
IntInput(
|
||||
name="dimensions",
|
||||
display_name="Dimensions",
|
||||
info="The number of dimensions the resulting output embeddings should have.",
|
||||
info="The number of dimensions the resulting output embeddings should have. "
|
||||
"Only supported by certain models.",
|
||||
advanced=True,
|
||||
),
|
||||
IntInput(name="chunk_size", display_name="Chunk Size", advanced=True, value=1000),
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import copy
|
|||
import json
|
||||
import queue
|
||||
import threading
|
||||
import traceback
|
||||
import uuid
|
||||
from collections import defaultdict, deque
|
||||
from datetime import datetime, timezone
|
||||
|
|
@ -38,7 +39,7 @@ from langflow.graph.vertex.schema import NodeData, NodeTypeEnum
|
|||
from langflow.graph.vertex.vertex_types import ComponentVertex, InterfaceVertex, StateVertex
|
||||
from langflow.logging.logger import LogConfig, configure
|
||||
from langflow.schema.dotdict import dotdict
|
||||
from langflow.schema.schema import INPUT_FIELD_NAME, InputType
|
||||
from langflow.schema.schema import INPUT_FIELD_NAME, InputType, OutputValue
|
||||
from langflow.services.cache.utils import CacheMiss
|
||||
from langflow.services.deps import get_chat_service, get_tracing_service
|
||||
from langflow.utils.async_helpers import run_until_complete
|
||||
|
|
@ -1526,6 +1527,7 @@ class Graph:
|
|||
event_manager: EventManager | None = None,
|
||||
) -> Graph:
|
||||
"""Processes the graph with vertices in each layer run in parallel."""
|
||||
has_webhook_component = "webhook" in start_component_id.lower() if start_component_id else False
|
||||
first_layer = self.sort_vertices(start_component_id=start_component_id)
|
||||
vertex_task_run_count: dict[str, int] = {}
|
||||
to_process = deque(first_layer)
|
||||
|
|
@ -1549,14 +1551,16 @@ class Graph:
|
|||
set_cache=chat_service.set_cache,
|
||||
event_manager=event_manager,
|
||||
),
|
||||
name=f"{vertex.display_name} Run {vertex_task_run_count.get(vertex_id, 0)}",
|
||||
name=f"{vertex.id} Run {vertex_task_run_count.get(vertex_id, 0)}",
|
||||
)
|
||||
tasks.append(task)
|
||||
vertex_task_run_count[vertex_id] = vertex_task_run_count.get(vertex_id, 0) + 1
|
||||
|
||||
logger.debug(f"Running layer {layer_index} with {len(tasks)} tasks, {current_batch}")
|
||||
try:
|
||||
next_runnable_vertices = await self._execute_tasks(tasks, lock=lock)
|
||||
next_runnable_vertices = await self._execute_tasks(
|
||||
tasks, lock=lock, has_webhook_component=has_webhook_component
|
||||
)
|
||||
except Exception:
|
||||
logger.exception(f"Error executing tasks in layer {layer_index}")
|
||||
raise
|
||||
|
|
@ -1595,16 +1599,81 @@ class Graph:
|
|||
await set_cache_coro(data=self, lock=lock)
|
||||
return next_runnable_vertices
|
||||
|
||||
async def _execute_tasks(self, tasks: list[asyncio.Task], lock: asyncio.Lock) -> list[str]:
|
||||
"""Executes tasks in parallel, handling exceptions for each task."""
|
||||
async def _log_vertex_build_from_exception(self, vertex_id: str, result: Exception) -> None:
|
||||
"""Log a vertex build failure caused by an exception.
|
||||
|
||||
This method handles formatting and logging errors that occur during vertex building.
|
||||
It creates appropriate error output structures and logs the build failure.
|
||||
|
||||
Args:
|
||||
vertex_id: The ID of the vertex that failed to build
|
||||
result: The exception that caused the build failure
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
Side effects:
|
||||
- Logs the exception details
|
||||
- Creates error output structures
|
||||
- Calls log_vertex_build to record the failure
|
||||
"""
|
||||
if isinstance(result, ComponentBuildError):
|
||||
params = result.message
|
||||
tb = result.formatted_traceback
|
||||
else:
|
||||
from langflow.api.utils import format_exception_message
|
||||
|
||||
tb = traceback.format_exc()
|
||||
logger.exception("Error building Component")
|
||||
|
||||
params = format_exception_message(result)
|
||||
message = {"errorMessage": params, "stackTrace": tb}
|
||||
vertex = self.get_vertex(vertex_id)
|
||||
output_label = vertex.outputs[0]["name"] if vertex.outputs else "output"
|
||||
outputs = {output_label: OutputValue(message=message, type="error")}
|
||||
result_data_response = {
|
||||
"results": {},
|
||||
"outputs": outputs,
|
||||
"logs": {},
|
||||
"message": {},
|
||||
"artifacts": {},
|
||||
"timedelta": None,
|
||||
"duration": None,
|
||||
"used_frozen_result": False,
|
||||
}
|
||||
|
||||
await log_vertex_build(
|
||||
flow_id=self.flow_id or "",
|
||||
vertex_id=vertex_id or "errors",
|
||||
valid=False,
|
||||
params=params,
|
||||
data=result_data_response,
|
||||
artifacts={},
|
||||
)
|
||||
|
||||
async def _execute_tasks(
|
||||
self, tasks: list[asyncio.Task], lock: asyncio.Lock, *, has_webhook_component: bool = False
|
||||
) -> list[str]:
|
||||
"""Executes tasks in parallel, handling exceptions for each task.
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to execute
|
||||
lock: Async lock for synchronization
|
||||
has_webhook_component: Whether the graph has a webhook component
|
||||
"""
|
||||
results = []
|
||||
completed_tasks = await asyncio.gather(*tasks, return_exceptions=True)
|
||||
vertices: list[Vertex] = []
|
||||
|
||||
for i, result in enumerate(completed_tasks):
|
||||
task_name = tasks[i].get_name()
|
||||
vertex_id = tasks[i].get_name().split(" ")[0]
|
||||
|
||||
if isinstance(result, Exception):
|
||||
logger.error(f"Task {task_name} failed with exception: {result}")
|
||||
if has_webhook_component:
|
||||
await self._log_vertex_build_from_exception(vertex_id, result)
|
||||
|
||||
# Cancel all remaining tasks
|
||||
for t in tasks[i + 1 :]:
|
||||
t.cancel()
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ async def log_vertex_build(
|
|||
vertex_id: str,
|
||||
valid: bool,
|
||||
params: Any,
|
||||
data: ResultDataResponse,
|
||||
data: ResultDataResponse | dict,
|
||||
artifacts: dict | None = None,
|
||||
) -> None:
|
||||
try:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue