Skip to content

Commit 7917b11

Browse files
committed
fix(storage): Handle request transformation correctly after BidiWriteObject redirects
This commit addresses an issue where BidiWriteObject operations, particularly in cross-region redirect scenarios, would fail with a NOT_FOUND error. The root cause was that bucket information was not propagated in the request headers after the client received a redirect error from the service.
1 parent f3de489 commit 7917b11

10 files changed

Lines changed: 605 additions & 98 deletions

google/cloud/storage/internal/async/connection_impl.cc

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,11 @@ AsyncConnectionImpl::AppendableObjectUploadImpl(AppendableUploadParams p) {
334334
auto factory = WriteResultFactory(
335335
[stub = stub_, cq = cq_, retry = std::move(retry),
336336
// NOLINTNEXTLINE(bugprone-lambda-function-name)
337-
backoff = std::move(backoff), current, function_name = __func__](
337+
backoff = std::move(backoff), current, function_name = __func__,
338+
// Use shared_ptr to propagate RoutingHeaderOptions across retries.
339+
current_routing_options = std::make_shared<RoutingHeaderOptions>()](
338340
google::storage::v2::BidiWriteObjectRequest req) {
339-
auto call = [stub, request = std::move(req)](
341+
auto call = [stub, request = std::move(req), current_routing_options](
340342
CompletionQueue& cq,
341343
std::shared_ptr<grpc::ClientContext> context,
342344
google::cloud::internal::ImmutableOptions options,
@@ -351,9 +353,11 @@ AsyncConnectionImpl::AppendableObjectUploadImpl(AppendableUploadParams p) {
351353

352354
// Apply the routing header
353355
if (request.has_write_object_spec())
354-
ApplyRoutingHeaders(*context, request.write_object_spec());
356+
ApplyRoutingHeaders(*context, request.write_object_spec(),
357+
*current_routing_options);
355358
else
356-
ApplyRoutingHeaders(*context, request.append_object_spec());
359+
ApplyRoutingHeaders(*context, request.append_object_spec(),
360+
*current_routing_options);
357361

358362
auto rpc = stub->AsyncBidiWriteObject(cq, std::move(context),
359363
std::move(options));
@@ -362,18 +366,23 @@ AsyncConnectionImpl::AppendableObjectUploadImpl(AppendableUploadParams p) {
362366
std::move(rpc));
363367
request.set_state_lookup(true);
364368
auto open = std::make_shared<WriteObject>(std::move(rpc), request);
365-
return open->Call().then([open, &request](auto f) mutable {
366-
open.reset();
367-
auto response = f.get();
368-
if (!response) {
369-
google::rpc::Status grpc_status =
370-
ExtractGrpcStatus(response.status());
371-
EnsureFirstMessageAppendObjectSpec(request, grpc_status);
372-
ApplyWriteRedirectErrors(*request.mutable_append_object_spec(),
373-
grpc_status);
374-
}
375-
return response;
376-
});
369+
return open->Call().then(
370+
[open, &request, current_routing_options](auto f) mutable {
371+
open.reset();
372+
auto response = f.get();
373+
if (!response) {
374+
google::rpc::Status grpc_status =
375+
ExtractGrpcStatus(response.status());
376+
// Handle redirect and get info for updating routing options.
377+
BidiWriteRedirectInfo redirect_info =
378+
HandleBidiWriteRedirect(request, grpc_status);
379+
380+
// Update RoutingHeaderOptions for the next attempt.
381+
current_routing_options->routing_token =
382+
redirect_info.routing_token;
383+
}
384+
return response;
385+
});
377386
};
378387

379388
return google::cloud::internal::AsyncRetryLoop(

0 commit comments

Comments
 (0)