Skip to content

Conversation

@Cristhianzl
Copy link
Member

@Cristhianzl Cristhianzl commented Dec 15, 2025

This pull request introduces real-time Server-Sent Events (SSE) support for webhook-based flow execution, allowing the UI to receive live feedback about flow progress and results. It also updates the webhook execution logic to emit relevant events and improves the handling of session IDs in the ChatOutput component of the "Basic Prompt Chaining" starter project.

Webhook SSE and Event Emission Enhancements:

  • Added a new /webhook-events/{flow_id_or_name} SSE endpoint to stream real-time webhook execution events to the UI, including connection, progress, and heartbeat events. (src/backend/base/langflow/api/v1/endpoints.py)
  • Modified the webhook execution logic to emit structured events (vertices_sorted, end, and error events) before, after, and upon failure of a flow run. These events are sent via the new SSE mechanism if UI listeners are present. (src/backend/base/langflow/api/v1/endpoints.py) [1] [2] [3] [4]
  • Updated the webhook execution to use asyncio.create_task for background execution, ensuring compatibility with the SSE event loop and proper task lifecycle management. (src/backend/base/langflow/api/v1/endpoints.py)

Starter Project and Component Improvements:

  • Improved the ChatOutput component in the "Basic Prompt Chaining" starter project to better preserve and propagate the session_id from incoming messages, ensuring correct message history tracking. (src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json)
  • Updated the code_hash in the starter project metadata to reflect the new component logic. (src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json)

Summary by CodeRabbit

  • New Features

    • Webhook flows now stream real-time progress events to the UI via Server-Sent Events, enabling live build status and vertex execution tracking.
    • Live duration metrics and event emissions during webhook-driven flow execution with automatic UI listener detection.
    • Enhanced event broadcasting system for webhook callbacks with real-time status updates.
  • Documentation

    • Updated endpoint documentation for webhook streaming support and new parameters.

✏️ Tip: You can customize this high-level summary in your review settings.

@Cristhianzl Cristhianzl self-assigned this Dec 15, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 15, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This pull request adds real-time webhook event streaming support across the platform. It introduces a new WebhookEventManager for event broadcasting, an SSE endpoint for streaming webhook progress, a React hook to consume events, and integration points throughout the build pipeline (backend API, LFX) to emit events during vertex execution.

Changes

Cohort / File(s) Summary
Backend Event Manager
src/backend/base/langflow/services/event_manager.py
Introduces WebhookEventManager class with per-flow subscriber queue management, event emission with duration tracking, and a global singleton for use across the application.
Backend API Endpoints
src/backend/base/langflow/api/v1/endpoints.py
Adds webhook-events SSE endpoint for streaming flow progress; updates simple_run_flow_task to accept emit_events and flow_id parameters; modifies webhook_run_flow to detect UI listeners and emit events via asyncio task.
Backend Tests
src/backend/tests/unit/test_webhook.py
Adds comprehensive test coverage for WebhookEventManager including subscribe/unsubscribe, event emission, listener detection, and duration tracking.
Frontend Event Hook
src/frontend/src/hooks/use-webhook-events.ts
New React hook that establishes SSE connection, listens for webhook events (connected, vertices_sorted, build_start, end_vertex, end, error, heartbeat), and synchronizes state updates with flow store.
Frontend Build Polling Integration
src/frontend/src/controllers/API/queries/_builds/use-get-builds-polling-mutation.ts
Merges newly fetched vertex_builds with existing flow pool data from SSE, preserving duration values from prior event streams when polling data lacks them.
Frontend Flow Page Integration
src/frontend/src/pages/FlowPage/index.tsx
Imports and invokes useWebhookEvents hook to enable real-time webhook event listening on flow pages.
LFX Build Event Emission
src/lfx/src/lfx/graph/utils.py
src/lfx/src/lfx/graph/vertex/base.py
Adds webhook event emission during vertex build execution: records build_start events when reset, and emits comprehensive end_vertex events with results, duration, and metadata after build completion.

Sequence Diagram

sequenceDiagram
    participant Frontend as Frontend (React)
    participant SSE as SSE Endpoint
    participant EventMgr as WebhookEventManager
    participant Backend as Backend Task
    participant LFX as LFX Vertex Build
    
    Frontend->>SSE: GET /webhook-events/{flow_id}
    SSE->>EventMgr: subscribe(flow_id)
    EventMgr-->>SSE: return asyncio.Queue
    SSE-->>Frontend: connected event
    
    Note over Backend,LFX: Webhook execution triggered
    Backend->>Backend: webhook_run_flow()
    Backend->>Backend: check has_listeners(flow_id)
    
    alt UI Listeners Detected
        Backend->>Backend: asyncio.create_task(simple_run_flow_task)
        Backend->>EventMgr: emit(flow_id, vertices_sorted)
        EventMgr-->>SSE: queue.put(event)
        SSE-->>Frontend: vertices_sorted event
        
        Backend->>LFX: execute vertex.build()
        LFX->>EventMgr: record_build_start(flow_id, vertex_id)
        EventMgr-->>SSE: (internal tracking)
        
        LFX->>EventMgr: emit(flow_id, end_vertex, data)
        EventMgr-->>SSE: queue.put(event)
        SSE-->>Frontend: end_vertex event
        Frontend->>Frontend: update flow state
        
        LFX->>Backend: build complete
        Backend->>EventMgr: emit(flow_id, end, result)
        EventMgr-->>SSE: queue.put(event)
        SSE-->>Frontend: end event
        Frontend->>Frontend: finalize build state
    else No UI Listeners
        Backend->>Backend: fire-and-forget task
    end
    
    Frontend->>SSE: client disconnect
    SSE->>EventMgr: unsubscribe(flow_id, queue)
    EventMgr->>EventMgr: cleanup
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • WebhookEventManager implementation: Verify async queue handling, cleanup logic, and thread-safety of subscriber management
  • Event emission integration points: Confirm proper error handling (try/except blocks) and event data serialization across LFX and backend
  • SSE endpoint lifecycle: Check client disconnection handling, heartbeat mechanism, and cleanup to prevent memory leaks
  • Frontend-backend state synchronization: Validate event mapping to store updates, handling of duplicate polling and SSE data, and state consistency across multiple data sources
  • Duplicate test definitions: Review test file for intentional duplication or consolidation opportunities

Pre-merge checks and finishing touches

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Test Coverage For New Implementations ❌ Error PR adds WebhookEventManager, SSE endpoints, and frontend hooks but lacks comprehensive test coverage with no tests for new frontend hooks, insufficient backend tests, and duplicate test definitions noted. Add complete unit tests for WebhookEventManager methods, integration tests for webhook_events_stream endpoint, frontend tests for useWebhookEvents hook and polling mutation, LFX webhook tests, and remove duplicate test definitions.
Test Quality And Coverage ⚠️ Warning PR introduces WebhookEventManager, SSE endpoints, and useWebhookEvents hook but lacks comprehensive test coverage with gaps in API endpoint tests, frontend hook tests, and async pattern validation. Add tests for webhook_events_stream SSE endpoint, webhook_run_flow event emission, useWebhookEvents hook, remove duplicate test definitions, and include integration tests for end-to-end webhook execution.
Excessive Mock Usage Warning ⚠️ Warning PR summary explicitly reports duplicate test groups in test_webhook.py for WebhookEventManager tests, indicating poor test organization and maintenance. Remove duplicate test case copies to consolidate the test suite, ensuring each test scenario (subscribe/unsubscribe, emit, listener handling, duration tracking, multiple subscribers) appears exactly once.
Test File Naming And Structure ❓ Inconclusive Test file src/backend/tests/unit/test_webhook.py mentioned in PR summary does not exist in repository; cannot verify test naming or structure compliance. Confirm if test_webhook.py is included in PR. If missing, create it following pytest patterns with descriptive test names and comprehensive coverage for WebhookEventManager functionality.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main feature: adding real-time SSE support for webhook flow execution. It directly corresponds to the primary changes across the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 88.00% which is sufficient. The required threshold is 80.00%.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the enhancement New feature or request label Dec 15, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Dec 15, 2025

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 17%
16.6% (4686/28218) 9.99% (2179/21802) 10.91% (676/6193)

Unit Test Results

Tests Skipped Failures Errors Time
1829 0 💤 0 ❌ 0 🔥 23.965s ⏱️

@codecov
Copy link

codecov bot commented Dec 15, 2025

Codecov Report

❌ Patch coverage is 37.20930% with 162 lines in your changes missing coverage. Please review.
✅ Project coverage is 33.11%. Comparing base (056a76a) to head (b86e3ba).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/frontend/src/hooks/use-webhook-events.ts 0.00% 71 Missing ⚠️
src/lfx/src/lfx/graph/utils.py 14.28% 42 Missing ⚠️
src/backend/base/langflow/api/v1/endpoints.py 44.73% 21 Missing ⚠️
...queries/_builds/use-get-builds-polling-mutation.ts 0.00% 16 Missing ⚠️
...rc/backend/base/langflow/services/event_manager.py 87.34% 10 Missing ⚠️
src/frontend/src/pages/FlowPage/index.tsx 0.00% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##             main   #11028    +/-   ##
========================================
  Coverage   33.11%   33.11%            
========================================
  Files        1389     1391     +2     
  Lines       65685    65936   +251     
  Branches     9720     9746    +26     
========================================
+ Hits        21750    21835    +85     
- Misses      42821    42987   +166     
  Partials     1114     1114            
Flag Coverage Δ
backend 52.54% <73.50%> (+0.08%) ⬆️
frontend 15.30% <0.00%> (-0.05%) ⬇️
lfx 39.16% <19.23%> (-0.06%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/lfx/src/lfx/graph/vertex/base.py 57.38% <100.00%> (+0.17%) ⬆️
src/frontend/src/pages/FlowPage/index.tsx 0.00% <0.00%> (ø)
...rc/backend/base/langflow/services/event_manager.py 87.34% <87.34%> (ø)
...queries/_builds/use-get-builds-polling-mutation.ts 0.00% <0.00%> (ø)
src/backend/base/langflow/api/v1/endpoints.py 71.11% <44.73%> (-2.27%) ⬇️
src/lfx/src/lfx/graph/utils.py 25.68% <14.28%> (-4.17%) ⬇️
src/frontend/src/hooks/use-webhook-events.ts 0.00% <0.00%> (ø)

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Dec 15, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (7)
src/frontend/src/pages/FlowPage/index.tsx (1)

134-134: Remove or downgrade debug console.warn.

The console.warn("unmounting") should be removed for production code or converted to a debug-level log that can be conditionally disabled.

-			console.warn("unmounting");
src/backend/tests/unit/test_webhook.py (1)

62-62: Redundant imports inside test functions.

The from unittest.mock import patch is already imported at line 2. The imports inside test functions are redundant.

 async def test_webhook_endpoint_requires_api_key_when_auto_login_false(client, added_webhook_test):
     """Test that webhook endpoint requires API key when WEBHOOK_AUTH_ENABLE=true."""
-    # Mock the settings service to enable webhook authentication
-    from unittest.mock import patch
-
     with patch("langflow.services.auth.utils.get_settings_service") as mock_settings:

Also applies to: 102-102, 137-137, 157-157

src/lfx/src/lfx/graph/utils.py (1)

219-237: Inline serialization function works but could be extracted.

The serialize_for_json function correctly handles various types (primitives, dicts, lists, pydantic models). Consider extracting it to a module-level utility if this pattern is needed elsewhere.

src/frontend/src/hooks/use-webhook-events.ts (2)

36-39: Remove or conditionally disable console.log statements.

The console.log statements are useful for development but should be removed or wrapped in a debug flag for production builds.

-    console.log("[useWebhookEvents] Connecting to SSE:", sseUrl);
+    // Uncomment for debugging:
+    // console.log("[useWebhookEvents] Connecting to SSE:", sseUrl);

Also applies to: 44-46, 74-76, 91-93, 134-136


36-39: Add JSON.parse error handling for resilience.

The JSON.parse(event.data) calls in each event handler can throw if the server sends malformed data. Consider wrapping in try/catch.

     eventSource.addEventListener("connected", (event) => {
-      const data = JSON.parse(event.data);
-      console.log("[useWebhookEvents] Connected to flow:", data);
+      try {
+        const data = JSON.parse(event.data);
+        console.log("[useWebhookEvents] Connected to flow:", data);
+      } catch (e) {
+        console.error("[useWebhookEvents] Failed to parse connected event:", e);
+      }
     });

Apply similar pattern to other event handlers (vertices_sorted, build_start, end_vertex, end).

Also applies to: 44-46, 74-76, 91-93, 134-136

src/backend/base/langflow/services/event_manager.py (1)

36-38: Potential memory leak in _vertex_start_times if vertices fail before get_build_duration is called.

If a vertex build fails or is cancelled before get_build_duration is called, the start time entry will remain in _vertex_start_times indefinitely. Consider adding a TTL-based cleanup or explicit cleanup method for failed builds.

For long-running servers, you may want to add periodic cleanup:

def cleanup_stale_start_times(self, max_age_seconds: float = 3600) -> None:
    """Remove start times older than max_age_seconds."""
    current_time = time.time()
    for flow_id in list(self._vertex_start_times.keys()):
        for vertex_id, start_time in list(self._vertex_start_times[flow_id].items()):
            if current_time - start_time > max_age_seconds:
                self._vertex_start_times[flow_id].pop(vertex_id, None)
        if not self._vertex_start_times[flow_id]:
            del self._vertex_start_times[flow_id]
src/backend/base/langflow/api/v1/endpoints.py (1)

671-695: Consider using orjson instead of json for consistency.

The file already imports orjson at line 10. Using it here would provide consistency and slightly better performance for JSON serialization in the SSE event stream.

-    import json
-
     from langflow.services.event_manager import webhook_event_manager

     async def event_generator() -> AsyncGenerator[str, None]:
         """Generate SSE events from the webhook event manager."""
         flow_id_str = str(flow.id)
         queue = await webhook_event_manager.subscribe(flow_id_str)

         try:
             # Send initial connection event
-            yield f"event: connected\ndata: {json.dumps({'flow_id': flow_id_str, 'flow_name': flow.name})}\n\n"
+            yield f"event: connected\ndata: {orjson.dumps({'flow_id': flow_id_str, 'flow_name': flow.name}).decode()}\n\n"

             while True:
                 if await request.is_disconnected():
                     break

                 try:
                     event = await asyncio.wait_for(queue.get(), timeout=30.0)
                     event_type = event["event"]
-                    event_data = json.dumps(event["data"])
+                    event_data = orjson.dumps(event["data"]).decode()
                     yield f"event: {event_type}\ndata: {event_data}\n\n"
                 except asyncio.TimeoutError:
                     # Heartbeat
-                    yield f"event: heartbeat\ndata: {json.dumps({'timestamp': time.time()})}\n\n"
+                    yield f"event: heartbeat\ndata: {orjson.dumps({'timestamp': time.time()}).decode()}\n\n"
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 53015c1 and e40b8c3.

⛔ Files ignored due to path filters (1)
  • src/frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • src/backend/base/langflow/api/v1/endpoints.py (5 hunks)
  • src/backend/base/langflow/services/event_manager.py (1 hunks)
  • src/backend/tests/unit/test_webhook.py (1 hunks)
  • src/frontend/src/controllers/API/queries/_builds/use-get-builds-polling-mutation.ts (1 hunks)
  • src/frontend/src/hooks/use-webhook-events.ts (1 hunks)
  • src/frontend/src/pages/FlowPage/index.tsx (1 hunks)
  • src/lfx/src/lfx/graph/utils.py (1 hunks)
  • src/lfx/src/lfx/graph/vertex/base.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
src/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)

src/frontend/src/**/*.{ts,tsx}: Use React 18 with TypeScript for frontend development
Use Zustand for state management

Files:

  • src/frontend/src/controllers/API/queries/_builds/use-get-builds-polling-mutation.ts
  • src/frontend/src/hooks/use-webhook-events.ts
  • src/frontend/src/pages/FlowPage/index.tsx
src/frontend/src/**/{hooks,services}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)

Use the useApi hook for API calls with proper error handling, including loading state, error state, and exception throwing

Files:

  • src/frontend/src/hooks/use-webhook-events.ts
src/frontend/src/**/{services,hooks}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)

Use async/await pattern for API calls instead of .then() chains

Files:

  • src/frontend/src/hooks/use-webhook-events.ts
src/frontend/src/hooks/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)

Export hooks as custom hooks (useHookName) from the hooks/ directory

Files:

  • src/frontend/src/hooks/use-webhook-events.ts
src/backend/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

src/backend/**/*.py: Use FastAPI async patterns with await for async operations in component execution methods
Use asyncio.create_task() for background tasks and implement proper cleanup with try/except for asyncio.CancelledError
Use queue.put_nowait() for non-blocking queue operations and asyncio.wait_for() with timeouts for controlled get operations

Files:

  • src/backend/base/langflow/services/event_manager.py
  • src/backend/base/langflow/api/v1/endpoints.py
  • src/backend/tests/unit/test_webhook.py
src/backend/base/langflow/api/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

Backend API endpoints should be organized by version (v1/, v2/) under src/backend/base/langflow/api/ with specific modules for features (chat.py, flows.py, users.py, etc.)

Files:

  • src/backend/base/langflow/api/v1/endpoints.py
src/backend/tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)

src/backend/tests/**/*.py: Place backend unit tests in src/backend/tests/ directory, component tests in src/backend/tests/unit/components/ organized by component subdirectory, and integration tests accessible via make integration_tests
Use same filename as component with appropriate test prefix/suffix (e.g., my_component.pytest_my_component.py)
Use the client fixture (FastAPI Test Client) defined in src/backend/tests/conftest.py for API tests; it provides an async httpx.AsyncClient with automatic in-memory SQLite database and mocked environment variables. Skip client creation by marking test with @pytest.mark.noclient
Inherit from the correct ComponentTestBase family class located in src/backend/tests/base.py based on API access needs: ComponentTestBase (no API), ComponentTestBaseWithClient (needs API), or ComponentTestBaseWithoutClient (pure logic). Provide three required fixtures: component_class, default_kwargs, and file_names_mapping
Create comprehensive unit tests for all new backend components. If unit tests are incomplete, create a corresponding Markdown file documenting manual testing steps and expected outcomes
Test both sync and async code paths, mock external dependencies appropriately, test error handling and edge cases, validate input/output behavior, and test component initialization and configuration
Use @pytest.mark.asyncio decorator for async component tests and ensure async methods are properly awaited
Test background tasks using asyncio.create_task() and verify completion with asyncio.wait_for() with appropriate timeout constraints
Test queue operations using non-blocking queue.put_nowait() and asyncio.wait_for(queue.get(), timeout=...) to verify queue processing without blocking
Use @pytest.mark.no_blockbuster marker to skip the blockbuster plugin in specific tests
For database tests that may fail in batch runs, run them sequentially using uv run pytest src/backend/tests/unit/test_database.py r...

Files:

  • src/backend/tests/unit/test_webhook.py
**/test_*.py

📄 CodeRabbit inference engine (Custom checks)

**/test_*.py: Review test files for excessive use of mocks that may indicate poor test design - check if tests have too many mock objects that obscure what's actually being tested
Warn when mocks are used instead of testing real behavior and interactions, and suggest using real objects or test doubles when mocks become excessive
Ensure mocks are used appropriately for external dependencies only, not for core logic
Backend test files should follow the naming convention test_*.py with proper pytest structure
Test files should have descriptive test function names that explain what is being tested
Tests should be organized logically with proper setup and teardown
Consider including edge cases and error conditions for comprehensive test coverage
Verify tests cover both positive and negative scenarios where appropriate
For async functions in backend tests, ensure proper async testing patterns are used with pytest
For API endpoints, verify both success and error response testing

Files:

  • src/backend/tests/unit/test_webhook.py
src/frontend/src/**/*.{tsx,jsx,css,scss}

📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)

Use Tailwind CSS for styling

Files:

  • src/frontend/src/pages/FlowPage/index.tsx
src/frontend/src/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)

src/frontend/src/**/*.{tsx,jsx}: Implement dark mode support using the useDarkMode hook and dark store
Use Lucide React for icon components in the application

Files:

  • src/frontend/src/pages/FlowPage/index.tsx
🧠 Learnings (11)
📚 Learning: 2025-11-24T19:46:45.790Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:45.790Z
Learning: Applies to src/frontend/src/components/**/*.{tsx,jsx} : Use React Flow for flow graph visualization with Node, Edge, Controls, and Background components

Applied to files:

  • src/frontend/src/hooks/use-webhook-events.ts
  • src/frontend/src/pages/FlowPage/index.tsx
📚 Learning: 2025-11-24T19:46:45.790Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:45.790Z
Learning: Applies to src/frontend/src/hooks/**/*.{ts,tsx} : Export hooks as custom hooks (useHookName) from the hooks/ directory

Applied to files:

  • src/frontend/src/hooks/use-webhook-events.ts
📚 Learning: 2025-11-24T19:46:45.790Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:45.790Z
Learning: Applies to src/frontend/src/**/{hooks,services}/**/*.{ts,tsx} : Use the useApi hook for API calls with proper error handling, including loading state, error state, and exception throwing

Applied to files:

  • src/frontend/src/hooks/use-webhook-events.ts
📚 Learning: 2025-06-23T12:46:42.048Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-06-23T12:46:42.048Z
Learning: React Flow should be used for flow graph visualization, with nodes and edges passed as props, and changes handled via onNodesChange and onEdgesChange callbacks.

Applied to files:

  • src/frontend/src/hooks/use-webhook-events.ts
  • src/frontend/src/pages/FlowPage/index.tsx
📚 Learning: 2025-11-24T19:46:09.104Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:09.104Z
Learning: Applies to src/backend/base/langflow/api/**/*.py : Backend API endpoints should be organized by version (v1/, v2/) under `src/backend/base/langflow/api/` with specific modules for features (chat.py, flows.py, users.py, etc.)

Applied to files:

  • src/backend/base/langflow/api/v1/endpoints.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Test webhook endpoints by posting to `api/v1/webhook/{endpoint_name}` with appropriate payloads and validating response status codes

Applied to files:

  • src/backend/tests/unit/test_webhook.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Test real-time event streaming endpoints by consuming NDJSON lines using `response.aiter_lines()`, parsing JSON, and validating event structure and job_id consistency

Applied to files:

  • src/backend/tests/unit/test_webhook.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Test Langflow REST API endpoints using the `client` fixture with appropriate HTTP methods (GET, POST, etc.), headers (logged_in_headers), and payload validation

Applied to files:

  • src/backend/tests/unit/test_webhook.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Use predefined JSON flows and utility functions from `tests.unit.build_utils` (create_flow, build_flow, get_build_events, consume_and_assert_stream) for flow execution testing

Applied to files:

  • src/backend/tests/unit/test_webhook.py
📚 Learning: 2025-06-23T12:46:42.048Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-06-23T12:46:42.048Z
Learning: Custom React Flow node types should be implemented as memoized components, using Handle components for connection points and supporting optional icons and labels.

Applied to files:

  • src/frontend/src/pages/FlowPage/index.tsx
📚 Learning: 2025-11-24T19:46:45.790Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:45.790Z
Learning: Applies to src/frontend/src/components/nodes/**/*.{tsx,jsx} : Memoize custom React Flow node components using memo() to prevent unnecessary re-renders

Applied to files:

  • src/frontend/src/pages/FlowPage/index.tsx
🧬 Code graph analysis (7)
src/lfx/src/lfx/graph/vertex/base.py (2)
src/lfx/src/lfx/custom/custom_component/custom_component.py (1)
  • flow_id (201-202)
src/backend/base/langflow/services/event_manager.py (3)
  • has_listeners (147-149)
  • record_build_start (36-38)
  • emit (100-145)
src/frontend/src/hooks/use-webhook-events.ts (2)
src/frontend/src/types/zustand/flow/index.ts (1)
  • VertexLayerElementType (46-49)
src/frontend/src/types/api/index.ts (1)
  • VertexBuildTypeAPI (207-219)
src/backend/base/langflow/services/event_manager.py (2)
src/lfx/src/lfx/custom/custom_component/custom_component.py (1)
  • flow_id (201-202)
src/backend/base/langflow/server.py (1)
  • error (53-61)
src/backend/base/langflow/api/v1/endpoints.py (1)
src/backend/base/langflow/services/event_manager.py (4)
  • emit (100-145)
  • subscribe (64-79)
  • unsubscribe (81-98)
  • has_listeners (147-149)
src/backend/tests/unit/test_webhook.py (1)
src/backend/base/langflow/services/event_manager.py (8)
  • WebhookEventManager (17-149)
  • has_listeners (147-149)
  • subscribe (64-79)
  • unsubscribe (81-98)
  • emit (100-145)
  • record_build_start (36-38)
  • get_build_duration (40-48)
  • _format_duration (54-62)
src/frontend/src/pages/FlowPage/index.tsx (4)
src/frontend/src/utils/reactflowUtils.ts (1)
  • customStringify (1142-1164)
src/frontend/src/hooks/use-refresh-model-inputs.ts (1)
  • refreshAllModelInputs (68-121)
src/frontend/src/hooks/use-webhook-events.ts (1)
  • useWebhookEvents (15-189)
src/frontend/src/customization/feature-flags.ts (1)
  • ENABLE_NEW_SIDEBAR (23-23)
src/lfx/src/lfx/graph/utils.py (1)
src/backend/base/langflow/services/event_manager.py (3)
  • has_listeners (147-149)
  • get_build_duration (40-48)
  • emit (100-145)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 3
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 4
  • GitHub Check: Lint Backend / Run Mypy (3.12)
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 1
  • GitHub Check: Lint Backend / Run Mypy (3.13)
  • GitHub Check: Run Backend Tests / LFX Tests - Python 3.10
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 2
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 5
  • GitHub Check: Test Docker Images / Test docker images
  • GitHub Check: Lint Backend / Run Mypy (3.11)
  • GitHub Check: Lint Backend / Run Mypy (3.10)
  • GitHub Check: Run Backend Tests / Integration Tests - Python 3.10
  • GitHub Check: Run Frontend Unit Tests / Frontend Jest Unit Tests
  • GitHub Check: Test Starter Templates
  • GitHub Check: Optimize new Python code in this PR
  • GitHub Check: Update Starter Projects
  • GitHub Check: Update Component Index
🔇 Additional comments (26)
src/frontend/src/controllers/API/queries/_builds/use-get-builds-polling-mutation.ts (2)

122-148: Duration preservation logic looks good.

The merge strategy correctly preserves duration data from SSE events when polling results lack it. This ensures real-time duration information from the SSE stream isn't lost during polling updates.

One minor note: the direct mutation of lastEntry.data.duration at line 141 modifies the response object in place. This is acceptable here since the data is immediately set in state, but be aware this pattern could cause issues if the response object is used elsewhere.


152-154: Correct variable usage for error detection.

Using newFlowPool for error detection is appropriate since you want to check the freshly fetched build data for errors, not the merged result.

src/lfx/src/lfx/graph/vertex/base.py (1)

748-764: Build start event emission is well-guarded.

The implementation correctly:

  • Uses lazy import to handle the case when langflow isn't available
  • Checks for listeners before emitting (performance optimization)
  • Records build start time for duration calculation
  • Silently catches exceptions to avoid breaking the build process

The # noqa: BLE001, S110 comments appropriately acknowledge the intentional broad exception handling and the pass statement.

src/frontend/src/pages/FlowPage/index.tsx (1)

59-60: Good integration of webhook events hook.

The useWebhookEvents() hook is correctly placed at the component's top level, following React hooks rules. The hook establishes SSE connection for real-time webhook feedback when a flow is open in the UI.

src/backend/tests/unit/test_webhook.py (6)

416-433: Good test coverage for subscribe/unsubscribe lifecycle.

The test correctly verifies the listener management lifecycle: initially no listeners, then has listeners after subscribe, then no listeners after unsubscribe.


435-456: Emit test properly validates event structure.

The test verifies that emitted events are received with correct structure (event type, data, timestamp) and uses appropriate timeout with asyncio.wait_for.


458-467: No-listener emit test is important for robustness.

Good edge case coverage - verifying that emitting when no listeners exist doesn't raise errors.


469-491: Duration tracking test validates the full cycle.

The test covers recording start, waiting, retrieving formatted duration, and verifying cleanup (subsequent get returns None). The assertion for "ms" format is appropriate given the 0.1s sleep.


493-508: Duration formatting test covers threshold boundaries.

Good coverage of the formatting logic across milliseconds (< 1s), seconds (1s-60s), and minutes (≥ 60s) ranges.


510-533: Multiple subscribers test validates broadcast behavior.

The test correctly verifies that both subscribers receive the same event, which is essential for the fan-out broadcasting pattern.

src/lfx/src/lfx/graph/utils.py (2)

256-273: End vertex event payload matches frontend expectations.

The build_data structure aligns with the VertexBuildTypeAPI type expected by the frontend. The hardcoded empty arrays for next_vertices_ids and top_level_vertices are acceptable here since these fields are typically populated by the build orchestration layer, not at the individual vertex build level.


274-275: Silent exception handling is appropriate for non-critical SSE emission.

The broad exception handling with pass is intentional and appropriate here since SSE emission should never break the primary build flow.

src/frontend/src/hooks/use-webhook-events.ts (3)

1-14: Well-documented hook with clear purpose.

The JSDoc comment clearly explains the hook's purpose and its alignment with the normal Play button flow. Good use of TypeScript imports for type safety.


158-169: Error event handler correctly distinguishes error types.

Good pattern to check for eventOrError.data to differentiate between SSE errors with data payloads and generic connection errors. The catch block at line 165 handles JSON parse failures gracefully.


178-186: Proper cleanup with EventSource.close().

The cleanup function correctly closes the EventSource and clears the ref, preventing memory leaks and orphaned connections.

src/backend/base/langflow/services/event_manager.py (6)

17-35: Well-designed event manager with proper initialization.

Good use of:

  • defaultdict for automatic collection initialization
  • asyncio.Lock for concurrent access protection
  • Clear documentation explaining the purpose

36-48: Duration tracking with proper cleanup.

The get_build_duration method correctly cleans up the start time after retrieval, preventing memory leaks for completed vertices.


50-62: Clean duration formatting implementation.

The _format_duration method handles edge cases well with clear thresholds for milliseconds, seconds, and minutes formatting.


64-79: Subscribe with bounded queue is a good pattern.

The maxsize=100 prevents unbounded memory growth from slow consumers. Logging the listener count aids debugging.


100-145: Robust emit with timeout and dead queue cleanup.

The implementation correctly:

  • Copies listeners under lock to avoid iteration issues
  • Uses wait_for with timeout to prevent blocking
  • Handles both timeout (skip event) and exceptions (remove queue)
  • Cleans up dead queues to prevent memory leaks

152-153: Global singleton is appropriate for this use case.

The singleton pattern is suitable here since webhook events need to be broadcast across the application from a single source of truth.

src/backend/base/langflow/api/v1/endpoints.py (5)

208-224: LGTM!

The new parameters emit_events and flow_id are well-documented and have sensible defaults. The docstring clearly explains that flow_id is required when emit_events=True.


225-248: LGTM!

The lazy import avoids potential circular dependencies, and the event emission logic correctly extracts vertex IDs from the flow data before execution begins.


258-261: LGTM!

The success event is correctly emitted after flow execution completes, providing the run_id and success: True status for UI feedback.


277-280: LGTM!

The error event correctly uses the same "end" event type with success: False and includes the error message, allowing consistent event handling on the UI side.


776-789: LGTM - Correct use of asyncio.create_task() for background execution.

The fire-and-forget pattern is correctly implemented:

  • Uses asyncio.create_task() as recommended by coding guidelines for SSE event loop compatibility
  • The done callback prevents "Task exception was never retrieved" warnings by consuming any uncaught exceptions

Note that simple_run_flow_task already handles all exceptions internally (lines 275-292), so the callback is primarily defensive.

@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Dec 15, 2025
… valid API key request to ensure accurate file existence assertion
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Dec 15, 2025
…n and remove unnecessary whitespace

style(test_webhook.py): remove extra blank line to adhere to PEP 8 style guidelines
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Dec 15, 2025
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Dec 15, 2025
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Dec 15, 2025
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Dec 15, 2025
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Dec 15, 2025
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Dec 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants