⚡️ Speed up function encrypt_auth_settings by 30% in PR #11639 (docs-chat-refactor-and-screenshots)#11640
Closed
codeflash-ai[bot] wants to merge 6 commits into
Closed
Conversation
The optimized code achieves a **30% speedup** by introducing two key optimizations:
## 1. **LRU Caching for Expensive Decryption Checks** (Primary Optimization)
The bottleneck is clear from the line profiler: `is_encrypted()` spends **97.5% of its time** (198ms out of 205ms) calling `auth_utils.decrypt_api_key()`, which involves cryptographic operations.
The optimization adds `@lru_cache(maxsize=1024)` to a new internal helper `_is_encrypted_cached()` that performs the actual decryption logic. This means:
- **First call** for a given value: Performs the expensive decryption (~10ms per call based on profiler)
- **Subsequent calls** with the same value: Returns cached result instantly (nanoseconds)
This is particularly effective when:
- The same credentials are checked multiple times across different auth_settings dictionaries
- Configuration validation runs repeatedly during initialization or hot-reload scenarios
- Test suites process the same test credentials repeatedly (as seen in `test_large_scale_with_many_non_sensitive_keys` where the same "ALREADY_ENCRYPTED_TOKEN" is checked)
The cache is **safe** because:
- Decryption results are deterministic (same encrypted value always decrypts to the same plaintext)
- The cache stores only the boolean result, not sensitive data
- Cache size of 1024 is reasonable for typical workloads with limited unique credentials
## 2. **Eliminating Redundant Dictionary Lookups** (Micro-optimization)
In `encrypt_auth_settings()`, the original code performs:
```python
if encrypted_settings.get(field):
field_to_encrypt = encrypted_settings[field] # Second lookup
```
The optimized version stores the result once:
```python
field_val = encrypted_settings.get(field)
if field_val:
# Use field_val directly
```
This eliminates one dictionary hash lookup per sensitive field, though the impact is minor compared to caching.
## Performance Characteristics
Based on the annotated tests:
- **Best speedup**: Scenarios with repeated credential checks (e.g., batch processing, validation loops, test suites)
- **Minimal speedup**: First-time encryption of unique credentials
- **No regression**: All tests pass, proving correctness is preserved
The optimization is most valuable if `encrypt_auth_settings()` is called in configuration hot paths, server initialization loops, or validation pipelines where the same credentials are encountered multiple times.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## docs-1.8-release #11640 +/- ##
===================================================
Coverage ? 35.24%
===================================================
Files ? 1521
Lines ? 72927
Branches ? 10936
===================================================
Hits ? 25701
Misses ? 45830
Partials ? 1396
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Base automatically changed from
docs-chat-refactor-and-screenshots
to
docs-1.8-release
February 10, 2026 16:03
Contributor
|
Closing: removing CodeFlash integration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
⚡️ This pull request contains optimizations for PR #11639
If you approve this dependent PR, these changes will be merged into the original PR branch
docs-chat-refactor-and-screenshots.📄 30% (0.30x) speedup for
encrypt_auth_settingsinsrc/backend/base/langflow/services/auth/mcp_encryption.py⏱️ Runtime :
1.59 milliseconds→1.22 milliseconds(best of72runs)📝 Explanation and details
The optimized code achieves a 30% speedup by introducing two key optimizations:
1. LRU Caching for Expensive Decryption Checks (Primary Optimization)
The bottleneck is clear from the line profiler:
is_encrypted()spends 97.5% of its time (198ms out of 205ms) callingauth_utils.decrypt_api_key(), which involves cryptographic operations.The optimization adds
@lru_cache(maxsize=1024)to a new internal helper_is_encrypted_cached()that performs the actual decryption logic. This means:This is particularly effective when:
test_large_scale_with_many_non_sensitive_keyswhere the same "ALREADY_ENCRYPTED_TOKEN" is checked)The cache is safe because:
2. Eliminating Redundant Dictionary Lookups (Micro-optimization)
In
encrypt_auth_settings(), the original code performs:The optimized version stores the result once:
This eliminates one dictionary hash lookup per sensitive field, though the impact is minor compared to caching.
Performance Characteristics
Based on the annotated tests:
The optimization is most valuable if
encrypt_auth_settings()is called in configuration hot paths, server initialization loops, or validation pipelines where the same credentials are encountered multiple times.✅ Correctness verification report:
⚙️ Click to see Existing Unit Tests
🌀 Click to see Generated Regression Tests
from typing import Any
from unittest.mock import Mock
imports
import pytest # used for our unit tests
from cryptography.fernet import InvalidToken # noqa: F401
from cryptography.fernet import InvalidToken as _InvalidToken
function to test
Fields that should be encrypted when stored
from langflow.services.auth import utils as auth_utils
from langflow.services.auth.mcp_encryption import (encrypt_auth_settings,
is_encrypted)
from lfx.log.logger import logger
def test_returns_none_when_input_is_none():
# Basic scenario: If auth_settings is None, the function should simply return None.
codeflash_output = encrypt_auth_settings(None)
def test_encrypts_plaintext_sensitive_fields(monkeypatch):
# Basic scenario: Sensitive fields that are plaintext should be encrypted.
# Prepare input with both sensitive fields as plaintext strings.
input_settings = {
"api_key": "plain_api_key",
"oauth_client_secret": "plain_oauth_secret",
"other": "value",
}
def test_does_not_reencrypt_already_encrypted_fields(monkeypatch):
# Edge scenario: If a sensitive field appears encrypted, encrypt_auth_settings should not call encrypt_api_key again.
input_settings = {
"api_key": "ALREADY_ENC_TOKEN",
"oauth_client_secret": "", # empty should be skipped
}
def test_is_encrypted_treats_decrypt_exceptions_as_encrypted(monkeypatch):
# Edge scenario: If decrypt_api_key raises InvalidToken for a given value,
# is_encrypted should return True (can't decrypt but treat as encrypted).
monkeypatch.setattr(auth_utils, "decrypt_api_key", Mock(side_effect=InvalidToken()))
def test_encrypt_auth_settings_propagates_value_error_from_encrypt(monkeypatch):
# Edge scenario: If encrypt_api_key raises ValueError, encrypt_auth_settings should propagate it.
input_settings = {"api_key": "to_encrypt"}
def test_falsy_sensitive_values_are_ignored(monkeypatch):
# Edge scenario: Falsy values (None, empty string, 0) for sensitive fields should be ignored and not encrypted.
inputs = [
{"api_key": None},
{"api_key": ""},
{"api_key": 0}, # 0 is falsy, should be ignored (no call to encrypt)
]
def test_large_scale_with_many_non_sensitive_keys(monkeypatch):
# Large Scale scenario: The function should scale to handle larger dictionaries
# (but we keep under 1000 elements as required).
large_dict = {f"key_{i}": f"value_{i}" for i in range(500)} # 500 non-sensitive keys
# Add sensitive fields: one plaintext, one already "encrypted"
large_dict["api_key"] = "plain_api_key_large"
large_dict["oauth_client_secret"] = "ALREADY_ENCRYPTED_TOKEN"
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
from unittest.mock import MagicMock, patch
import pytest
from cryptography.fernet import InvalidToken
from langflow.services.auth.mcp_encryption import (encrypt_auth_settings,
is_encrypted)
class TestEncryptAuthSettingsBasic:
"""Basic test cases for encrypt_auth_settings function."""
To edit these changes
git checkout codeflash/optimize-pr11639-2026-02-06T23.01.57and push.