Skip to content

⚡️ Speed up function import_all_services_into_a_dict by 193% in PR #11654 (feat/pluggable-auth-service-1.8)#11660

Closed
codeflash-ai[bot] wants to merge 2 commits intorelease-v1.8.0from
codeflash/optimize-pr11654-2026-02-09T00.57.38
Closed

⚡️ Speed up function import_all_services_into_a_dict by 193% in PR #11654 (feat/pluggable-auth-service-1.8)#11660
codeflash-ai[bot] wants to merge 2 commits intorelease-v1.8.0from
codeflash/optimize-pr11654-2026-02-09T00.57.38

Conversation

@codeflash-ai
Copy link
Contributor

@codeflash-ai codeflash-ai bot commented Feb 9, 2026

⚡️ This pull request contains optimizations for PR #11654

If you approve this dependent PR, these changes will be merged into the original PR branch feat/pluggable-auth-service-1.8.

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


📄 193% (1.93x) speedup for import_all_services_into_a_dict in src/backend/base/langflow/services/factory.py

⏱️ Runtime : 8.60 milliseconds 2.94 milliseconds (best of 194 runs)

📝 Explanation and details

The optimized code achieves a 192% speedup (from 8.60ms to 2.94ms) by eliminating the overhead of inspect.getmembers() and simplifying enum value access.

Key Optimizations

1. Direct Module Dictionary Iteration (vars(module).items() vs inspect.getmembers())

  • The original code uses inspect.getmembers(module, inspect.isclass) which performs expensive introspection operations
  • inspect.getmembers() iterates over all module attributes, calls getattr() on each, applies the predicate function (inspect.isclass), and sorts the results alphabetically
  • The optimized version directly iterates vars(module).items(), accessing the module's __dict__ without the sorting and extra function call overhead
  • This eliminates the intermediate list allocation and the cost of sorting class names

2. Simplified Enum Access

  • Changed from ServiceType(service_type).value to service_type.value
  • When iterating over an enum with for service_type in ServiceType:, each service_type is already an enum member
  • The original code redundantly wraps it in ServiceType() constructor, which is unnecessary and adds lookup overhead

Performance Impact

The line profiler results show the core function execution time dropped from 59.2ms to 18.3ms (~69% reduction), which is the dominant cost inside the cached wrapper. The speedup is particularly effective because:

  • Module introspection is avoided: For each service module loaded (multiple iterations), the optimization saves the cost of inspect.getmembers() scanning and filtering
  • No behavioral changes: The function still collects the same Service subclasses, maintains the same exception handling, and produces identical output
  • Cache-friendly: Since the function is cached with @cached(LRUCache(maxsize=1)), the first call benefits significantly, and subsequent calls remain O(1) dictionary lookups

Test Case Analysis

The annotated tests show the optimization performs well across all scenarios:

  • Basic functionality tests confirm identical behavior (collecting Service subclasses, including BaseAuthService/SettingsService)
  • Edge cases like exception handling and mcp_composer special handling remain unchanged
  • Performance tests benefit from reduced initial call overhead, making the cache even more valuable
  • Integration tests verify the returned services dictionary is functionally equivalent

This optimization is especially valuable if the function is called before the cache is populated (cold start scenarios), or if the cache is ever invalidated, as it reduces the initialization cost of service discovery.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 34 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Click to see Generated Regression Tests
import functools
# Now define the original function EXACTLY as provided in the prompt.
# We must preserve its signature and implementation. We use the same code body.
import importlib
import importlib as _importlib  # alias to avoid confusion with test-level importlib
import inspect
import sys
import types
from enum import Enum

# imports
import pytest  # used for our unit tests
from cachetools import \
    LRUCache as _LRUCache  # these resolve to our stub in sys.modules
from cachetools import cached as _cached
from langflow.services.factory import import_all_services_into_a_dict
from langflow.services.schema import ServiceType as _ServiceType
from lfx.log.logger import logger as _logger

# We must create minimal module structures in sys.modules so that the original
# function (which imports from langflow.* and lfx.*) can execute without
# ImportError in the test environment.
#
# IMPORTANT: We create modules and classes with the exact names the function
# expects (Service, BaseAuthService, SettingsService, ServiceType, logger).
# These are not "fake" replacements for real project classes in a real project
# environment, but are necessary here so the function can be executed.
# We avoid naming any "Fake" classes per instructions; classes use the same
# names referenced by the function.

# Helper to create modules easily
def _make_module(module_name):
    mod = types.ModuleType(module_name)
    sys.modules[module_name] = mod
    # Ensure package attributes for dotted names
    parts = module_name.split(".")
    for i in range(1, len(parts)):
        pkg_name = ".".join(parts[:i])
        pkg = sys.modules.get(pkg_name)
        if pkg is None:
            pkg = types.ModuleType(pkg_name)
            sys.modules[pkg_name] = pkg
        child = parts[i]
        # Attach child module to package if not present
        if not hasattr(pkg, child):
            setattr(pkg, child, mod if i == len(parts) - 1 else sys.modules[".".join(parts[: i + 1])])
    return mod
class BaseAuthService:
    pass
class SettingsService:
    pass
class Service:
    """Base Service class used for subclass checks."""
    pass
class AlphaService(Service):
    pass
class BetaService(Service):
    pass
class McpComposerService(Service):
    pass


def test_basic_functionality_collects_expected_services(monkeypatch):
    """
    Ensure that the function collects classes that are subclasses of Service from
    the declared modules and includes BaseAuthService and SettingsService.
    We dynamically create the missing module on demand so the function succeeds.
    """
    # Ensure we call the original underlying function (bypass caching wrapper)
    func = import_all_services_into_a_dict.__wrapped__

    # Save original import_module to delegate for non-missing modules
    real_import = importlib.import_module

    # Create dynamic module when missing module is requested so the function runs successfully.
    def import_module_dynamic(name, package=None):
        # If the function asks for the missing module, create it dynamically with one Service subclass.
        if name == "langflow.services.missing.service":
            mod = _make_module(name)
            # Define a class in this module that subclasses Service.
            # We must fetch the real Service class from langflow.services.base
            base_mod = sys.modules["langflow.services.base"]
            ServiceCls = getattr(base_mod, "Service")
            MissingService = type("MissingService", (ServiceCls,), {})
            mod.MissingService = MissingService
            return mod
        # Delegate to the real import for all other modules (which we've pre-created).
        return real_import(name, package=package)

    monkeypatch.setattr(importlib, "import_module", import_module_dynamic)

    # Execute the function (underlying original) to collect services
    services = func()

    # Every collected object must be a class and subclass of Service (except the explicit lfx additions,
    # which we can also verify are classes).
    base_service_cls = sys.modules["langflow.services.base"].Service
    for name, cls in services.items():
        # BaseAuthService/SettingsService may not be subclasses of Service in some setups; we only assert
        # subclass relation for those that came from modules under langflow/lfx service modules (heuristic).
        if name not in {"BaseAuthService", "SettingsService"}:
            pass




#------------------------------------------------
import importlib
import inspect
from unittest.mock import MagicMock, patch

import pytest
from langflow.services.base import Service
from langflow.services.factory import import_all_services_into_a_dict
from langflow.services.schema import ServiceType


class TestImportAllServicesIntoDictBasic:
    """Basic test cases for import_all_services_into_a_dict function."""

    def test_returns_dictionary(self):
        """Test that the function returns a dictionary."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_dictionary_not_empty(self):
        """Test that the returned dictionary is not empty."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_contains_base_auth_service(self):
        """Test that the dictionary contains BaseAuthService."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_contains_settings_service(self):
        """Test that the dictionary contains SettingsService."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_all_values_are_classes(self):
        """Test that all values in the dictionary are classes."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        for name, obj in result.items():
            pass

    def test_service_classes_inherit_from_service(self):
        """Test that Service subclasses inherit from the Service base class."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        # Filter out the manually added services that may not be Service subclasses
        for name, obj in result.items():
            if name not in ["BaseAuthService", "SettingsService"]:
                # These should be Service subclasses
                try:
                    pass
                except TypeError:
                    # obj might not be a class, but we already checked it is in previous test
                    pass

    def test_caching_returns_same_object(self):
        """Test that the function uses caching and returns the same object."""
        codeflash_output = import_all_services_into_a_dict(); result1 = codeflash_output
        codeflash_output = import_all_services_into_a_dict(); result2 = codeflash_output

    def test_dictionary_keys_are_strings(self):
        """Test that all dictionary keys are strings."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        for key in result.keys():
            pass

    def test_no_none_values(self):
        """Test that no values in the dictionary are None."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        for name, obj in result.items():
            pass


class TestImportAllServicesIntoDictEdgeCases:
    """Edge case tests for import_all_services_into_a_dict function."""

    def test_exception_handling_for_missing_service_modules(self):
        """Test that RuntimeError is raised when service modules cannot be imported."""
        with patch("importlib.import_module") as mock_import:
            # Simulate import failure
            mock_import.side_effect = ImportError("Module not found")
            with pytest.raises(RuntimeError) as exc_info:
                # Create a fresh call by clearing cache if possible
                # Since we can't easily clear the LRU cache, we verify the exception handling logic
                import_all_services_into_a_dict()

    def test_service_type_enum_iteration(self):
        """Test that the function iterates through all ServiceType enum values."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_special_handling_for_mcp_composer(self):
        """Test that mcp_composer service is correctly imported from lfx module."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_service_class_not_included_as_value(self):
        """Test that the base Service class itself is not included in the results."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        # The function explicitly excludes the Service class itself: obj is not Service
        for name, obj in result.items():
            if name not in ["BaseAuthService", "SettingsService"]:
                pass

    def test_exception_caught_and_logged(self):
        """Test that exceptions during service import are caught and re-raised as RuntimeError."""
        # The function catches all exceptions and converts them to RuntimeError
        # This is already tested in test_exception_handling_for_missing_service_modules
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_base_auth_service_value_is_correct(self):
        """Test that BaseAuthService value is the actual BaseAuthService class."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        from lfx.services.auth.base import BaseAuthService

    def test_settings_service_value_is_correct(self):
        """Test that SettingsService value is the actual SettingsService class."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        from lfx.services.settings.service import SettingsService

    def test_no_duplicate_keys(self):
        """Test that there are no duplicate keys in the returned dictionary."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        keys = list(result.keys())

    def test_all_services_are_unique_instances(self):
        """Test that each service class object is unique (no duplicates)."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        values = list(result.values())
        # Check that no two distinct keys map to the same class object (except by design)
        seen_classes = {}
        for name, obj in result.items():
            if id(obj) in seen_classes:
                # Same class can appear under different names, but this shouldn't happen
                # because we're mapping names to classes
                pass
            seen_classes[id(obj)] = name


class TestImportAllServicesIntoDictLargeScale:
    """Large scale test cases for import_all_services_into_a_dict function."""

    def test_performance_multiple_calls(self):
        """Test that repeated calls are efficient due to caching."""
        import time

        # First call might be slower due to import overhead
        start = time.time()
        codeflash_output = import_all_services_into_a_dict(); result1 = codeflash_output
        first_call_time = time.time() - start

        # Subsequent calls should be instant due to caching
        start = time.time()
        codeflash_output = import_all_services_into_a_dict(); result2 = codeflash_output
        cached_call_time = time.time() - start

    def test_dictionary_size_reasonable(self):
        """Test that the returned dictionary has a reasonable number of services."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_all_class_names_valid_identifiers(self):
        """Test that all keys are valid Python identifiers."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        for key in result.keys():
            pass

    def test_service_lookup_performance(self):
        """Test that looking up services in the dictionary is efficient."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_iteration_over_all_services(self):
        """Test that iteration over all services is reliable."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        # Iterate over all services and verify they're all valid classes
        count = 0
        for name, service_class in result.items():
            count += 1

    def test_memory_efficiency_with_cached_result(self):
        """Test that caching prevents redundant object creation."""
        codeflash_output = import_all_services_into_a_dict(); result1 = codeflash_output
        codeflash_output = import_all_services_into_a_dict(); result2 = codeflash_output
        codeflash_output = import_all_services_into_a_dict(); result3 = codeflash_output

    def test_service_type_enum_coverage(self):
        """Test that all ServiceType enum values are processed."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        # Count how many ServiceType values exist
        service_types_count = len(list(ServiceType))


class TestImportAllServicesIntoDictIntegration:
    """Integration tests for import_all_services_into_a_dict function."""

    def test_services_can_be_used_as_globals(self):
        """Test that returned services can be used as module globals."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        # Verify we can assign to a globals-like dict
        test_globals = {}
        test_globals.update(result)

    def test_service_classes_can_be_instantiated(self):
        """Test that returned service classes are valid and can be referenced."""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        # We can at least reference the classes (actual instantiation may fail due to deps)
        base_auth = result.get("BaseAuthService")
        settings = result.get("SettingsService")

    def test_consistent_results_across_sessions(self):
        """Test that the function returns consistent results."""
        codeflash_output = import_all_services_into_a_dict(); result1 = codeflash_output
        codeflash_output = import_all_services_into_a_dict(); result2 = codeflash_output
        # Values should be the same classes
        for key in result1.keys():
            pass
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

To edit these changes git checkout codeflash/optimize-pr11654-2026-02-09T00.57.38 and push.

Codeflash

ogabrielluiz and others added 2 commits February 8, 2026 15:57
* feat: Introduce service registration decorator and enhance ServiceManager for pluggable service discovery

- Added `register_service` decorator to allow services to self-register with the ServiceManager.
- Enhanced `ServiceManager` to support multiple service discovery mechanisms, including decorator-based registration, config files, and entry points.
- Implemented methods for direct service class registration and plugin discovery from various sources, improving flexibility and extensibility of service management.

* feat: Implement VariableService for managing environment variables

- Introduced VariableService class to handle environment variables with in-memory caching.
- Added methods for getting, setting, deleting, and listing variables.
- Included logging for service initialization and variable operations.
- Created an __init__.py file to expose VariableService in the package namespace.

* feat: Enhance LocalStorageService with Service integration and async teardown

- Updated LocalStorageService to inherit from both StorageService and Service for improved functionality.
- Added a name attribute for service identification.
- Implemented an async teardown method for future extensibility, even though no cleanup is currently needed.
- Refactored the constructor to ensure proper initialization of both parent classes.

* feat: Implement telemetry service with abstract base class and minimal logging functionality

- Added `BaseTelemetryService` as an abstract base class defining the interface for telemetry services.
- Introduced `TelemetryService`, a lightweight implementation that logs telemetry events without sending data.
- Created `__init__.py` to expose the telemetry service in the package namespace.
- Ensured robust async methods for logging various telemetry events and handling exceptions.

* feat: Introduce BaseTracingService and implement minimal TracingService

- Added `BaseTracingService` as an abstract base class defining the interface for tracing services.
- Implemented `TracingService`, a lightweight version that logs trace events without external integrations.
- Included async methods for starting and ending traces, tracing components, and managing logs and outputs.
- Enhanced documentation for clarity on method usage and parameters.

* feat: Add unit tests for service registration decorators

- Introduced a new test suite for validating the functionality of the @register_service decorator.
- Implemented tests for various service types including LocalStorageService, TelemetryService, and TracingService.
- Verified behavior for service registration with and without overrides, ensuring correct service management.
- Included tests for custom service implementations and preservation of class functionality.
- Enhanced overall test coverage for the service registration mechanism.

* feat: Add comprehensive unit and integration tests for ServiceManager

- Introduced a suite of unit tests covering edge cases for service registration, lifecycle management, and dependency resolution.
- Implemented integration tests to validate service loading from configuration files and environment variables.
- Enhanced test coverage for various service types including LocalStorageService, TelemetryService, and VariableService.
- Verified behavior for service registration with and without overrides, ensuring correct service management.
- Ensured robust handling of error conditions and edge cases in service creation and configuration parsing.

* feat: Add unit and integration tests for minimal service implementations

- Introduced comprehensive unit tests for LocalStorageService, TelemetryService, TracingService, and VariableService.
- Implemented integration tests to validate the interaction between minimal services.
- Ensured robust coverage for file operations, service readiness, and exception handling.
- Enhanced documentation within tests for clarity on functionality and expected behavior.

* docs: Add detailed documentation for pluggable services architecture and usage

* feat: Add example configuration file for Langflow services

* docs: Update PLUGGABLE_SERVICES.md to enhance architecture benefits section

- Revised the documentation to highlight the advantages of the pluggable service system.
- Replaced the migration guide with a detailed overview of features such as automatic discovery, lazy instantiation, dependency injection, and lifecycle management.
- Clarified examples of service registration and improved overall documentation for better understanding.

* [autofix.ci] apply automated fixes

* test(services): improve variable service teardown test with public API assertions

* docs(pluggable-service-layer): add docstrings for service manager and implementations

* fix: remove duplicate teardown method from LocalStorageService

During rebase, the teardown method was added in two locations (lines 57 and 220).
Removed the duplicate at line 57, keeping the one at the end of the class (line 220)
which is the more appropriate location for cleanup methods.

* fix(tests): update service tests for LocalStorageService constructor changes

- Add MockSessionService fixtures to test files that use ServiceManager
- Update LocalStorageService test instantiation to use mock session and settings services
- Fix service count assertions to account for MockSessionService in fixtures
- Remove duplicate class-level clean_manager fixtures in test_edge_cases.py

These changes fix test failures caused by LocalStorageService requiring
session_service and settings_service parameters instead of just data_dir.

* fix(services): Harden service lifecycle methods

- Fixed Diamond Inheritance in LocalStorageService
- Added Circular Dependency Detection in _create_service_from_class
- Fixed StorageService.teardown to Have Default Implementation

* docs: Update discovery order for pluggable services

* fix(lfx): replace aiofile with aiofiles for CI compatibility

- The aiofile library uses native async I/O (libaio) which fails with
  EAGAIN (SystemError: 11, 'Resource temporarily unavailable') in
  containerized environments like GitHub Actions runners.
- Switch to aiofiles which uses thread pool executors, providing reliable
  async file I/O across all environments including containers.

* [autofix.ci] apply automated fixes

* fix(lfx): prevent race condition in plugin discovery

  The discover_plugins() method had a TOCTOU (time-of-check to time-of-use)
  race condition. Since get() uses a keyed lock (per service name), multiple
  threads requesting different services could concurrently see
  _plugins_discovered=False and trigger duplicate plugin discovery.

  Wrap discover_plugins() with self._lock to ensure thread-safe access to
  the _plugins_discovered flag and prevent concurrent discovery execution.

* [autofix.ci] apply automated fixes

* feat: Introduce service registration decorator and enhance ServiceManager for pluggable service discovery

- Added `register_service` decorator to allow services to self-register with the ServiceManager.
- Enhanced `ServiceManager` to support multiple service discovery mechanisms, including decorator-based registration, config files, and entry points.
- Implemented methods for direct service class registration and plugin discovery from various sources, improving flexibility and extensibility of service management.

* feat: Enhance LocalStorageService with Service integration and async teardown

- Updated LocalStorageService to inherit from both StorageService and Service for improved functionality.
- Added a name attribute for service identification.
- Implemented an async teardown method for future extensibility, even though no cleanup is currently needed.
- Refactored the constructor to ensure proper initialization of both parent classes.

* docs(pluggable-service-layer): add docstrings for service manager and implementations

* feat(auth): implement abstract base class for authentication services and add auth service retrieval function

* refactor(auth): move authentication logic from utils to AuthService

  Consolidate all authentication methods into the AuthService class to
  enable pluggable authentication implementations. The utils module now
  contains thin wrappers that delegate to the registered auth service.

  This allows alternative auth implementations (e.g., OIDC) to be
  registered via the pluggable services system while maintaining
  backward compatibility with existing code that imports from utils.

  Changes:
  - Move all auth logic (token creation, user validation, API key
    security, password hashing, encryption) to AuthService
  - Refactor utils.py to delegate to get_auth_service()
  - Update function signatures to remove settings_service parameter
    (now obtained from the service internally)

* refactor(auth): update authentication methods and remove settings_service parameter

  - Changed function to retrieve current user from access token instead of JWT.
  - Updated AuthServiceFactory to specify SettingsService type in create method.
  - Removed settings_service dependency from encryption and decryption functions, simplifying the code.

This refactor enhances the clarity and maintainability of the authentication logic.

* test(auth): add unit tests for AuthService and pluggable authentication

- Introduced comprehensive unit tests for AuthService, covering token creation, user validation, and authentication methods.
- Added tests for pluggable authentication, ensuring correct delegation to registered services.
- Enhanced test coverage for user authentication scenarios, including active/inactive user checks and token validation.

These additions improve the reliability and maintainability of the authentication system.

* fix(tests): update test cases to use AuthService and correct user retrieval method

- Replaced the mock for retrieving the current user from JWT to access token in the TestSuperuserCommand.
- Refactored unit tests for MCP encryption to utilize AuthService instead of a mock settings service, enhancing test reliability.
- Updated patch decorators in tests to reflect the new method of obtaining the AuthService, ensuring consistency across test cases.

These changes improve the accuracy and maintainability of the authentication tests.

* docs(pluggable-services): add auth_service to ServiceType enum documentation

* fix(auth): Add missing type hints and abstract methods to AuthServiceBase (#10710)

Co-authored-by: ogabrielluiz <24829397+ogabrielluiz@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* [autofix.ci] apply automated fixes

* fix(auth): refactor api_key_security method to accept optional database session and improve error handling

* feat(auth): enhance AuthServiceBase with detailed design principles and JIT provisioning methods

* fix(auth): remove settings_service from encrypt/decrypt_api_key calls

After the pluggable auth refactor, encrypt_api_key and decrypt_api_key
no longer take a settings_service argument - they get it internally.

- Update check_key import path in __main__.py (moved to crud module)
- Remove settings_service argument from calls in:
  - api/v1/api_key.py
  - api/v1/store.py
  - services/variable/service.py
  - services/variable/kubernetes.py
- Fix auth service to use session_scope() instead of non-existent
  get_db_service().with_session()

* fix(auth): resolve type errors and duplicate definitions in pluggable auth branch

  - Add missing imports in auth/utils.py (Final, HTTPException, status,
    logger, SettingsService) that prevented application startup
  - Remove duplicate NoServiceRegisteredError class in lfx/services/manager.py
  - Remove duplicate teardown method in lfx/services/storage/local.py
  - Fix invalid settings_service parameter in encrypt_api_key calls
    in variable/service.py and variable/kubernetes.py
  - Add proper type guards for check_key calls to satisfy mypy
  - Add null checks for password fields in users.py endpoints

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

* [autofix.ci] apply automated fixes

* replace jose with pyjwt

* [autofix.ci] apply automated fixes

* starter projects

* fix BE mcp tests

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* remive legacy usage of session

* fix user tests

* [autofix.ci] apply automated fixes

* fix lfx tests

* starter project update

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* fix mypy errors

* fix mypy errors on tests

* fix tests for decrypt_api_key

* resolve conflicts in auth utils

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* Add pluggable authentication factory with provider enum

* Add SSO feature flags to AuthSettings

* Add SSO fields to User model

* Add SSO configuration loader with YAML support

* Add unit tests for SSO configuration loader

* Add SSO configuration database model and CRUD operations

* Add CRUD operations for SSO configuration management

* Add SSO configuration service supporting both file and database configs

* Add example SSO configuration file with W3ID and other providers

* Implement OIDC authentication service with discovery and JIT provisioning

* Update AuthServiceFactory to instantiate OIDC service when SSO enabled

* Improve JWT token validation and API key decryption error handling

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* fix: resolve ruff linting errors in auth services and add sso-config.yaml to gitignore

* [autofix.ci] apply automated fixes

* fix: use correct function name get_current_user_from_access_token in login endpoint

* fix: remove incorrect settings_service parameter from decrypt_api_key call

* fix: correct encryption logic to properly detect plaintext vs encrypted values

* [autofix.ci] apply automated fixes

* fix tests

* [autofix.ci] apply automated fixes

* fix mypy errors

* fix tests

* [autofix.ci] apply automated fixes

* fix ruff errors

* fix tests in service

* [autofix.ci] apply automated fixes

* fix test security cors

* [autofix.ci] apply automated fixes

* fix webhook issues

* modify component index

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

* fix webhook tests

* [autofix.ci] apply automated fixes

* build component index

* remove SSO functionality

* [autofix.ci] apply automated fixes

* fix variable creation

* [autofix.ci] apply automated fixes

* refactor: move MCPServerConfig schema to a separate file and update model_dump usage

* refactor: streamline AuthServiceFactory to use service_class for instance creation

* handle access token type

* [autofix.ci] apply automated fixes

* remove SSO fields from user model

* [autofix.ci] apply automated fixes

* replace is_encrypted back

* fix mypy errors

* remove sso config example

* feat: Refactor framework agnostic auth service (#11565)

* modify auth service layer

* [autofix.ci] apply automated fixes

* fix ruff errorrs

* [autofix.ci] apply automated fixes

* Update src/backend/base/langflow/services/deps.py

Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>

* address review comments

* [autofix.ci] apply automated fixes

* fix ruff errors

* remove cache

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>

* move base to lfx

* [autofix.ci] apply automated fixes

* resolve review comments

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* add auth protocol

* [autofix.ci] apply automated fixes

* revert models.py execption handling

* revert wrappers to ensure backwards compatibility

* fix http error code

* fix FE tests

* fix test_variables.py

* [autofix.ci] apply automated fixes

* fix ruff errors

* fix tests

* add wrappers for create token methods

* fix ruff errors

* [autofix.ci] apply automated fixes

* update error message

* modify status code for inactive user

* fix ruff errors

* fix patch for webhook tests

* fix error message when getting active users

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Mike Pawlowski <mike.pawlowski@datastax.com>
Co-authored-by: Mike Pawlowski <mpawlow@ca.ibm.com>
Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ogabrielluiz <24829397+ogabrielluiz@users.noreply.github.com>
Co-authored-by: himavarshagoutham <himavarshajan17@gmail.com>
Co-authored-by: Deon Sanchez <69873175+deon-sanchez@users.noreply.github.com>
Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>
The optimized code achieves a **192% speedup** (from 8.60ms to 2.94ms) by eliminating the overhead of `inspect.getmembers()` and simplifying enum value access.

## Key Optimizations

**1. Direct Module Dictionary Iteration (`vars(module).items()` vs `inspect.getmembers()`)**
- The original code uses `inspect.getmembers(module, inspect.isclass)` which performs expensive introspection operations
- `inspect.getmembers()` iterates over all module attributes, calls `getattr()` on each, applies the predicate function (`inspect.isclass`), and sorts the results alphabetically
- The optimized version directly iterates `vars(module).items()`, accessing the module's `__dict__` without the sorting and extra function call overhead
- This eliminates the intermediate list allocation and the cost of sorting class names

**2. Simplified Enum Access**
- Changed from `ServiceType(service_type).value` to `service_type.value`
- When iterating over an enum with `for service_type in ServiceType:`, each `service_type` is already an enum member
- The original code redundantly wraps it in `ServiceType()` constructor, which is unnecessary and adds lookup overhead

## Performance Impact

The line profiler results show the core function execution time dropped from **59.2ms to 18.3ms** (~69% reduction), which is the dominant cost inside the cached wrapper. The speedup is particularly effective because:

- **Module introspection is avoided**: For each service module loaded (multiple iterations), the optimization saves the cost of `inspect.getmembers()` scanning and filtering
- **No behavioral changes**: The function still collects the same Service subclasses, maintains the same exception handling, and produces identical output
- **Cache-friendly**: Since the function is cached with `@cached(LRUCache(maxsize=1))`, the first call benefits significantly, and subsequent calls remain O(1) dictionary lookups

## Test Case Analysis

The annotated tests show the optimization performs well across all scenarios:
- Basic functionality tests confirm identical behavior (collecting Service subclasses, including BaseAuthService/SettingsService)
- Edge cases like exception handling and mcp_composer special handling remain unchanged
- Performance tests benefit from reduced initial call overhead, making the cache even more valuable
- Integration tests verify the returned services dictionary is functionally equivalent

This optimization is especially valuable if the function is called before the cache is populated (cold start scenarios), or if the cache is ever invalidated, as it reduces the initialization cost of service discovery.
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Feb 9, 2026
@github-actions github-actions bot added the community Pull Request from an external contributor label Feb 9, 2026
@codecov
Copy link

codecov bot commented Feb 9, 2026

Codecov Report

❌ Patch coverage is 73.99220% with 200 lines in your changes missing coverage. Please review.
✅ Project coverage is 35.25%. Comparing base (22607cc) to head (9b2f324).
⚠️ Report is 11 commits behind head on release-v1.8.0.

Files with missing lines Patch % Lines
src/backend/base/langflow/services/auth/service.py 66.66% 135 Missing ⚠️
src/lfx/src/lfx/services/auth/service.py 70.58% 15 Missing ⚠️
src/lfx/src/lfx/services/auth/exceptions.py 62.50% 9 Missing ⚠️
src/backend/base/langflow/services/auth/utils.py 89.18% 8 Missing ⚠️
src/backend/base/langflow/api/v1/login.py 50.00% 5 Missing ⚠️
src/backend/base/langflow/api/v1/models.py 0.00% 4 Missing ⚠️
src/lfx/src/lfx/services/auth/base.py 93.22% 4 Missing ⚠️
src/backend/base/langflow/__main__.py 50.00% 3 Missing ⚠️
src/backend/base/langflow/api/v1/store.py 0.00% 2 Missing ⚠️
src/backend/base/langflow/api/v1/users.py 80.00% 2 Missing ⚠️
... and 10 more

❌ Your project status has failed because the head coverage (42.10%) is below the target coverage (60.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##           release-v1.8.0   #11660      +/-   ##
==================================================
+ Coverage           35.02%   35.25%   +0.22%     
==================================================
  Files                1515     1521       +6     
  Lines               72567    72922     +355     
  Branches            10934    10935       +1     
==================================================
+ Hits                25418    25706     +288     
- Misses              45755    45821      +66     
- Partials             1394     1395       +1     
Flag Coverage Δ
backend 55.82% <71.97%> (+0.26%) ⬆️
lfx 42.10% <81.32%> (+0.26%) ⬆️

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/api_key.py 73.33% <100.00%> (ø)
src/backend/base/langflow/api/v1/endpoints.py 72.89% <100.00%> (+0.81%) ⬆️
src/backend/base/langflow/api/v1/mcp.py 72.57% <100.00%> (ø)
src/backend/base/langflow/api/v2/schemas.py 100.00% <100.00%> (ø)
...c/backend/base/langflow/services/auth/constants.py 100.00% <100.00%> (ø)
...kend/base/langflow/services/auth/mcp_encryption.py 73.07% <100.00%> (-1.93%) ⬇️
src/backend/base/langflow/services/deps.py 87.67% <100.00%> (+0.71%) ⬆️
...rc/backend/base/langflow/services/event_manager.py 75.42% <100.00%> (ø)
src/backend/base/langflow/services/factory.py 83.87% <100.00%> (+0.82%) ⬆️
...kend/base/langflow/services/variable/kubernetes.py 0.00% <ø> (ø)
... and 25 more

... and 13 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.

Base automatically changed from feat/pluggable-auth-service-1.8 to release-v1.8.0 February 9, 2026 12:02
@ogabrielluiz
Copy link
Contributor

Closing: removing CodeFlash integration.

@codeflash-ai codeflash-ai bot deleted the codeflash/optimize-pr11654-2026-02-09T00.57.38 branch February 11, 2026 15:39
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.

1 participant