From 53635c7c903eb730a944da038c797befc7ded4d9 Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Sat, 15 Aug 2026 12:15:29 -0400 Subject: [PATCH] GH-50876: [C++][FS][Azure] Wait for Azurite to start This should help with flakiness. Fixes #50876 Assisted-by: Codex --- cpp/src/arrow/filesystem/azurefs_test.cc | 60 ++++++++++++++++-------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/cpp/src/arrow/filesystem/azurefs_test.cc b/cpp/src/arrow/filesystem/azurefs_test.cc index 4cd425055540..250e3572bd9b 100644 --- a/cpp/src/arrow/filesystem/azurefs_test.cc +++ b/cpp/src/arrow/filesystem/azurefs_test.cc @@ -18,6 +18,7 @@ #include "arrow/filesystem/azurefs.h" #include "arrow/filesystem/azurefs_internal.h" +#include #include #include #include @@ -91,6 +92,26 @@ class BaseAzureEnv : public ::testing::Environment { } }; +namespace { +Result MakeOptions(BaseAzureEnv* env) { + AzureOptions options; + options.account_name = env->account_name(); + switch (env->backend()) { + case AzureBackend::kAzurite: + options.blob_storage_authority = "127.0.0.1:10000"; + options.dfs_storage_authority = "127.0.0.1:10000"; + options.blob_storage_scheme = "http"; + options.dfs_storage_scheme = "http"; + break; + case AzureBackend::kAzure: + // Use the default values + break; + } + ARROW_EXPECT_OK(options.ConfigureAccountKeyCredential(env->account_key())); + return options; +} +} // namespace + template class AzureEnvImpl : public BaseAzureEnv { private: @@ -158,6 +179,24 @@ class AzuriteEnv : public AzureEnvImpl { arrow::internal::PlatformFilename debug_log_path_; std::unique_ptr server_process_; + // Azurite has no readiness endpoint: https://github.com/Azure/Azurite/issues/1666 + Status WaitForStartup() { + ARROW_ASSIGN_OR_RAISE(auto options, MakeOptions(this)); + ARROW_ASSIGN_OR_RAISE(auto client, options.MakeBlobServiceClient()); + const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(30); + std::string last_error; + while (server_process_->IsRunning() && std::chrono::steady_clock::now() < deadline) { + try { + client->ListBlobContainers(); + return Status::OK(); + } catch (const std::exception& exception) { + last_error = exception.what(); + } + SleepFor(0.1); + } + return Status::IOError("Azurite failed to start: ", last_error); + } + using AzureEnvImpl::AzureEnvImpl; public: @@ -182,6 +221,7 @@ class AzuriteEnv : public AzureEnvImpl { // Azurite with old Node.js on old Ubuntu. "--skipApiVersionCheck"}); ARROW_RETURN_NOT_OK(self->server_process_->Execute()); + ARROW_RETURN_NOT_OK(self->WaitForStartup()); return self; } @@ -264,26 +304,6 @@ class AzureHierarchicalNSEnv : public AzureEnvImpl { bool WithHierarchicalNamespace() const final { return true; } }; -namespace { -Result MakeOptions(BaseAzureEnv* env) { - AzureOptions options; - options.account_name = env->account_name(); - switch (env->backend()) { - case AzureBackend::kAzurite: - options.blob_storage_authority = "127.0.0.1:10000"; - options.dfs_storage_authority = "127.0.0.1:10000"; - options.blob_storage_scheme = "http"; - options.dfs_storage_scheme = "http"; - break; - case AzureBackend::kAzure: - // Use the default values - break; - } - ARROW_EXPECT_OK(options.ConfigureAccountKeyCredential(env->account_key())); - return options; -} -} // namespace - struct PreexistingData { public: using RNG = random::pcg32_fast;