From 5b3ca47c31f64a2f9e727200612ed30f3ce6378d Mon Sep 17 00:00:00 2001 From: v-pratap Date: Thu, 2 Apr 2026 18:02:55 +0000 Subject: [PATCH 1/6] feat(storage): add IsOpen API for zonal read operation --- .../cloud/storage/async/object_descriptor.cc | 2 + .../cloud/storage/async/object_descriptor.h | 8 ++ .../async/object_descriptor_connection.h | 8 ++ .../storage/async/object_descriptor_test.cc | 9 ++ .../storage/internal/async/connection_impl.cc | 37 +++++--- .../object_descriptor_connection_tracing.cc | 1 + .../internal/async/object_descriptor_impl.cc | 14 ++- .../internal/async/object_descriptor_impl.h | 9 +- .../async/object_descriptor_impl_test.cc | 90 +++++++++++++++++-- .../mock_async_object_descriptor_connection.h | 1 + 10 files changed, 157 insertions(+), 22 deletions(-) diff --git a/google/cloud/storage/async/object_descriptor.cc b/google/cloud/storage/async/object_descriptor.cc index 3f1bbabb88a5e..cb66a50f2658c 100644 --- a/google/cloud/storage/async/object_descriptor.cc +++ b/google/cloud/storage/async/object_descriptor.cc @@ -52,6 +52,8 @@ std::pair ObjectDescriptor::ReadLast( return {AsyncReader(std::move(reader)), std::move(token)}; } +bool ObjectDescriptor::IsOpen() const { return impl_->IsOpen(); } + GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace storage } // namespace cloud diff --git a/google/cloud/storage/async/object_descriptor.h b/google/cloud/storage/async/object_descriptor.h index c826859d7a027..545d4ba96aeea 100644 --- a/google/cloud/storage/async/object_descriptor.h +++ b/google/cloud/storage/async/object_descriptor.h @@ -76,6 +76,14 @@ class ObjectDescriptor { */ std::pair ReadLast(std::int64_t limit); + /** + * Returns true if the descriptor is open. + * + * A descriptor is open if it has not been cancelled and has not hit a + * permanent failure. + */ + bool IsOpen() const; + private: std::shared_ptr impl_; }; diff --git a/google/cloud/storage/async/object_descriptor_connection.h b/google/cloud/storage/async/object_descriptor_connection.h index f7ea1898a12bf..6d8115fb7fcd0 100644 --- a/google/cloud/storage/async/object_descriptor_connection.h +++ b/google/cloud/storage/async/object_descriptor_connection.h @@ -61,6 +61,14 @@ class ObjectDescriptorConnection { virtual std::unique_ptr Read(ReadParams p) = 0; virtual void MakeSubsequentStream() = 0; + + /** + * Returns true if the descriptor is open. + * + * A descriptor is open if it has not been cancelled and has not hit a + * permanent failure. + */ + virtual bool IsOpen() const = 0; }; GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END diff --git a/google/cloud/storage/async/object_descriptor_test.cc b/google/cloud/storage/async/object_descriptor_test.cc index 4fd3dd0724235..5426d194ab2fd 100644 --- a/google/cloud/storage/async/object_descriptor_test.cc +++ b/google/cloud/storage/async/object_descriptor_test.cc @@ -186,6 +186,15 @@ TEST(ObjectDescriptor, ReadExceedsMaxRange) { EXPECT_FALSE(token.valid()); } +TEST(ObjectDescriptor, IsOpen) { + auto mock = std::make_shared(); + EXPECT_CALL(*mock, IsOpen).WillOnce(Return(true)).WillOnce(Return(false)); + + auto tested = ObjectDescriptor(mock); + EXPECT_TRUE(tested.IsOpen()); + EXPECT_FALSE(tested.IsOpen()); +} + } // namespace GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace storage diff --git a/google/cloud/storage/internal/async/connection_impl.cc b/google/cloud/storage/internal/async/connection_impl.cc index 32ae9a4e9f0e0..5e3cd2610ff1b 100644 --- a/google/cloud/storage/internal/async/connection_impl.cc +++ b/google/cloud/storage/internal/async/connection_impl.cc @@ -55,6 +55,7 @@ #include "google/cloud/internal/async_streaming_read_rpc_timeout.h" #include "google/cloud/internal/async_streaming_write_rpc_timeout.h" #include "google/cloud/internal/make_status.h" +#include #include #include @@ -231,19 +232,29 @@ AsyncConnectionImpl::Open(OpenParams p) { auto pending = factory(std::move(initial_request)); using ReturnType = std::shared_ptr; - return pending.then( - [rp = std::move(resume_policy), fa = std::move(factory), - rs = std::move(p.read_spec), - options = std::move(p.options)](auto f) mutable -> StatusOr { - auto result = f.get(); - if (!result) return std::move(result).status(); - - auto impl = std::make_shared( - std::move(rp), std::move(fa), std::move(rs), - std::move(result->stream), std::move(options)); - impl->Start(std::move(result->first_response)); - return ReturnType(impl); - }); + return pending.then([rp = std::move(resume_policy), fa = std::move(factory), + rs = std::move(p.read_spec), + options = std::move(p.options), refresh = refresh_]( + auto f) mutable -> StatusOr { + auto result = f.get(); + if (!result) return std::move(result).status(); + + auto transport_ok = [refresh] { + for (auto const& channel : refresh->channels()) { + auto state = channel->GetState(false); + if (state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_IDLE || + state == GRPC_CHANNEL_CONNECTING) { + return true; + } + } + return false; + }; + auto impl = std::make_shared( + std::move(rp), std::move(fa), std::move(rs), std::move(result->stream), + std::move(options), std::move(transport_ok)); + impl->Start(std::move(result->first_response)); + return ReturnType(impl); + }); } future>> diff --git a/google/cloud/storage/internal/async/object_descriptor_connection_tracing.cc b/google/cloud/storage/internal/async/object_descriptor_connection_tracing.cc index 64cf5bde9d4ed..58adf2e2c6c5f 100644 --- a/google/cloud/storage/internal/async/object_descriptor_connection_tracing.cc +++ b/google/cloud/storage/internal/async/object_descriptor_connection_tracing.cc @@ -46,6 +46,7 @@ class AsyncObjectDescriptorConnectionTracing absl::optional metadata() const override { return impl_->metadata(); } + bool IsOpen() const override { return impl_->IsOpen(); } std::unique_ptr Read(ReadParams p) override { internal::OTelScope scope(span_); diff --git a/google/cloud/storage/internal/async/object_descriptor_impl.cc b/google/cloud/storage/internal/async/object_descriptor_impl.cc index c4ab3e28c9a43..dd9080ff5704b 100644 --- a/google/cloud/storage/internal/async/object_descriptor_impl.cc +++ b/google/cloud/storage/internal/async/object_descriptor_impl.cc @@ -34,11 +34,13 @@ ObjectDescriptorImpl::ObjectDescriptorImpl( std::unique_ptr resume_policy, OpenStreamFactory make_stream, google::storage::v2::BidiReadObjectSpec read_object_spec, - std::shared_ptr stream, Options options) + std::shared_ptr stream, Options options, + std::function transport_ok) : resume_policy_prototype_(std::move(resume_policy)), make_stream_(std::move(make_stream)), read_object_spec_(std::move(read_object_spec)), - options_(std::move(options)) { + options_(std::move(options)), + transport_ok_(std::move(transport_ok)) { stream_manager_ = std::make_unique( []() -> std::shared_ptr { return nullptr; }, // NOLINT std::make_shared(std::move(stream), @@ -62,8 +64,16 @@ void ObjectDescriptorImpl::Start( } } +bool ObjectDescriptorImpl::IsOpen() const { + std::unique_lock lk(mu_); + if (cancelled_) return false; + if (stream_manager_->Empty()) return false; + return transport_ok_(); +} + void ObjectDescriptorImpl::Cancel() { std::unique_lock lk(mu_); + if (cancelled_) return; cancelled_ = true; if (stream_manager_) stream_manager_->CancelAll(); if (pending_stream_.valid()) pending_stream_.cancel(); diff --git a/google/cloud/storage/internal/async/object_descriptor_impl.h b/google/cloud/storage/internal/async/object_descriptor_impl.h index f7f8a0d55a285..6d2f7b0ecdb5a 100644 --- a/google/cloud/storage/internal/async/object_descriptor_impl.h +++ b/google/cloud/storage/internal/async/object_descriptor_impl.h @@ -27,6 +27,7 @@ #include "absl/types/optional.h" #include "google/storage/v2/storage.pb.h" #include +#include #include #include #include @@ -59,8 +60,8 @@ class ObjectDescriptorImpl ObjectDescriptorImpl(std::unique_ptr resume_policy, OpenStreamFactory make_stream, google::storage::v2::BidiReadObjectSpec read_object_spec, - std::shared_ptr stream, - Options options = {}); + std::shared_ptr stream, Options options = {}, + std::function transport_ok = {}); ~ObjectDescriptorImpl() override; // Start the read loop. @@ -82,6 +83,8 @@ class ObjectDescriptorImpl std::size_t StreamSize() const; + bool IsOpen() const override; + private: using StreamManager = MultiStreamManager; using StreamIterator = @@ -123,6 +126,8 @@ class ObjectDescriptorImpl google::cloud::StatusOr> pending_stream_; bool cancelled_ = false; + bool permanent_failure_ = false; + std::function transport_ok_; }; GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END diff --git a/google/cloud/storage/internal/async/object_descriptor_impl_test.cc b/google/cloud/storage/internal/async/object_descriptor_impl_test.cc index 96c998b51c1eb..f87f8b3c1a939 100644 --- a/google/cloud/storage/internal/async/object_descriptor_impl_test.cc +++ b/google/cloud/storage/internal/async/object_descriptor_impl_test.cc @@ -67,15 +67,18 @@ auto constexpr kMetadataText = R"pb( auto NoResume() { return storage::LimitedErrorCountResumePolicy(0)(); } -auto MakeTested(std::unique_ptr resume_policy, - OpenStreamFactory make_stream, - google::storage::v2::BidiReadObjectSpec read_object_spec, - std::shared_ptr stream) { +auto MakeTested( + std::unique_ptr resume_policy, + OpenStreamFactory make_stream, + google::storage::v2::BidiReadObjectSpec read_object_spec, + std::shared_ptr stream, + std::function transport_ok = [] { return true; }) { Options options; options.set(true); return std::make_shared( std::move(resume_policy), std::move(make_stream), - std::move(read_object_spec), std::move(stream), std::move(options)); + std::move(read_object_spec), std::move(stream), std::move(options), + std::move(transport_ok)); } MATCHER_P(IsProtoEqualModuloRepeatedFieldOrdering, value, @@ -1784,6 +1787,83 @@ TEST(ObjectDescriptorImpl, MultiStreamOptimizationDisabled) { tested.reset(); } +/// @test Verify that IsOpen() is true by default. +TEST(ObjectDescriptorImpl, IsOpenTrueByDefault) { + MockFactory factory; + auto stream = std::make_unique(); + EXPECT_CALL(*stream, Finish).WillOnce(Return(make_ready_future(Status{}))); + EXPECT_CALL(*stream, Cancel).Times(AtMost(1)); + auto tested = MakeTested(NoResume(), factory.AsStdFunction(), + google::storage::v2::BidiReadObjectSpec{}, + std::make_shared(std::move(stream))); + EXPECT_TRUE(tested->IsOpen()); +} + +/// @test Verify that IsOpen() is false after Cancel(). +TEST(ObjectDescriptorImpl, IsOpenFalseOnCancel) { + MockFactory factory; + auto stream = std::make_unique(); + EXPECT_CALL(*stream, Finish).WillOnce(Return(make_ready_future(Status{}))); + EXPECT_CALL(*stream, Cancel).Times(AtMost(2)); + auto tested = MakeTested(NoResume(), factory.AsStdFunction(), + google::storage::v2::BidiReadObjectSpec{}, + std::make_shared(std::move(stream))); + EXPECT_TRUE(tested->IsOpen()); + tested->Cancel(); + EXPECT_FALSE(tested->IsOpen()); +} + +/// @test Verify that IsOpen() is false if transport health check fails. +TEST(ObjectDescriptorImpl, IsOpenFalseOnPermanentError) { + MockFactory factory; + auto stream = std::make_unique(); + EXPECT_CALL(*stream, Finish).WillOnce(Return(make_ready_future(Status{}))); + EXPECT_CALL(*stream, Cancel).Times(AtMost(1)); + bool transport_ok = true; + auto transport_ok_callback = [&transport_ok] { return transport_ok; }; + + auto tested = MakeTested(NoResume(), factory.AsStdFunction(), + google::storage::v2::BidiReadObjectSpec{}, + std::make_shared(std::move(stream)), + transport_ok_callback); + + EXPECT_TRUE(tested->IsOpen()); + transport_ok = false; + EXPECT_FALSE(tested->IsOpen()); +} + +TEST(ObjectDescriptorImpl, IsOpenFalseOnTransportFailure) { + auto stream = std::make_unique(); + EXPECT_CALL(*stream, Cancel).Times(1); + EXPECT_CALL(*stream, Finish).WillOnce([] { + return make_ready_future(Status{}); + }); + MockFactory factory; + auto transport_ok = [] { return false; }; + auto tested = std::make_shared( + NoResume(), factory.AsStdFunction(), + google::storage::v2::BidiReadObjectSpec{}, + std::make_shared(std::move(stream)), Options{}, + std::move(transport_ok)); + EXPECT_FALSE(tested->IsOpen()); +} + +TEST(ObjectDescriptorImpl, IsOpenTrueOnTransportSuccess) { + auto stream = std::make_unique(); + EXPECT_CALL(*stream, Cancel).Times(1); + EXPECT_CALL(*stream, Finish).WillOnce([] { + return make_ready_future(Status{}); + }); + MockFactory factory; + auto transport_ok = [] { return true; }; + auto tested = std::make_shared( + NoResume(), factory.AsStdFunction(), + google::storage::v2::BidiReadObjectSpec{}, + std::make_shared(std::move(stream)), Options{}, + std::move(transport_ok)); + EXPECT_TRUE(tested->IsOpen()); +} + } // namespace GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace storage_internal diff --git a/google/cloud/storage/mocks/mock_async_object_descriptor_connection.h b/google/cloud/storage/mocks/mock_async_object_descriptor_connection.h index f0e089ac4dada..ad4f2aa94783b 100644 --- a/google/cloud/storage/mocks/mock_async_object_descriptor_connection.h +++ b/google/cloud/storage/mocks/mock_async_object_descriptor_connection.h @@ -33,6 +33,7 @@ class MockAsyncObjectDescriptorConnection (ReadParams), (override)); MOCK_METHOD(void, MakeSubsequentStream, (), (override)); MOCK_METHOD(Options, options, (), (const, override)); + MOCK_METHOD(bool, IsOpen, (), (const, override)); }; GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END From 02eeddb89db4957c28848acd3de0f340de9302b5 Mon Sep 17 00:00:00 2001 From: v-pratap Date: Thu, 2 Apr 2026 18:11:03 +0000 Subject: [PATCH 2/6] resolve gemini code review comments --- .../storage/internal/async/object_descriptor_impl.cc | 10 ++++++---- .../storage/internal/async/object_descriptor_impl.h | 1 - 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/google/cloud/storage/internal/async/object_descriptor_impl.cc b/google/cloud/storage/internal/async/object_descriptor_impl.cc index dd9080ff5704b..e5ea63ccd3ed8 100644 --- a/google/cloud/storage/internal/async/object_descriptor_impl.cc +++ b/google/cloud/storage/internal/async/object_descriptor_impl.cc @@ -65,10 +65,12 @@ void ObjectDescriptorImpl::Start( } bool ObjectDescriptorImpl::IsOpen() const { - std::unique_lock lk(mu_); - if (cancelled_) return false; - if (stream_manager_->Empty()) return false; - return transport_ok_(); + { + std::unique_lock lk(mu_); + if (cancelled_) return false; + if (stream_manager_->Empty()) return false; + } + return !transport_ok_ || transport_ok_(); } void ObjectDescriptorImpl::Cancel() { diff --git a/google/cloud/storage/internal/async/object_descriptor_impl.h b/google/cloud/storage/internal/async/object_descriptor_impl.h index 6d2f7b0ecdb5a..e45ce7caf6cfb 100644 --- a/google/cloud/storage/internal/async/object_descriptor_impl.h +++ b/google/cloud/storage/internal/async/object_descriptor_impl.h @@ -126,7 +126,6 @@ class ObjectDescriptorImpl google::cloud::StatusOr> pending_stream_; bool cancelled_ = false; - bool permanent_failure_ = false; std::function transport_ok_; }; From fe9eed4fbe36b86405786173ca98d407fb4ec766 Mon Sep 17 00:00:00 2001 From: v-pratap Date: Thu, 2 Apr 2026 18:34:48 +0000 Subject: [PATCH 3/6] fix the format --- .../storage/internal/async/connection_impl.cc | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/google/cloud/storage/internal/async/connection_impl.cc b/google/cloud/storage/internal/async/connection_impl.cc index 5e3cd2610ff1b..549639dc55bd8 100644 --- a/google/cloud/storage/internal/async/connection_impl.cc +++ b/google/cloud/storage/internal/async/connection_impl.cc @@ -240,14 +240,14 @@ AsyncConnectionImpl::Open(OpenParams p) { if (!result) return std::move(result).status(); auto transport_ok = [refresh] { - for (auto const& channel : refresh->channels()) { - auto state = channel->GetState(false); - if (state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_IDLE || - state == GRPC_CHANNEL_CONNECTING) { - return true; - } - } - return false; + if (!refresh) return true; + auto const& channels = refresh->channels(); + return std::any_of( + channels.begin(), channels.end(), [](auto const& channel) { + auto state = channel->GetState(false); + return state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_IDLE || + state == GRPC_CHANNEL_CONNECTING; + }); }; auto impl = std::make_shared( std::move(rp), std::move(fa), std::move(rs), std::move(result->stream), @@ -382,7 +382,7 @@ AsyncConnectionImpl::AppendableObjectUploadImpl(AppendableUploadParams p) { return pending.then( [current, request = std::move(p.request), persisted_size, hash = std::move(hash_function), fa = std::move(factory)](auto f) mutable - -> StatusOr> { + -> StatusOr> { auto rpc = f.get(); if (!rpc) return std::move(rpc).status(); std::unique_ptr impl; @@ -438,7 +438,7 @@ AsyncConnectionImpl::StartBufferedUpload(UploadParams p) { return StartUnbufferedUpload(std::move(p)) .then([current = std::move(current), async_write_object = std::move(async_write_object)](auto f) mutable - -> StatusOr> { + -> StatusOr> { auto w = f.get(); if (!w) return std::move(w).status(); auto factory = [upload_id = (*w)->UploadId(), @@ -472,14 +472,15 @@ AsyncConnectionImpl::ResumeBufferedUpload(ResumeUploadParams p) { }; auto f = make_unbuffered(); - return f.then([current = std::move(current), - make_unbuffered = std::move(make_unbuffered)](auto f) mutable - -> StatusOr> { - auto w = f.get(); - if (!w) return std::move(w).status(); - return MakeWriterConnectionBuffered(std::move(make_unbuffered), - *std::move(w), *current); - }); + return f.then( + [current = std::move(current), + make_unbuffered = std::move(make_unbuffered)](auto f) mutable + -> StatusOr> { + auto w = f.get(); + if (!w) return std::move(w).status(); + return MakeWriterConnectionBuffered(std::move(make_unbuffered), + *std::move(w), *current); + }); } future> From 3c8ee9ac8a5f28c0e277af22ed3531d2ba478462 Mon Sep 17 00:00:00 2001 From: v-pratap Date: Thu, 2 Apr 2026 18:47:56 +0000 Subject: [PATCH 4/6] fix the format --- .../storage/internal/async/connection_impl.cc | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/google/cloud/storage/internal/async/connection_impl.cc b/google/cloud/storage/internal/async/connection_impl.cc index 549639dc55bd8..67462ce745446 100644 --- a/google/cloud/storage/internal/async/connection_impl.cc +++ b/google/cloud/storage/internal/async/connection_impl.cc @@ -382,7 +382,7 @@ AsyncConnectionImpl::AppendableObjectUploadImpl(AppendableUploadParams p) { return pending.then( [current, request = std::move(p.request), persisted_size, hash = std::move(hash_function), fa = std::move(factory)](auto f) mutable - -> StatusOr> { + -> StatusOr> { auto rpc = f.get(); if (!rpc) return std::move(rpc).status(); std::unique_ptr impl; @@ -438,7 +438,7 @@ AsyncConnectionImpl::StartBufferedUpload(UploadParams p) { return StartUnbufferedUpload(std::move(p)) .then([current = std::move(current), async_write_object = std::move(async_write_object)](auto f) mutable - -> StatusOr> { + -> StatusOr> { auto w = f.get(); if (!w) return std::move(w).status(); auto factory = [upload_id = (*w)->UploadId(), @@ -472,15 +472,14 @@ AsyncConnectionImpl::ResumeBufferedUpload(ResumeUploadParams p) { }; auto f = make_unbuffered(); - return f.then( - [current = std::move(current), - make_unbuffered = std::move(make_unbuffered)](auto f) mutable - -> StatusOr> { - auto w = f.get(); - if (!w) return std::move(w).status(); - return MakeWriterConnectionBuffered(std::move(make_unbuffered), - *std::move(w), *current); - }); + return f.then([current = std::move(current), + make_unbuffered = std::move(make_unbuffered)](auto f) mutable + -> StatusOr> { + auto w = f.get(); + if (!w) return std::move(w).status(); + return MakeWriterConnectionBuffered(std::move(make_unbuffered), + *std::move(w), *current); + }); } future> From 7bf8a597c99f392394f8ac664a56543cd42d176f Mon Sep 17 00:00:00 2001 From: v-pratap Date: Fri, 3 Apr 2026 07:00:39 +0000 Subject: [PATCH 5/6] Converted IsOpen() function from pure virtual to default virtual function --- google/cloud/storage/async/object_descriptor_connection.h | 2 +- google/cloud/storage/internal/async/connection_impl.cc | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/google/cloud/storage/async/object_descriptor_connection.h b/google/cloud/storage/async/object_descriptor_connection.h index 6d8115fb7fcd0..41560d4673761 100644 --- a/google/cloud/storage/async/object_descriptor_connection.h +++ b/google/cloud/storage/async/object_descriptor_connection.h @@ -68,7 +68,7 @@ class ObjectDescriptorConnection { * A descriptor is open if it has not been cancelled and has not hit a * permanent failure. */ - virtual bool IsOpen() const = 0; + virtual bool IsOpen() const { return true; } }; GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END diff --git a/google/cloud/storage/internal/async/connection_impl.cc b/google/cloud/storage/internal/async/connection_impl.cc index 67462ce745446..b08618132501c 100644 --- a/google/cloud/storage/internal/async/connection_impl.cc +++ b/google/cloud/storage/internal/async/connection_impl.cc @@ -239,6 +239,10 @@ AsyncConnectionImpl::Open(OpenParams p) { auto result = f.get(); if (!result) return std::move(result).status(); + // The descriptor remains open if at least one gRPC channel is in a + // functional state. We consider READY, IDLE, and CONNECTING to be functional. + // TRANSIENT_FAILURE and SHUTDOWN are not included because they indicate + // a definitive loss of connectivity or terminal closure. auto transport_ok = [refresh] { if (!refresh) return true; auto const& channels = refresh->channels(); From 57b8c28367391a019aea9b8ba7e2fcbdbf0bd66a Mon Sep 17 00:00:00 2001 From: v-pratap Date: Fri, 3 Apr 2026 07:46:09 +0000 Subject: [PATCH 6/6] fix the format --- google/cloud/storage/internal/async/connection_impl.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/google/cloud/storage/internal/async/connection_impl.cc b/google/cloud/storage/internal/async/connection_impl.cc index b08618132501c..e67993317b6d0 100644 --- a/google/cloud/storage/internal/async/connection_impl.cc +++ b/google/cloud/storage/internal/async/connection_impl.cc @@ -240,9 +240,9 @@ AsyncConnectionImpl::Open(OpenParams p) { if (!result) return std::move(result).status(); // The descriptor remains open if at least one gRPC channel is in a - // functional state. We consider READY, IDLE, and CONNECTING to be functional. - // TRANSIENT_FAILURE and SHUTDOWN are not included because they indicate - // a definitive loss of connectivity or terminal closure. + // functional state. We consider READY, IDLE, and CONNECTING to be + // functional. TRANSIENT_FAILURE and SHUTDOWN are not included because they + // indicate a definitive loss of connectivity or terminal closure. auto transport_ok = [refresh] { if (!refresh) return true; auto const& channels = refresh->channels();