From 3d358cf431d2ef96a17bcb78ccfda05d8ee0c8b0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 12 Jun 2025 22:21:15 -0500 Subject: [PATCH] lock --- esphome/platformio_api.py | 27 +++++++++++++++++++++------ script/test_build_components | 7 +++++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/esphome/platformio_api.py b/esphome/platformio_api.py index 62bac150a3..a4052df51b 100644 --- a/esphome/platformio_api.py +++ b/esphome/platformio_api.py @@ -89,18 +89,33 @@ def run_platformio_cli(*args, **kwargs) -> str | int: # Import platformio with lock to prevent race conditions during initialization from esphome.git_lock import platformio_init_lock, platformio_install_lock + # Check if ~/.platformio exists to determine if initial setup is needed + home_pio = Path.home() / ".platformio" + needs_init = not home_pio.exists() + with platformio_init_lock(): import platformio.__main__ + # If this is the first time, ensure the directory is created + if needs_init: + _LOGGER.info("Initializing PlatformIO for the first time...") + home_pio.mkdir(exist_ok=True) + patch_structhash() - # For run commands that might install packages, use global locking - # This prevents concurrent package installations which cause conflicts + # For run commands, check if this is the first run that might need package installation if len(args) > 0 and args[0] == "run": - with platformio_install_lock("global_packages"): - return run_external_command(platformio.__main__.main, *cmd, **kwargs) - else: - return run_external_command(platformio.__main__.main, *cmd, **kwargs) + # Check if .pio directory exists - if not, we need to lock for initial setup + pio_dir = Path(CORE.build_path) / ".pio" + if not pio_dir.exists(): + _LOGGER.info("First build detected, using lock for PlatformIO setup...") + with platformio_install_lock("initial_setup", timeout=600.0): + result = run_external_command(platformio.__main__.main, *cmd, **kwargs) + _LOGGER.info("Initial PlatformIO setup completed") + return result + + # For subsequent runs or non-run commands, no locking needed + return run_external_command(platformio.__main__.main, *cmd, **kwargs) def run_platformio_cli_run(config, verbose, *args, **kwargs) -> str | int: diff --git a/script/test_build_components b/script/test_build_components index e4c0d467ed..b100e84a4c 100755 --- a/script/test_build_components +++ b/script/test_build_components @@ -118,6 +118,13 @@ start_esphome() { ( # Add compile process limit for ESPHome internal parallelization export ESPHOME_COMPILE_PROCESS_LIMIT=2 + + # For compilation, add a small random delay to reduce thundering herd effect + # This helps stagger the package installation requests + if [ "$esphome_command" = "compile" ]; then + sleep $((RANDOM % 3)) + fi + python3 -m esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file ) &