110110import com .google .cloud .bigtable .data .v2 .stub .mutaterows .MutateRowsPartialErrorRetryAlgorithm ;
111111import com .google .cloud .bigtable .data .v2 .stub .mutaterows .MutateRowsRetryingCallable ;
112112import com .google .cloud .bigtable .data .v2 .stub .readrows .FilterMarkerRowsCallable ;
113+ import com .google .cloud .bigtable .data .v2 .stub .readrows .LargeReadRowsResumptionStrategy ;
113114import com .google .cloud .bigtable .data .v2 .stub .readrows .ReadRowsBatchingDescriptor ;
114115import com .google .cloud .bigtable .data .v2 .stub .readrows .ReadRowsFirstCallable ;
115116import com .google .cloud .bigtable .data .v2 .stub .readrows .ReadRowsResumptionStrategy ;
@@ -176,6 +177,9 @@ public class EnhancedBigtableStub implements AutoCloseable {
176177 private final DynamicFlowControlStats bulkMutationDynamicFlowControlStats ;
177178
178179 private final ServerStreamingCallable <Query , Row > readRowsCallable ;
180+
181+ private final ServerStreamingCallable <Query , Row > skipLargeRowsCallable ;
182+
179183 private final UnaryCallable <Query , Row > readRowCallable ;
180184 private final UnaryCallable <Query , List <Row >> bulkReadRowsCallable ;
181185 @ Deprecated private final UnaryCallable <String , List <KeyOffset >> sampleRowKeysCallable ;
@@ -304,6 +308,7 @@ public EnhancedBigtableStub(
304308 this .bulkMutationDynamicFlowControlStats = new DynamicFlowControlStats ();
305309
306310 readRowsCallable = createReadRowsCallable (new DefaultRowAdapter ());
311+ skipLargeRowsCallable = createSkipLargeRowsCallable (new DefaultRowAdapter ());
307312 readRowCallable = createReadRowCallable (new DefaultRowAdapter ());
308313 bulkReadRowsCallable = createBulkReadRowsCallable (new DefaultRowAdapter ());
309314 sampleRowKeysCallable = createSampleRowKeysCallable ();
@@ -445,6 +450,7 @@ private <ReqT, RowT> ServerStreamingCallable<ReadRowsRequest, RowT> createReadRo
445450 return createReadRowsBaseCallable (
446451 readRowsSettings , rowAdapter , new ReadRowsResumptionStrategy <RowT >(rowAdapter ));
447452 }
453+
448454 /**
449455 * Creates a callable chain to handle ReadRows RPCs. The chain will:
450456 *
@@ -515,6 +521,96 @@ private <ReqT, RowT> ServerStreamingCallable<ReadRowsRequest, RowT> createReadRo
515521 return new FilterMarkerRowsCallable <>(retrying2 , rowAdapter );
516522 }
517523
524+ /**
525+ * Creates a callable chain to handle streaming ReadRows RPCs. This chain skips the large rows
526+ * internally. The chain will:
527+ *
528+ * <ul>
529+ * <li>Convert a {@link Query} into a {@link com.google.bigtable.v2.ReadRowsRequest}.
530+ * <li>Dispatch the RPC with {@link ReadRowsRequest}.
531+ * <li>Upon receiving the response stream, it will merge the {@link
532+ * com.google.bigtable.v2.ReadRowsResponse.CellChunk}s in logical rows. The actual row
533+ * implementation can be configured in by the {@code rowAdapter} parameter.
534+ * <li>Add bigtable tracer for tracking bigtable specific metrics.
535+ * <li>Retry/resume on failure (retries for retryable error codes, connection errors and skip
536+ * large row keys)
537+ * <li>Filter out marker rows.
538+ * <li>Add tracing & metrics.
539+ * </ul>
540+ */
541+ private <ReqT , RowT > ServerStreamingCallable <Query , RowT > createSkipLargeRowsCallable (
542+ RowAdapter <RowT > rowAdapter ) {
543+
544+ ServerStreamingCallSettings <ReqT , Row > readRowsSettings =
545+ (ServerStreamingCallSettings <ReqT , Row >) settings .readRowsSettings ();
546+
547+ ServerStreamingCallable <ReadRowsRequest , ReadRowsResponse > base =
548+ GrpcRawCallableFactory .createServerStreamingCallable (
549+ GrpcCallSettings .<ReadRowsRequest , ReadRowsResponse >newBuilder ()
550+ .setMethodDescriptor (BigtableGrpc .getReadRowsMethod ())
551+ .setParamsExtractor (
552+ r ->
553+ composeRequestParams (
554+ r .getAppProfileId (), r .getTableName (), r .getAuthorizedViewName ()))
555+ .build (),
556+ readRowsSettings .getRetryableCodes ());
557+
558+ ServerStreamingCallable <ReadRowsRequest , ReadRowsResponse > withStatsHeaders =
559+ new StatsHeadersServerStreamingCallable <>(base );
560+
561+ // Sometimes ReadRows connections are disconnected via an RST frame. This error is transient and
562+ // should be treated similar to UNAVAILABLE. However, this exception has an INTERNAL error code
563+ // which by default is not retryable. Convert the exception so it can be retried in the client.
564+ ServerStreamingCallable <ReadRowsRequest , ReadRowsResponse > convertException =
565+ new ConvertExceptionCallable <>(withStatsHeaders );
566+
567+ ServerStreamingCallable <ReadRowsRequest , RowT > merging =
568+ new RowMergingCallable <>(convertException , rowAdapter );
569+
570+ // Copy settings for the middle ReadRowsRequest -> RowT callable (as opposed to the inner
571+ // ReadRowsRequest -> ReadRowsResponse callable).
572+ // We override the resumption strategy to use LargeReadRowsResumptionStrategy here (which skips
573+ // the large rows) instead of ReadRowResumptionStrategy
574+ ServerStreamingCallSettings <ReadRowsRequest , RowT > innerSettings =
575+ ServerStreamingCallSettings .<ReadRowsRequest , RowT >newBuilder ()
576+ .setResumptionStrategy (new LargeReadRowsResumptionStrategy <>(rowAdapter ))
577+ .setRetryableCodes (readRowsSettings .getRetryableCodes ())
578+ .setRetrySettings (readRowsSettings .getRetrySettings ())
579+ .setIdleTimeout (readRowsSettings .getIdleTimeout ())
580+ .setWaitTimeout (readRowsSettings .getWaitTimeout ())
581+ .build ();
582+
583+ ServerStreamingCallable <ReadRowsRequest , RowT > watched =
584+ Callables .watched (merging , innerSettings , clientContext );
585+
586+ ServerStreamingCallable <ReadRowsRequest , RowT > withBigtableTracer =
587+ new BigtableTracerStreamingCallable <>(watched );
588+
589+ // Retry logic is split into 2 parts to workaround a rare edge case described in
590+ // ReadRowsRetryCompletedCallable
591+ ServerStreamingCallable <ReadRowsRequest , RowT > retrying1 =
592+ new ReadRowsRetryCompletedCallable <>(withBigtableTracer );
593+
594+ ServerStreamingCallable <ReadRowsRequest , RowT > retrying2 =
595+ largeRowWithRetries (retrying1 , innerSettings );
596+
597+ ServerStreamingCallable <ReadRowsRequest , RowT > readRowsCallable =
598+ new FilterMarkerRowsCallable <>(retrying2 , rowAdapter );
599+
600+ ServerStreamingCallable <Query , RowT > readRowsUserCallable =
601+ new ReadRowsUserCallable <>(readRowsCallable , requestContext );
602+
603+ SpanName span = getSpanName ("ReadRows" );
604+ ServerStreamingCallable <Query , RowT > traced =
605+ new TracedServerStreamingCallable <>(
606+ readRowsUserCallable , clientContext .getTracerFactory (), span );
607+
608+ return traced .withDefaultCallContext (
609+ clientContext
610+ .getDefaultCallContext ()
611+ .withRetrySettings (readRowsSettings .getRetrySettings ()));
612+ }
613+
518614 /**
519615 * Creates a callable chain to handle bulk ReadRows RPCs. This is meant to be used in ReadRows
520616 * batcher. The chain will:
@@ -1282,6 +1378,22 @@ private <RequestT, ResponseT> ServerStreamingCallable<RequestT, ResponseT> withR
12821378 return retrying ;
12831379 }
12841380
1381+ private <RequestT , ResponseT > ServerStreamingCallable <RequestT , ResponseT > largeRowWithRetries (
1382+ ServerStreamingCallable <RequestT , ResponseT > innerCallable ,
1383+ ServerStreamingCallSettings <RequestT , ResponseT > serverStreamingCallSettings ) {
1384+
1385+ // Retrying algorithm in retryingForLargeRows also takes RetryInfo into consideration, so we
1386+ // skip the check for settings.getEnableRetryInfo here
1387+ ServerStreamingCallable <RequestT , ResponseT > retrying ;
1388+ retrying =
1389+ com .google .cloud .bigtable .gaxx .retrying .Callables .retryingForLargeRows (
1390+ innerCallable , serverStreamingCallSettings , clientContext );
1391+ if (settings .getEnableRoutingCookie ()) {
1392+ return new CookiesServerStreamingCallable <>(retrying );
1393+ }
1394+ return retrying ;
1395+ }
1396+
12851397 // </editor-fold>
12861398
12871399 // <editor-fold desc="Callable accessors">
@@ -1290,6 +1402,11 @@ public ServerStreamingCallable<Query, Row> readRowsCallable() {
12901402 return readRowsCallable ;
12911403 }
12921404
1405+ /** Returns a streaming read rows callable that skips large rows */
1406+ public ServerStreamingCallable <Query , Row > skipLargeRowsCallable () {
1407+ return skipLargeRowsCallable ;
1408+ }
1409+
12931410 /** Return a point read callable */
12941411 public UnaryCallable <Query , Row > readRowCallable () {
12951412 return readRowCallable ;
0 commit comments