4141import com .google .api .gax .retrying .RetryAlgorithm ;
4242import com .google .api .gax .retrying .RetryingExecutorWithContext ;
4343import com .google .api .gax .retrying .ScheduledRetryingExecutor ;
44+ import com .google .api .gax .retrying .SimpleStreamResumptionStrategy ;
45+ import com .google .api .gax .retrying .StreamResumptionStrategy ;
4446import com .google .api .gax .rpc .ApiCallContext ;
4547import com .google .api .gax .rpc .Callables ;
4648import com .google .api .gax .rpc .ClientContext ;
136138import com .google .cloud .bigtable .gaxx .retrying .ApiResultRetryAlgorithm ;
137139import com .google .cloud .bigtable .gaxx .retrying .RetryInfoRetryAlgorithm ;
138140import com .google .common .annotations .VisibleForTesting ;
141+ import com .google .common .base .Functions ;
139142import com .google .common .base .MoreObjects ;
140143import com .google .common .base .Preconditions ;
141144import com .google .common .collect .ImmutableList ;
155158import java .io .IOException ;
156159import java .net .URI ;
157160import java .net .URISyntaxException ;
161+ import java .time .Duration ;
158162import java .util .Collections ;
159163import java .util .List ;
160164import java .util .Map ;
@@ -559,27 +563,54 @@ public <RowT> ServerStreamingCallable<Query, RowT> createReadRowsCallable(
559563 * </ul>
560564 */
561565 public <RowT > UnaryCallable <Query , RowT > createReadRowCallable (RowAdapter <RowT > rowAdapter ) {
562- ServerStreamingCallable <ReadRowsRequest , RowT > readRowsCallable =
563- createReadRowsBaseCallable (
564- ServerStreamingCallSettings .<ReadRowsRequest , Row >newBuilder ()
565- .setRetryableCodes (settings .readRowSettings ().getRetryableCodes ())
566- .setRetrySettings (settings .readRowSettings ().getRetrySettings ())
567- .setIdleTimeout (settings .readRowSettings ().getRetrySettings ().getTotalTimeout ())
568- .build (),
569- rowAdapter );
570-
571- ReadRowsUserCallable <RowT > readRowCallable =
572- new ReadRowsUserCallable <>(readRowsCallable , requestContext );
573-
574- ReadRowsFirstCallable <RowT > firstRow = new ReadRowsFirstCallable <>(readRowCallable );
575-
576- UnaryCallable <Query , RowT > traced =
577- new TracedUnaryCallable <>(
578- firstRow , clientContext .getTracerFactory (), getSpanName ("ReadRow" ));
579-
580- return traced .withDefaultCallContext (clientContext .getDefaultCallContext ());
566+ if (!EnhancedBigtableStubSettings .SKIP_TRAILERS ) {
567+ ServerStreamingCallable <ReadRowsRequest , RowT > readRowsCallable =
568+ createReadRowsBaseCallable (
569+ ServerStreamingCallSettings .<ReadRowsRequest , Row >newBuilder ()
570+ .setRetryableCodes (settings .readRowSettings ().getRetryableCodes ())
571+ .setRetrySettings (settings .readRowSettings ().getRetrySettings ())
572+ .setIdleTimeout (settings .readRowSettings ().getRetrySettings ().getTotalTimeout ())
573+ .build (),
574+ rowAdapter );
575+
576+ ReadRowsUserCallable <RowT > readRowCallable =
577+ new ReadRowsUserCallable <>(readRowsCallable , requestContext );
578+ ReadRowsFirstCallable <RowT > firstRow = new ReadRowsFirstCallable <>(readRowCallable );
579+ UnaryCallable <Query , RowT > traced =
580+ new TracedUnaryCallable <>(
581+ firstRow , clientContext .getTracerFactory (), getSpanName ("ReadRow" ));
582+ return traced .withDefaultCallContext (clientContext .getDefaultCallContext ());
583+ } else {
584+ ServerStreamingCallable <ReadRowsRequest , RowT > readRowsCallable =
585+ createReadRowsBaseCallable (
586+ ServerStreamingCallSettings .<ReadRowsRequest , Row >newBuilder ()
587+ .setRetryableCodes (settings .readRowSettings ().getRetryableCodes ())
588+ .setRetrySettings (settings .readRowSettings ().getRetrySettings ())
589+ .setIdleTimeoutDuration (Duration .ZERO )
590+ .setWaitTimeoutDuration (Duration .ZERO )
591+ .build (),
592+ rowAdapter ,
593+ new SimpleStreamResumptionStrategy <>());
594+ ServerStreamingCallable <Query , RowT > readRowCallable =
595+ new TransformingServerStreamingCallable <>(
596+ readRowsCallable ,
597+ (query ) -> query .limit (1 ).toProto (requestContext ),
598+ Functions .identity ());
599+
600+ return new BigtableUnaryOperationCallable <>(
601+ readRowCallable ,
602+ clientContext .getDefaultCallContext (),
603+ clientContext .getTracerFactory (),
604+ getSpanName ("ReadRow" ),
605+ /*allowNoResponses=*/ true );
606+ }
581607 }
582608
609+ private <ReqT , RowT > ServerStreamingCallable <ReadRowsRequest , RowT > createReadRowsBaseCallable (
610+ ServerStreamingCallSettings <ReqT , Row > readRowsSettings , RowAdapter <RowT > rowAdapter ) {
611+ return createReadRowsBaseCallable (
612+ readRowsSettings , rowAdapter , new ReadRowsResumptionStrategy <RowT >(rowAdapter ));
613+ }
583614 /**
584615 * Creates a callable chain to handle ReadRows RPCs. The chain will:
585616 *
@@ -596,8 +627,9 @@ public <RowT> UnaryCallable<Query, RowT> createReadRowCallable(RowAdapter<RowT>
596627 * <p>NOTE: the caller is responsible for adding tracing & metrics.
597628 */
598629 private <ReqT , RowT > ServerStreamingCallable <ReadRowsRequest , RowT > createReadRowsBaseCallable (
599- ServerStreamingCallSettings <ReqT , Row > readRowsSettings , RowAdapter <RowT > rowAdapter ) {
600-
630+ ServerStreamingCallSettings <ReqT , Row > readRowsSettings ,
631+ RowAdapter <RowT > rowAdapter ,
632+ StreamResumptionStrategy <ReadRowsRequest , RowT > resumptionStrategy ) {
601633 ServerStreamingCallable <ReadRowsRequest , ReadRowsResponse > base =
602634 GrpcRawCallableFactory .createServerStreamingCallable (
603635 GrpcCallSettings .<ReadRowsRequest , ReadRowsResponse >newBuilder ()
@@ -625,7 +657,7 @@ private <ReqT, RowT> ServerStreamingCallable<ReadRowsRequest, RowT> createReadRo
625657 // ReadRowsRequest -> ReadRowsResponse callable).
626658 ServerStreamingCallSettings <ReadRowsRequest , RowT > innerSettings =
627659 ServerStreamingCallSettings .<ReadRowsRequest , RowT >newBuilder ()
628- .setResumptionStrategy (new ReadRowsResumptionStrategy <>( rowAdapter ) )
660+ .setResumptionStrategy (resumptionStrategy )
629661 .setRetryableCodes (readRowsSettings .getRetryableCodes ())
630662 .setRetrySettings (readRowsSettings .getRetrySettings ())
631663 .setIdleTimeout (readRowsSettings .getIdleTimeout ())
@@ -1264,6 +1296,21 @@ private <BaseReqT, BaseRespT, ReqT, RespT> UnaryCallable<ReqT, RespT> createUnar
12641296 UnaryCallSettings <ReqT , RespT > callSettings ,
12651297 Function <ReqT , BaseReqT > requestTransformer ,
12661298 Function <BaseRespT , RespT > responseTranformer ) {
1299+ if (EnhancedBigtableStubSettings .SKIP_TRAILERS ) {
1300+ return createUnaryCallableNew (
1301+ methodDescriptor , headerParamsFn , callSettings , requestTransformer , responseTranformer );
1302+ } else {
1303+ return createUnaryCallableOld (
1304+ methodDescriptor , headerParamsFn , callSettings , requestTransformer , responseTranformer );
1305+ }
1306+ }
1307+
1308+ private <BaseReqT , BaseRespT , ReqT , RespT > UnaryCallable <ReqT , RespT > createUnaryCallableOld (
1309+ MethodDescriptor <BaseReqT , BaseRespT > methodDescriptor ,
1310+ RequestParamsExtractor <BaseReqT > headerParamsFn ,
1311+ UnaryCallSettings <ReqT , RespT > callSettings ,
1312+ Function <ReqT , BaseReqT > requestTransformer ,
1313+ Function <BaseRespT , RespT > responseTranformer ) {
12671314
12681315 UnaryCallable <BaseReqT , BaseRespT > base =
12691316 GrpcRawCallableFactory .createUnaryCallable (
@@ -1300,6 +1347,50 @@ public ApiFuture<RespT> futureCall(ReqT reqT, ApiCallContext apiCallContext) {
13001347 return traced .withDefaultCallContext (clientContext .getDefaultCallContext ());
13011348 }
13021349
1350+ private <BaseReqT , BaseRespT , ReqT , RespT > UnaryCallable <ReqT , RespT > createUnaryCallableNew (
1351+ MethodDescriptor <BaseReqT , BaseRespT > methodDescriptor ,
1352+ RequestParamsExtractor <BaseReqT > headerParamsFn ,
1353+ UnaryCallSettings <ReqT , RespT > callSettings ,
1354+ Function <ReqT , BaseReqT > requestTransformer ,
1355+ Function <BaseRespT , RespT > responseTranformer ) {
1356+
1357+ ServerStreamingCallable <BaseReqT , BaseRespT > base =
1358+ GrpcRawCallableFactory .createServerStreamingCallable (
1359+ GrpcCallSettings .<BaseReqT , BaseRespT >newBuilder ()
1360+ .setMethodDescriptor (methodDescriptor )
1361+ .setParamsExtractor (headerParamsFn )
1362+ .build (),
1363+ callSettings .getRetryableCodes ());
1364+
1365+ base = new StatsHeadersServerStreamingCallable <>(base );
1366+
1367+ base = new BigtableTracerStreamingCallable <>(base );
1368+
1369+ base = withRetries (base , convertUnaryToServerStreamingSettings (callSettings ));
1370+
1371+ ServerStreamingCallable <ReqT , RespT > transformed =
1372+ new TransformingServerStreamingCallable <>(base , requestTransformer , responseTranformer );
1373+
1374+ return new BigtableUnaryOperationCallable <>(
1375+ transformed ,
1376+ clientContext .getDefaultCallContext (),
1377+ clientContext .getTracerFactory (),
1378+ getSpanName (methodDescriptor .getBareMethodName ()),
1379+ /* allowNoResponse= */ false );
1380+ }
1381+
1382+ private static <ReqT , RespT >
1383+ ServerStreamingCallSettings <ReqT , RespT > convertUnaryToServerStreamingSettings (
1384+ UnaryCallSettings <?, ?> unarySettings ) {
1385+ return ServerStreamingCallSettings .<ReqT , RespT >newBuilder ()
1386+ .setResumptionStrategy (new SimpleStreamResumptionStrategy <>())
1387+ .setRetryableCodes (unarySettings .getRetryableCodes ())
1388+ .setRetrySettings (unarySettings .getRetrySettings ())
1389+ .setIdleTimeoutDuration (Duration .ZERO )
1390+ .setWaitTimeoutDuration (Duration .ZERO )
1391+ .build ();
1392+ }
1393+
13031394 private UnaryCallable <PingAndWarmRequest , PingAndWarmResponse > createPingAndWarmCallable () {
13041395 UnaryCallable <PingAndWarmRequest , PingAndWarmResponse > pingAndWarm =
13051396 GrpcRawCallableFactory .createUnaryCallable (
0 commit comments