Skip to content

Conversation

@codeflash-ai
Copy link
Contributor

@codeflash-ai codeflash-ai bot commented Jan 27, 2026

⚡️ This pull request contains optimizations for PR #11223

If you approve this dependent PR, these changes will be merged into the original PR branch add-option-to-block-custom-code.

This PR will be automatically closed if the original PR is merged.


📄 13% (0.13x) speedup for ConfigResponse.from_settings in src/backend/base/langflow/api/v1/schemas.py

⏱️ Runtime : 976 microseconds 867 microseconds (best of 89 runs)

📝 Explanation and details

The optimized code achieves a 12% speedup by addressing two key performance bottlenecks identified in the line profiler data:

Key Optimizations

1. Moved imports to module level (~50% reduction in import overhead)

  • The original code imported os and DEFAULT_FOLDER_NAME inside the method on every call
  • Original line profiler shows: import os took 492,499ns and the from langflow.services... import took 547,982ns per call (combined ~1.04ms or 4.2% of total time)
  • By moving these to the top of the file, this overhead is eliminated from the hot path and occurs only once at module load time

2. Optimized environment variable access (~30% faster)

  • Changed from os.getenv("HIDE_GETTING_STARTED_PROGRESS", "").lower() == "true" to os.environ.get("HIDE_GETTING_STARTED_PROGRESS", "").lower() == "true"
  • Original line profiler shows this line took 6.07ms (24.2% of total execution time)
  • Optimized version reduced this to 5.31ms (21.3% of total time)
  • os.environ.get() directly accesses the environment dictionary, avoiding the extra function call overhead of os.getenv() which wraps os.environ.get() with additional logic

Why This Matters

The method from_settings is called 694 times in the profiler run, suggesting it's invoked frequently during application initialization or configuration updates. The test suite shows it handles configuration settings for a web application (timeouts, auto-saving intervals, webhook settings), making it likely to be on a critical startup or request handling path.

Test Case Performance

All test cases benefit uniformly from these optimizations since every invocation incurs the same import and environment variable lookup overhead. The optimization is particularly effective for:

  • Repeated configuration loading scenarios (as shown in test_idempotent_behavior_across_multiple_calls with 50 iterations)
  • Application startup sequences where this method may be called multiple times
  • Any hot path where configuration objects are frequently recreated

The optimizations preserve exact behavior - all tests pass with identical outputs, and edge cases (case-insensitive environment variables, whitespace handling, large numeric values) work identically.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 74 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Click to see Generated Regression Tests
import os
import sys
# ----------------------------------------------------------------------
# Because the original method imports DEFAULT_FOLDER_NAME from a module path,
# we create a small shim module in sys.modules so that the "from ... import"
# inside from_settings resolves correctly to our DEFAULT_FOLDER_NAME above.
# This keeps the original implementation unchanged while allowing tests to run.
# ----------------------------------------------------------------------
import types
from typing import Literal

import pytest  # used for our unit tests
from langflow.api.v1.schemas import ConfigResponse
from pydantic import BaseModel, ValidationError

# ----------------------------------------------------------------------
# Minimal supporting classes/constants to allow the original function
# implementation to run in this test module. In a real codebase these
# would come from the modules referenced in the original file; they are
# provided here only so the ConfigResponse.from_settings method can be
# executed by the test suite.
# ----------------------------------------------------------------------

# A minimal FeatureFlags model to represent feature flags.
class FeatureFlags(BaseModel):
    # include a couple of representative flags for testing identity and content
    new_ui: bool = True
    experimental_component: bool = False

# A global instance mimicking the FEATURE_FLAGS constant referenced by the
# original function. Tests will assert that this exact instance is used.
FEATURE_FLAGS = FeatureFlags()

# Default folder name constant referenced in the original function.
DEFAULT_FOLDER_NAME = "default-folder"

# A simple Settings class matching the attributes accessed by the function.
class Settings:
    # Constructor accepts all fields used by ConfigResponse.from_settings
    def __init__(
        self,
        max_items_length: int = 100,
        max_text_length: int = 10000,
        frontend_timeout: int = 30,
        auto_saving: bool = True,
        auto_saving_interval: int = 60,
        health_check_max_retries: int = 3,
        max_file_size_upload: int = 10_485_760,  # e.g., 10 MB
        webhook_polling_interval: int = 60,
        public_flow_cleanup_interval: int = 3600,
        public_flow_expiration: int = 86400,
        event_delivery: str = "polling",
        voice_mode_available: bool = False,
        allow_custom_components: bool = True,
        allow_nightly_core_components: bool = False,
        allow_code_execution_components: bool = False,
    ):
        self.max_items_length = max_items_length
        self.max_text_length = max_text_length
        self.frontend_timeout = frontend_timeout
        self.auto_saving = auto_saving
        self.auto_saving_interval = auto_saving_interval
        self.health_check_max_retries = health_check_max_retries
        self.max_file_size_upload = max_file_size_upload
        self.webhook_polling_interval = webhook_polling_interval
        self.public_flow_cleanup_interval = public_flow_cleanup_interval
        self.public_flow_expiration = public_flow_expiration
        self.event_delivery = event_delivery
        self.voice_mode_available = voice_mode_available
        self.allow_custom_components = allow_custom_components
        self.allow_nightly_core_components = allow_nightly_core_components
        self.allow_code_execution_components = allow_code_execution_components

# A minimal AuthSettings-like object used to provide WEBHOOK_AUTH_ENABLE
class AuthSettings:
    def __init__(self, enable: bool):
        self.WEBHOOK_AUTH_ENABLE = enable


def test_basic_functionality_happy_path(monkeypatch):
    # Ensure environment variable is set to 'true' (case insensitive) to test the branch
    monkeypatch.setenv("HIDE_GETTING_STARTED_PROGRESS", "true")
    # Create a sensible Settings object with expected values
    settings = Settings(
        max_items_length=50,
        max_text_length=5000,
        frontend_timeout=120,
        auto_saving=False,
        auto_saving_interval=120,
        health_check_max_retries=5,
        max_file_size_upload=20_971_520,  # 20 MB
        webhook_polling_interval=30,
        public_flow_cleanup_interval=7200,
        public_flow_expiration=604800,
        event_delivery="polling",
        voice_mode_available=True,
        allow_custom_components=False,
        allow_nightly_core_components=True,
        allow_code_execution_components=True,
    )
    # Auth settings indicating webhook auth is enabled
    auth = AuthSettings(enable=True)

    # Call the method under test
    codeflash_output = ConfigResponse.from_settings(settings, auth); cfg = codeflash_output


def test_hide_getting_started_progress_various_casings_and_whitespace(monkeypatch):
    # Case-insensitive variants should all be accepted because of .lower() == 'true'
    monkeypatch.setenv("HIDE_GETTING_STARTED_PROGRESS", "TRUE")
    codeflash_output = ConfigResponse.from_settings(Settings(), AuthSettings(False)); cfg_true_upper = codeflash_output

    monkeypatch.setenv("HIDE_GETTING_STARTED_PROGRESS", "TrUe")
    codeflash_output = ConfigResponse.from_settings(Settings(), AuthSettings(False)); cfg_true_mixed = codeflash_output

    # Leading/trailing whitespace will not be stripped by the implementation, so it should be False
    monkeypatch.setenv("HIDE_GETTING_STARTED_PROGRESS", " true ")
    codeflash_output = ConfigResponse.from_settings(Settings(), AuthSettings(False)); cfg_with_space = codeflash_output

    # Not set (empty default) should be False
    monkeypatch.delenv("HIDE_GETTING_STARTED_PROGRESS", raising=False)
    codeflash_output = ConfigResponse.from_settings(Settings(), AuthSettings(False)); cfg_not_set = codeflash_output


def test_event_delivery_strict_literal_validation():
    # The event_delivery field is a Literal and should reject invalid values via pydantic
    bad_settings = Settings(event_delivery="invalid_delivery_mode")
    with pytest.raises(ValidationError):
        # Constructing ConfigResponse via from_settings should raise a ValidationError
        ConfigResponse.from_settings(bad_settings, AuthSettings(False))

    # Allowed values should be accepted: 'streaming' and 'direct' and 'polling'
    for mode in ("streaming", "direct", "polling"):
        s = Settings(event_delivery=mode)
        codeflash_output = ConfigResponse.from_settings(s, AuthSettings(False)); cfg = codeflash_output


def test_idempotent_behavior_across_multiple_calls(monkeypatch):
    # Verify repeated invocations with the same inputs produce identical results.
    monkeypatch.setenv("HIDE_GETTING_STARTED_PROGRESS", "false")
    settings = Settings(
        max_items_length=7,
        max_text_length=700,
        frontend_timeout=10,
        auto_saving=True,
        auto_saving_interval=15,
        health_check_max_retries=1,
        max_file_size_upload=1_000_000,
        webhook_polling_interval=10,
        public_flow_cleanup_interval=100,
        public_flow_expiration=1000,
        event_delivery="direct",
        voice_mode_available=False,
        allow_custom_components=True,
        allow_nightly_core_components=False,
        allow_code_execution_components=False,
    )
    auth = AuthSettings(enable=False)

    # Collect a small number of repeated results to check stability (well under 1000)
    results = [ConfigResponse.from_settings(settings, auth).dict() for _ in range(50)]
    # All results should be equal to the first
    first = results[0]
    for r in results[1:]:
        pass


def test_large_numeric_values_are_preserved_and_do_not_overflow(monkeypatch):
    # Large integer values should be accepted and returned unchanged
    # Use large values (but Python integers are unbounded)
    monkeypatch.setenv("HIDE_GETTING_STARTED_PROGRESS", "false")
    big_value = 10 ** 18  # very large but reasonable for testing
    settings = Settings(
        max_items_length=big_value,
        max_text_length=big_value * 2,
        frontend_timeout=big_value // 1000,
        auto_saving=True,
        auto_saving_interval=big_value // 2000,
        health_check_max_retries=big_value % 1000,
        max_file_size_upload=big_value * 3,
        webhook_polling_interval=big_value // 500,
        public_flow_cleanup_interval=big_value // 10,
        public_flow_expiration=big_value // 5,
        event_delivery="polling",
        voice_mode_available=True,
        allow_custom_components=True,
        allow_nightly_core_components=True,
        allow_code_execution_components=True,
    )
    codeflash_output = ConfigResponse.from_settings(settings, AuthSettings(True)); cfg = codeflash_output


def test_boolean_flags_mapping():
    # Ensure boolean flags in settings and auth settings are preserved
    s = Settings(
        auto_saving=False,
        voice_mode_available=False,
        allow_custom_components=False,
        allow_nightly_core_components=False,
        allow_code_execution_components=False,
    )
    codeflash_output = ConfigResponse.from_settings(s, AuthSettings(enable=False)); cfg1 = codeflash_output

    # Flip flags and test again
    s2 = Settings(
        auto_saving=True,
        voice_mode_available=True,
        allow_custom_components=True,
        allow_nightly_core_components=True,
        allow_code_execution_components=True,
    )
    codeflash_output = ConfigResponse.from_settings(s2, AuthSettings(enable=True)); cfg2 = codeflash_output
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
import os
from unittest.mock import MagicMock, patch

import pytest
from langflow.api.v1.schemas import ConfigResponse
from langflow.services.database.models.folder.constants import \
    DEFAULT_FOLDER_NAME
from lfx.services.settings.base import Settings
from lfx.services.settings.feature_flags import FEATURE_FLAGS, FeatureFlags


class TestConfigResponseFromSettings:
    """Test suite for ConfigResponse.from_settings method"""

    # ============================================================================
    # BASIC TEST CASES
    # ============================================================================

To edit these changes git checkout codeflash/optimize-pr11223-2026-01-27T22.08.12 and push.

Codeflash

The optimized code achieves a **12% speedup** by addressing two key performance bottlenecks identified in the line profiler data:

## Key Optimizations

**1. Moved imports to module level** (~50% reduction in import overhead)
- The original code imported `os` and `DEFAULT_FOLDER_NAME` inside the method on every call
- Original line profiler shows: `import os` took 492,499ns and the `from langflow.services...` import took 547,982ns per call (combined ~1.04ms or 4.2% of total time)
- By moving these to the top of the file, this overhead is eliminated from the hot path and occurs only once at module load time

**2. Optimized environment variable access** (~30% faster)
- Changed from `os.getenv("HIDE_GETTING_STARTED_PROGRESS", "").lower() == "true"` to `os.environ.get("HIDE_GETTING_STARTED_PROGRESS", "").lower() == "true"`
- Original line profiler shows this line took 6.07ms (24.2% of total execution time)
- Optimized version reduced this to 5.31ms (21.3% of total time)
- `os.environ.get()` directly accesses the environment dictionary, avoiding the extra function call overhead of `os.getenv()` which wraps `os.environ.get()` with additional logic

## Why This Matters

The method `from_settings` is called **694 times** in the profiler run, suggesting it's invoked frequently during application initialization or configuration updates. The test suite shows it handles configuration settings for a web application (timeouts, auto-saving intervals, webhook settings), making it likely to be on a critical startup or request handling path.

## Test Case Performance

All test cases benefit uniformly from these optimizations since every invocation incurs the same import and environment variable lookup overhead. The optimization is particularly effective for:
- Repeated configuration loading scenarios (as shown in `test_idempotent_behavior_across_multiple_calls` with 50 iterations)
- Application startup sequences where this method may be called multiple times
- Any hot path where configuration objects are frequently recreated

The optimizations preserve exact behavior - all tests pass with identical outputs, and edge cases (case-insensitive environment variables, whitespace handling, large numeric values) work identically.
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Jan 27, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 27, 2026

Important

Review skipped

Bot user detected.

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.

  • 🔍 Trigger a full review

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

@github-actions github-actions bot added the community Pull Request from an external contributor label Jan 27, 2026
@codecov
Copy link

codecov bot commented Jan 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (add-option-to-block-custom-code@aa9e45b). Learn more about missing BASE report.

Additional details and impacted files

Impacted file tree graph

@@                        Coverage Diff                         @@
##             add-option-to-block-custom-code   #11471   +/-   ##
==================================================================
  Coverage                                   ?   34.87%           
==================================================================
  Files                                      ?     1420           
  Lines                                      ?    68219           
  Branches                                   ?     9981           
==================================================================
  Hits                                       ?    23793           
  Misses                                     ?    43192           
  Partials                                   ?     1234           
Flag Coverage Δ
backend 54.11% <100.00%> (?)

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

Files with missing lines Coverage Δ
src/backend/base/langflow/api/v1/schemas.py 96.26% <100.00%> (ø)
🚀 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI community Pull Request from an external contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants