Skip to content

⚡️ Speed up function import_all_services_into_a_dict by 177% in PR #10702 (pluggable-auth-service)#11633

Closed
codeflash-ai[bot] wants to merge 187 commits into
mainfrom
codeflash/optimize-pr10702-2026-02-06T18.04.37
Closed

⚡️ Speed up function import_all_services_into_a_dict by 177% in PR #10702 (pluggable-auth-service)#11633
codeflash-ai[bot] wants to merge 187 commits into
mainfrom
codeflash/optimize-pr10702-2026-02-06T18.04.37

Conversation

@codeflash-ai
Copy link
Copy Markdown
Contributor

@codeflash-ai codeflash-ai Bot commented Feb 6, 2026

⚡️ This pull request contains optimizations for PR #10702

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

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


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

⏱️ Runtime : 6.79 milliseconds 2.45 milliseconds (best of 204 runs)

📝 Explanation and details

The optimized code achieves a 177% speedup (from 6.79ms to 2.45ms) by eliminating the overhead of inspect.getmembers() and replacing it with direct dictionary iteration.

Key Optimizations

1. Direct Module Dictionary Access

  • Original: Used inspect.getmembers(module, inspect.isclass) which internally iterates over the module's __dict__, applies the predicate to every member, and constructs a sorted list of tuples
  • Optimized: Directly iterates module.__dict__.items(), avoiding the inspection overhead, filtering, and sorting operations

2. In-place Dictionary Assignment

  • Original: Created an intermediate dictionary via comprehension with .update()
  • Optimized: Assigns directly to services[name] = obj, eliminating temporary dictionary creation

3. Removed Redundant Enum Wrapping

  • Original: ServiceType(service_type).value re-wraps the enum member
  • Optimized: Uses service_type.value directly since we're already iterating enum members

Why This Is Faster

The line profiler shows the main function execution (v = func(*args, **kwargs)) dropped from 107.8ms to 76.9ms - a ~29% reduction in the core logic. This is because:

  • inspect.getmembers() performs attribute resolution, sorting, and filtering for all module attributes
  • Direct __dict__ iteration is a simple key-value traversal with inline type checks
  • Avoiding intermediate data structures reduces memory allocation and GC pressure

Test Case Performance

The optimizations benefit all test scenarios uniformly since they reduce the cold-path execution time:

  • Cache hits (160/180 calls) see negligible difference as they bypass the function
  • Cache misses (21 calls) benefit from the ~30% reduction in service discovery overhead
  • Large-scale tests with 100+ repeated calls leverage caching, so the speedup primarily impacts the initial cold execution

The optimization preserves all behavior: exception handling, special mcp_composer logic, and the final addition of BaseAuthService and SettingsService remain identical.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 181 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Click to see Generated Regression Tests
import importlib
import inspect
# imports
import sys
import types
from enum import Enum

import pytest
from cachetools import LRUCache, cached
from langflow.services.base import Service
from langflow.services.factory import import_all_services_into_a_dict
from lfx.services.auth.base import BaseAuthService
from lfx.services.settings.service import SettingsService





#------------------------------------------------
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_returns_non_empty_dictionary(self):
        """Test that the function returns a non-empty dictionary"""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_contains_base_auth_service(self):
        """Test that BaseAuthService is included in the returned dictionary"""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_contains_settings_service(self):
        """Test that SettingsService is included in the returned dictionary"""
        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_are_subclasses_of_service(self):
        """Test that service classes (except BaseAuthService) are subclasses of Service"""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        # BaseAuthService and SettingsService are from lfx, not subclasses of langflow Service
        service_exclusions = {"BaseAuthService", "SettingsService"}
        for name, obj in result.items():
            if name not in service_exclusions and inspect.isclass(obj):
                try:
                    pass
                except TypeError:
                    # Some classes might not be proper classes, skip those
                    pass

    def test_dict_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_service_base_class_in_result(self):
        """Test that the Service base class itself is not included in the result"""
        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_function_is_cached(self):
        """Test that the function uses caching and returns the same dictionary 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_all_service_types_are_processed(self):
        """Test that all ServiceType enum values are processed"""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_mcp_composer_special_handling(self):
        """Test that mcp_composer service is handled with special lfx module path"""
        # This test verifies the special case handling for mcp_composer
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

    def test_exception_handling_for_missing_modules(self):
        """Test that the function raises RuntimeError when services cannot be initialized"""
        # Mock importlib to raise an exception for a service module
        with patch('importlib.import_module') as mock_import:
            mock_import.side_effect = ImportError("Module not found")
            with pytest.raises(RuntimeError) as exc_info:
                # Clear the cache first to force re-execution
                import_all_services_into_a_dict.__wrapped__()

    def test_dict_contains_unique_keys(self):
        """Test that all dictionary keys are unique"""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        keys = list(result.keys())

    def test_no_none_values_in_dict(self):
        """Test that the dictionary does not contain None values"""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        for name, obj in result.items():
            pass

    def test_dict_with_empty_service_type(self):
        """Test behavior when service modules are empty or contain no Service subclasses"""
        # This is an edge case where a module might exist but have no Service subclasses
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output


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

    def test_large_number_of_repeated_calls(self):
        """Test function performance with many repeated calls (should use cache)"""
        # Call the function multiple times to test caching performance
        results = []
        num_calls = 100
        for _ in range(num_calls):
            codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
            results.append(result)

    def test_dict_key_count_consistency(self):
        """Test that the dictionary maintains consistent size across calls"""
        results = []
        for _ in range(10):
            codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
            results.append(len(result.keys()))

    def test_all_service_objects_are_distinct(self):
        """Test that all service objects in the dictionary are distinct classes"""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        service_objects = list(result.values())
        
        # Check that we don't have duplicate class objects
        service_ids = [id(obj) for obj in service_objects]

    def test_dictionary_iteration_completeness(self):
        """Test that we can iterate through all dictionary items without errors"""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        item_count = 0
        
        # Iterate through all items
        for name, obj in result.items():
            item_count += 1

    def test_memory_efficiency_with_cache(self):
        """Test that caching prevents excessive memory allocation"""
        # Get the first result
        codeflash_output = import_all_services_into_a_dict(); result1 = codeflash_output
        initial_id = id(result1)
        
        # Make 50 calls and verify same object
        for _ in range(50):
            codeflash_output = import_all_services_into_a_dict(); result = codeflash_output

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

    def test_dict_with_many_service_types(self):
        """Test that function handles all ServiceType enum values"""
        codeflash_output = import_all_services_into_a_dict(); result = codeflash_output
        
        # Count how many ServiceType enum values we have
        service_type_count = len(list(ServiceType))
        
        # All keys in result should be valid class names
        for key in result.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-pr10702-2026-02-06T18.04.37 and push.

Codeflash

ogabrielluiz and others added 30 commits January 15, 2026 12:49
…ager 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.
- 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.
…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.
…l 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.
- 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.
- 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.
- 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.
- 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.
…ection

- 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.
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.
…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.
- Fixed Diamond Inheritance in LocalStorageService
- Added Circular Dependency Detection in _create_service_from_class
- Fixed StorageService.teardown to Have Default Implementation
- 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.
  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.
…ager 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.
…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.
  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)
…vice 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.
- 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.
HimavarshaVS and others added 23 commits February 5, 2026 16:44
The optimized code achieves a **177% speedup** (from 6.79ms to 2.45ms) by eliminating the overhead of `inspect.getmembers()` and replacing it with direct dictionary iteration.

## Key Optimizations

**1. Direct Module Dictionary Access**
- **Original**: Used `inspect.getmembers(module, inspect.isclass)` which internally iterates over the module's `__dict__`, applies the predicate to every member, and constructs a sorted list of tuples
- **Optimized**: Directly iterates `module.__dict__.items()`, avoiding the inspection overhead, filtering, and sorting operations

**2. In-place Dictionary Assignment**
- **Original**: Created an intermediate dictionary via comprehension with `.update()`
- **Optimized**: Assigns directly to `services[name] = obj`, eliminating temporary dictionary creation

**3. Removed Redundant Enum Wrapping**
- **Original**: `ServiceType(service_type).value` re-wraps the enum member
- **Optimized**: Uses `service_type.value` directly since we're already iterating enum members

## Why This Is Faster

The line profiler shows the main function execution (`v = func(*args, **kwargs)`) dropped from **107.8ms to 76.9ms** - a **~29% reduction in the core logic**. This is because:

- `inspect.getmembers()` performs attribute resolution, sorting, and filtering for *all* module attributes
- Direct `__dict__` iteration is a simple key-value traversal with inline type checks
- Avoiding intermediate data structures reduces memory allocation and GC pressure

## Test Case Performance

The optimizations benefit all test scenarios uniformly since they reduce the cold-path execution time:
- **Cache hits** (160/180 calls) see negligible difference as they bypass the function
- **Cache misses** (21 calls) benefit from the ~30% reduction in service discovery overhead
- **Large-scale tests** with 100+ repeated calls leverage caching, so the speedup primarily impacts the initial cold execution

The optimization preserves all behavior: exception handling, special `mcp_composer` logic, and the final addition of `BaseAuthService` and `SettingsService` remain identical.
@codeflash-ai codeflash-ai Bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Feb 6, 2026
@github-actions github-actions Bot added the community Pull Request from an external contributor label Feb 6, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 6, 2026

Codecov Report

❌ Patch coverage is 71.78153% with 217 lines in your changes missing coverage. Please review.
✅ Project coverage is 34.67%. Comparing base (22607cc) to head (4073ff0).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
src/backend/base/langflow/services/auth/service.py 63.95% 146 Missing ⚠️
src/lfx/src/lfx/services/auth/service.py 70.58% 15 Missing ⚠️
src/backend/base/langflow/services/auth/utils.py 86.48% 10 Missing ⚠️
src/lfx/src/lfx/services/auth/exceptions.py 62.50% 9 Missing ⚠️
src/backend/base/langflow/api/v1/users.py 40.00% 6 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 ⚠️
... 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             @@
##             main   #11633      +/-   ##
==========================================
- Coverage   35.02%   34.67%   -0.36%     
==========================================
  Files        1515     1512       -3     
  Lines       72567    72142     -425     
  Branches    10934    10644     -290     
==========================================
- Hits        25418    25015     -403     
- Misses      45755    45796      +41     
+ Partials     1394     1331      -63     
Flag Coverage Δ
backend 53.83% <69.15%> (-1.73%) ⬇️
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 63.68% <100.00%> (-8.41%) ⬇️
src/backend/base/langflow/api/v1/mcp.py 72.00% <100.00%> (-0.58%) ⬇️
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 69.23% <100.00%> (-5.77%) ⬇️
src/backend/base/langflow/services/deps.py 87.67% <100.00%> (+0.71%) ⬆️
...rc/backend/base/langflow/services/event_manager.py 69.49% <100.00%> (-5.94%) ⬇️
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 110 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 pluggable-auth-service to main February 6, 2026 20:41
@codeflash-ai codeflash-ai Bot closed this Feb 11, 2026
@codeflash-ai
Copy link
Copy Markdown
Contributor Author

codeflash-ai Bot commented Feb 11, 2026

This PR has been automatically closed because the original PR #10375 by nightosong was closed.

@codeflash-ai codeflash-ai Bot deleted the codeflash/optimize-pr10702-2026-02-06T18.04.37 branch February 11, 2026 10:19
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.

5 participants