@@ -29,7 +29,7 @@ DefaultRowReader::DefaultRowReader(
2929 bigtable::Filter filter, bool reverse,
3030 std::unique_ptr<bigtable::DataRetryPolicy> retry_policy,
3131 std::unique_ptr<BackoffPolicy> backoff_policy, bool enable_server_retries,
32- Sleeper sleeper)
32+ std::shared_ptr<OperationContext> operation_context, Sleeper sleeper)
3333 : stub_(std::move(stub)),
3434 app_profile_id_ (std::move(app_profile_id)),
3535 table_name_(std::move(table_name)),
@@ -40,7 +40,8 @@ DefaultRowReader::DefaultRowReader(
4040 retry_policy_(std::move(retry_policy)),
4141 backoff_policy_(std::move(backoff_policy)),
4242 enable_server_retries_(enable_server_retries),
43- sleeper_(std::move(sleeper)) {}
43+ sleeper_(std::move(sleeper)),
44+ operation_context_(std::move(operation_context)) {}
4445
4546void DefaultRowReader::MakeRequest () {
4647 response_ = {};
@@ -62,10 +63,11 @@ void DefaultRowReader::MakeRequest() {
6263 }
6364
6465 auto const & options = internal::CurrentOptions ();
65- context_ = std::make_shared<grpc::ClientContext>();
66- internal::ConfigureContext (*context_, options);
67- operation_context_.PreCall (*context_);
68- stream_ = stub_->ReadRows (context_, options, request);
66+ client_context_ = std::make_shared<grpc::ClientContext>();
67+ internal::ConfigureContext (*client_context_, options);
68+ operation_context_->PreCall (*client_context_);
69+ called_post_call_ = false ;
70+ stream_ = stub_->ReadRows (client_context_, options, request);
6971 stream_is_open_ = true ;
7072
7173 parser_ = bigtable::internal::ReadRowsParserFactory ().Create (reverse_);
@@ -78,9 +80,9 @@ bool DefaultRowReader::NextChunk() {
7880 auto v = stream_->Read ();
7981 if (absl::holds_alternative<Status>(v)) {
8082 last_status_ = absl::get<Status>(std::move (v));
83+ operation_context_->PostCall (*client_context_, last_status_);
84+ called_post_call_ = true ;
8185 response_ = {};
82- operation_context_.PostCall (*context_, {});
83- context_.reset ();
8486 return false ;
8587 }
8688 response_ = absl::get<google::bigtable::v2::ReadRowsResponse>(std::move (v));
@@ -92,6 +94,11 @@ bool DefaultRowReader::NextChunk() {
9294}
9395
9496absl::variant<Status, bigtable::Row> DefaultRowReader::Advance () {
97+ // We only want to call ElementRequest if an RPC has previously been
98+ // made.
99+ if (stream_is_open_) {
100+ operation_context_->ElementRequest (*client_context_);
101+ }
95102 if (operation_cancelled_) {
96103 return internal::CancelledError (
97104 " call cancelled" ,
@@ -100,6 +107,7 @@ absl::variant<Status, bigtable::Row> DefaultRowReader::Advance() {
100107 while (true ) {
101108 auto variant = AdvanceOrFail ();
102109 if (absl::holds_alternative<bigtable::Row>(variant)) {
110+ operation_context_->ElementDelivery (*client_context_);
103111 return absl::get<bigtable::Row>(std::move (variant));
104112 }
105113
@@ -143,16 +151,19 @@ absl::variant<Status, bigtable::Row> DefaultRowReader::Advance() {
143151}
144152
145153absl::variant<Status, bigtable::Row> DefaultRowReader::AdvanceOrFail () {
146- grpc::Status status;
147- if (!stream_) {
148- MakeRequest ();
149- }
154+ grpc::Status grpc_status;
155+ if (!stream_) MakeRequest ();
150156 while (!parser_->HasNext ()) {
151157 if (NextChunk ()) {
152158 parser_->HandleChunk (
153159 std::move (*(response_.mutable_chunks (processed_chunks_count_))),
154- status);
155- if (!status.ok ()) return MakeStatusFromRpcError (status);
160+ grpc_status);
161+ if (!grpc_status.ok ()) {
162+ auto status = MakeStatusFromRpcError (grpc_status);
163+ operation_context_->PostCall (*client_context_, status);
164+ called_post_call_ = true ;
165+ return status;
166+ }
156167 continue ;
157168 }
158169
@@ -161,21 +172,30 @@ absl::variant<Status, bigtable::Row> DefaultRowReader::AdvanceOrFail() {
161172 // fails during cleanup.
162173 stream_is_open_ = false ;
163174 if (!last_status_.ok ()) return last_status_;
164- parser_->HandleEndOfStream (status );
165- return MakeStatusFromRpcError (status );
175+ parser_->HandleEndOfStream (grpc_status );
176+ return MakeStatusFromRpcError (grpc_status );
166177 }
167178
168179 // We have a complete row in the parser.
169- bigtable::Row parsed_row = parser_->Next (status );
180+ bigtable::Row parsed_row = parser_->Next (grpc_status );
170181
171- if (!status .ok ()) return MakeStatusFromRpcError (status );
182+ if (!grpc_status .ok ()) return MakeStatusFromRpcError (grpc_status );
172183
173184 ++rows_count_;
174185 last_read_row_key_ = parsed_row.row_key ();
175186 return parsed_row;
176187}
177188
178189void DefaultRowReader::Cancel () {
190+ // As the destructor also calls Cancel, we want to call OnDone exactly once.
191+ // If parser_ == nullptr, then we know no RPC was ever attempted.
192+ if (!operation_cancelled_ && parser_) {
193+ if (!called_post_call_) {
194+ called_post_call_ = true ;
195+ operation_context_->PostCall (*client_context_, last_status_);
196+ }
197+ operation_context_->OnDone (last_status_);
198+ }
179199 operation_cancelled_ = true ;
180200 if (!stream_is_open_) return ;
181201 stream_->Cancel ();
@@ -185,7 +205,7 @@ void DefaultRowReader::Cancel() {
185205 stream_->Read ())) {
186206 }
187207
188- context_ .reset ();
208+ client_context_ .reset ();
189209 stream_is_open_ = false ;
190210}
191211
0 commit comments