|
30 | 30 | RequestExtractor, |
31 | 31 | ) |
32 | 32 |
|
| 33 | +# Global cache for database configurations to avoid connection pool interference |
33 | 34 | _cached_db_configs = {} # type: Dict[str, Dict[str, Any]] |
| 35 | +_cache_initialized = False # type: bool |
| 36 | +_cache_lock = threading.Lock() |
34 | 37 |
|
35 | 38 | try: |
36 | 39 | from django import VERSION as DJANGO_VERSION |
@@ -621,35 +624,47 @@ def _cache_database_configurations(): |
621 | 624 | """ |
622 | 625 | Cache database configurations from Django settings to avoid connection pool interference. |
623 | 626 | """ |
624 | | - global _cached_db_configs |
| 627 | + global _cached_db_configs, _cache_initialized |
625 | 628 |
|
626 | | - try: |
627 | | - from django.conf import settings |
628 | | - from django.db import connections |
| 629 | + # Fast path: if already initialized, return immediately |
| 630 | + if _cache_initialized: |
| 631 | + return |
629 | 632 |
|
630 | | - for alias, db_config in settings.DATABASES.items(): |
631 | | - if not db_config: # Skip empty default configs |
632 | | - continue |
| 633 | + # Slow path: acquire lock and check again (double-checked locking) |
| 634 | + with _cache_lock: |
| 635 | + if _cache_initialized: |
| 636 | + return |
633 | 637 |
|
634 | | - with capture_internal_exceptions(): |
635 | | - _cached_db_configs[alias] = { |
636 | | - "db_name": db_config.get("NAME"), |
637 | | - "host": db_config.get("HOST", "localhost"), |
638 | | - "port": db_config.get("PORT"), |
639 | | - "unix_socket": db_config.get("OPTIONS", {}).get("unix_socket"), |
640 | | - "engine": db_config.get("ENGINE"), |
641 | | - } |
| 638 | + try: |
| 639 | + from django.conf import settings |
| 640 | + from django.db import connections |
642 | 641 |
|
643 | | - db_wrapper = connections.get(alias) |
644 | | - if db_wrapper is None: |
| 642 | + for alias, db_config in settings.DATABASES.items(): |
| 643 | + if not db_config: # Skip empty default configs |
645 | 644 | continue |
646 | 645 |
|
647 | | - if hasattr(db_wrapper, "vendor"): |
648 | | - _cached_db_configs[alias]["vendor"] = db_wrapper.vendor |
| 646 | + with capture_internal_exceptions(): |
| 647 | + _cached_db_configs[alias] = { |
| 648 | + "db_name": db_config.get("NAME"), |
| 649 | + "host": db_config.get("HOST", "localhost"), |
| 650 | + "port": db_config.get("PORT"), |
| 651 | + "unix_socket": db_config.get("OPTIONS", {}).get("unix_socket"), |
| 652 | + "engine": db_config.get("ENGINE"), |
| 653 | + } |
649 | 654 |
|
650 | | - except Exception as e: |
651 | | - logger.debug("Failed to cache database configurations: %s", e) |
652 | | - _cached_db_configs = {} |
| 655 | + db_wrapper = connections.get(alias) |
| 656 | + if db_wrapper is None: |
| 657 | + continue |
| 658 | + |
| 659 | + if hasattr(db_wrapper, "vendor"): |
| 660 | + _cached_db_configs[alias]["vendor"] = db_wrapper.vendor |
| 661 | + |
| 662 | + # Mark as initialized only after successful completion |
| 663 | + _cache_initialized = True |
| 664 | + |
| 665 | + except Exception as e: |
| 666 | + logger.debug("Failed to cache database configurations: %s", e) |
| 667 | + _cached_db_configs = {} |
653 | 668 |
|
654 | 669 |
|
655 | 670 | def install_sql_hook(): |
|
0 commit comments