Skip to content

Commit

Permalink
[ggj][codegen] feat: add LRO to ServiceStubSettings.Builder.initDefau…
Browse files Browse the repository at this point in the history
…lts (#240)

* feat: add factory var decl in ServiceStubSettings codegen

* fix: prevent duplicate MethodDefinition annotations

* feat: add descriptor fields to ServiceStubSettings codegen

* feat: add starter Builder to ServiceStubSettings codegen

* feat: add settings.builder decls to ServiceStubSettings codegen

* feat: add first nested ctors to ServiceStubSettings codegen

* feat: add GapicServiceConfig DS and processing

* feat: integrate GapicServiceConfig into GapicContext, Parser, Composer

* feat: initial param block, RetrySettingsComposer, test

* fix!: refactor GapicRetrySettings

* fix: recognize 1. or .1 double patterns

* feat: support BlockStatement in ClassDef stmts

* feat: add params block to ServiceStubSettings codegen

* feat: add codes def to ServiceStubSettings codegen

* feat: add initDefaults() to ServiceStubSettings codegen

* feat: add LRO to ServiceStubSettings.Builder.initDefaults
  • Loading branch information
miraleung authored Aug 29, 2020
1 parent 99f354d commit 15da1d0
Show file tree
Hide file tree
Showing 4 changed files with 350 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@

package com.google.api.generator.gapic.composer;

import com.google.api.gax.grpc.ProtoOperationTransformers;
import com.google.api.gax.longrunning.OperationSnapshot;
import com.google.api.gax.longrunning.OperationTimedPollAlgorithm;
import com.google.api.gax.retrying.RetrySettings;
import com.google.api.gax.rpc.StatusCode;
import com.google.api.gax.rpc.UnaryCallSettings;
import com.google.api.generator.engine.ast.AssignmentExpr;
import com.google.api.generator.engine.ast.BlockStatement;
import com.google.api.generator.engine.ast.ConcreteReference;
Expand Down Expand Up @@ -56,10 +60,12 @@ public class RetrySettingsComposer {
TypeNode.withReference(ConcreteReference.withClazz(StatusCode.Code.class));

// TODO(miraleung): Determine defaults here.
private static final long LRO_DEFAULT_INITIAL_POLL_DELAY_MILLIS = 9999;
private static final long LRO_DEFAULT_POLL_DELAY_MULTIPLIER = 1;
private static final long LRO_DEFAULT_MAX_POLL_DELAY_MILLIS = 8888;
private static final long LRO_DEFAULT_TOTAL_POLL_TIMEOUT_MILLIS = 7777;
// Default values for LongRunningConfig fields.
private static final long LRO_DEFAULT_INITIAL_POLL_DELAY_MILLIS = 500;
private static final double LRO_DEFAULT_POLL_DELAY_MULTIPLIER = 1.5;
private static final long LRO_DEFAULT_MAX_POLL_DELAY_MILLIS = 5000;
private static final long LRO_DEFAULT_TOTAL_POLL_TIMEOUT_MILLS = 300000;
private static final double LRO_DEFAULT_MAX_RPC_TIMEOUT = 1.0;

public static BlockStatement createRetryParamDefinitionsBlock(
Service service,
Expand Down Expand Up @@ -231,6 +237,134 @@ public static Expr createSimpleBuilderSettingsExpr(
return builderSettingsExpr;
}

public static Expr createLroSettingsBuilderExpr(
Service service,
GapicServiceConfig serviceConfig,
Method method,
VariableExpr builderVarExpr,
VariableExpr retryableCodeDefsVarExpr,
VariableExpr retryParamDefsVarExpr) {
Preconditions.checkState(
method.hasLro(),
String.format(
"Tried to create LRO settings initialization for non-LRO method %s", method.name()));

String codeName = serviceConfig.getRetryCodeName(service, method);
String retryParamName = serviceConfig.getRetryParamsName(service, method);
String settingsGetterMethodName =
String.format("%sOperationSettings", JavaStyle.toLowerCamelCase(method.name()));

Function<String, ValueExpr> strValExprFn =
s -> ValueExpr.withValue(StringObjectValue.withValue(s));

// Argument for setInitialCallSettings.
Expr unaryCallSettingsExpr =
MethodInvocationExpr.builder()
.setStaticReferenceType(STATIC_TYPES.get("UnaryCallSettings"))
.setGenerics(
Arrays.asList(
method.inputType().reference(),
STATIC_TYPES.get("OperationSnapshot").reference()))
.setMethodName("newUnaryCallSettingsBuilder")
.build();
unaryCallSettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(unaryCallSettingsExpr)
.setMethodName("setRetryableCodes")
.setArguments(
MethodInvocationExpr.builder()
.setExprReferenceExpr(retryableCodeDefsVarExpr)
.setMethodName("get")
.setArguments(strValExprFn.apply(codeName))
.build())
.build();
unaryCallSettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(unaryCallSettingsExpr)
.setMethodName("setRetrySettings")
.setArguments(
MethodInvocationExpr.builder()
.setExprReferenceExpr(retryParamDefsVarExpr)
.setMethodName("get")
.setArguments(strValExprFn.apply(retryParamName))
.build())
.build();
unaryCallSettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(unaryCallSettingsExpr)
.setMethodName("build")
.build();

Expr builderSettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(builderVarExpr)
.setMethodName(settingsGetterMethodName)
.build();
builderSettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(builderSettingsExpr)
.setMethodName("setInitialCallSettings")
.setArguments(unaryCallSettingsExpr)
.build();

Function<TypeNode, VariableExpr> classFieldRefFn =
t ->
VariableExpr.builder()
.setVariable(
Variable.builder()
.setType(TypeNode.withReference(ConcreteReference.withClazz(Class.class)))
.setName("class")
.build())
.setStaticReferenceType(t)
.build();
builderSettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(builderSettingsExpr)
.setMethodName("setResponseTransformer")
.setArguments(
MethodInvocationExpr.builder()
.setStaticReferenceType(
TypeNode.withReference(
ConcreteReference.withClazz(
ProtoOperationTransformers.ResponseTransformer.class)))
.setMethodName("create")
.setArguments(classFieldRefFn.apply(method.lro().responseType()))
.build())
.build();
builderSettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(builderSettingsExpr)
.setMethodName("setMetadataTransformer")
.setArguments(
MethodInvocationExpr.builder()
.setStaticReferenceType(
TypeNode.withReference(
ConcreteReference.withClazz(
ProtoOperationTransformers.MetadataTransformer.class)))
.setMethodName("create")
.setArguments(classFieldRefFn.apply(method.lro().metadataType()))
.build())
.build();

// TODO(miraleung): Determine fianl LRO settings values here.
Expr lroRetrySettingsExpr = createLroRetrySettingsExpr();
Expr pollAlgoExpr =
MethodInvocationExpr.builder()
.setStaticReferenceType(STATIC_TYPES.get("OperationTimedPollAlgorithm"))
.setMethodName("create")
.setArguments(lroRetrySettingsExpr)
.build();

builderSettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(builderSettingsExpr)
.setMethodName("setPollingAlgorithm")
.setArguments(pollAlgoExpr)
.build();

return builderSettingsExpr;
}

private static Expr createRetryCodeDefinitionExpr(
String codeName, List<Code> retryCodes, VariableExpr definitionsVarExpr) {
// Construct something like `definitions.put("code_name",
Expand Down Expand Up @@ -264,28 +398,6 @@ private static List<Expr> createRetrySettingsExprs(
GapicRetrySettings settings,
VariableExpr settingsVarExpr,
VariableExpr definitionsVarExpr) {
Function<Duration, ValueExpr> durationToMillisValExprFn =
d ->
ValueExpr.withValue(
PrimitiveValue.builder()
.setType(TypeNode.LONG)
.setValue(String.format("%dL", Durations.toMillis(d)))
.build());
Function<Float, ValueExpr> floatToValExprFn =
f ->
ValueExpr.withValue(
PrimitiveValue.builder()
.setType(TypeNode.DOUBLE)
.setValue(String.format("%.1f", f))
.build());
Function<ValueExpr, MethodInvocationExpr> durationMillisMethodFn =
v ->
MethodInvocationExpr.builder()
.setStaticReferenceType(STATIC_TYPES.get("Duration"))
.setMethodName("ofMillis")
.setArguments(v)
.build();

Expr settingsBuilderExpr =
MethodInvocationExpr.builder()
.setStaticReferenceType(STATIC_TYPES.get("RetrySettings"))
Expand All @@ -301,16 +413,14 @@ private static List<Expr> createRetrySettingsExprs(
MethodInvocationExpr.builder()
.setExprReferenceExpr(settingsBuilderExpr)
.setMethodName("setInitialRetryDelay")
.setArguments(
durationMillisMethodFn.apply(
durationToMillisValExprFn.apply(retryPolicy.getInitialBackoff())))
.setArguments(createDurationOfMillisExpr(toValExpr(retryPolicy.getInitialBackoff())))
.build();

settingsBuilderExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(settingsBuilderExpr)
.setMethodName("setRetryDelayMultiplier")
.setArguments(floatToValExprFn.apply(retryPolicy.getBackoffMultiplier()))
.setArguments(toValExpr(retryPolicy.getBackoffMultiplier()))
.build();

Preconditions.checkState(
Expand All @@ -320,9 +430,7 @@ private static List<Expr> createRetrySettingsExprs(
MethodInvocationExpr.builder()
.setExprReferenceExpr(settingsBuilderExpr)
.setMethodName("setMaxRetryDelay")
.setArguments(
durationMillisMethodFn.apply(
durationToMillisValExprFn.apply(retryPolicy.getMaxBackoff())))
.setArguments(createDurationOfMillisExpr(toValExpr(retryPolicy.getMaxBackoff())))
.build();
}

Expand All @@ -331,8 +439,7 @@ private static List<Expr> createRetrySettingsExprs(
MethodInvocationExpr.builder()
.setExprReferenceExpr(settingsBuilderExpr)
.setMethodName("setInitialRpcTimeout")
.setArguments(
durationMillisMethodFn.apply(durationToMillisValExprFn.apply(settings.timeout())))
.setArguments(createDurationOfMillisExpr(toValExpr(settings.timeout())))
.build();
}

Expand All @@ -352,9 +459,7 @@ private static List<Expr> createRetrySettingsExprs(
MethodInvocationExpr.builder()
.setExprReferenceExpr(settingsBuilderExpr)
.setMethodName(setterMethodName)
.setArguments(
durationMillisMethodFn.apply(
durationToMillisValExprFn.apply(settings.timeout())))
.setArguments(createDurationOfMillisExpr(toValExpr(settings.timeout())))
.build();
}
}
Expand Down Expand Up @@ -383,19 +488,129 @@ private static List<Expr> createRetrySettingsExprs(
return Arrays.asList(settingsAssignExpr, definitionsPutExpr);
}

private static Expr createLroRetrySettingsExpr() {
// TODO(miraleung): Determine fianl LRO settings values here.
Expr lroRetrySettingsExpr =
MethodInvocationExpr.builder()
.setStaticReferenceType(STATIC_TYPES.get("RetrySettings"))
.setMethodName("newBuilder")
.build();

lroRetrySettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(lroRetrySettingsExpr)
.setMethodName("setInitialRetryDelay")
.setArguments(
createDurationOfMillisExpr(toValExpr(LRO_DEFAULT_INITIAL_POLL_DELAY_MILLIS)))
.build();

lroRetrySettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(lroRetrySettingsExpr)
.setMethodName("setRetryDelayMultiplier")
.setArguments(toValExpr(LRO_DEFAULT_POLL_DELAY_MULTIPLIER))
.build();

lroRetrySettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(lroRetrySettingsExpr)
.setMethodName("setMaxRetryDelay")
.setArguments(createDurationOfMillisExpr(toValExpr(LRO_DEFAULT_MAX_POLL_DELAY_MILLIS)))
.build();

Expr zeroDurationExpr =
EnumRefExpr.builder().setType(STATIC_TYPES.get("Duration")).setName("ZERO").build();
// TODO(miraleung): Find a way to add an "// ignored" comment here.
lroRetrySettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(lroRetrySettingsExpr)
.setMethodName("setInitialRpcTimeout")
.setArguments(zeroDurationExpr)
.build();

// TODO(miraleung): Find a way to add an "// ignored" comment here.
lroRetrySettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(lroRetrySettingsExpr)
.setMethodName("setRpcTimeoutMultiplier")
.setArguments(toValExpr(LRO_DEFAULT_MAX_RPC_TIMEOUT))
.build();

// TODO(miraleung): Find a way to add an "// ignored" comment here.
lroRetrySettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(lroRetrySettingsExpr)
.setMethodName("setMaxRpcTimeout")
.setArguments(zeroDurationExpr)
.build();

lroRetrySettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(lroRetrySettingsExpr)
.setMethodName("setTotalTimeout")
.setArguments(
createDurationOfMillisExpr(toValExpr(LRO_DEFAULT_TOTAL_POLL_TIMEOUT_MILLS)))
.build();

lroRetrySettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(lroRetrySettingsExpr)
.setMethodName("build")
.build();

return lroRetrySettingsExpr;
}

private static EnumRefExpr toStatusCodeEnumRefExpr(Code code) {
return EnumRefExpr.builder().setType(STATUS_CODE_CODE_TYPE).setName(code.name()).build();
}

private static ValueExpr toValExpr(long longValue) {
return ValueExpr.withValue(
PrimitiveValue.builder()
.setType(TypeNode.LONG)
.setValue(String.format("%dL", longValue))
.build());
}

private static ValueExpr toValExpr(float floatValue) {
return toValExpr((double) floatValue);
}

private static ValueExpr toValExpr(double val) {
return ValueExpr.withValue(
PrimitiveValue.builder()
.setType(TypeNode.DOUBLE)
.setValue(String.format("%.1f", val))
.build());
}

private static ValueExpr toValExpr(Duration duration) {
return toValExpr(Durations.toMillis(duration));
}

private static MethodInvocationExpr createDurationOfMillisExpr(ValueExpr valExpr) {
return MethodInvocationExpr.builder()
.setStaticReferenceType(STATIC_TYPES.get("Duration"))
.setMethodName("ofMillis")
.setArguments(valExpr)
.build();
}

private static Map<String, TypeNode> createStaticTypes() {
List<Class> concreteClazzes =
Arrays.asList(
org.threeten.bp.Duration.class,
ImmutableMap.class,
ImmutableSet.class,
Lists.class,
OperationSnapshot.class,
OperationTimedPollAlgorithm.class,
ProtoOperationTransformers.class,
RetrySettings.class,
StatusCode.class);
StatusCode.class,
UnaryCallSettings.class);

return concreteClazzes.stream()
.collect(
Collectors.toMap(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,19 @@ private static MethodDefinition createNestedClassInitDefaultsMethod(
NESTED_RETRYABLE_CODE_DEFINITIONS_VAR_EXPR,
NESTED_RETRY_PARAM_DEFINITIONS_VAR_EXPR));
}
for (Method method : service.methods()) {
if (!method.hasLro()) {
continue;
}
bodyExprs.add(
RetrySettingsComposer.createLroSettingsBuilderExpr(
service,
serviceConfig,
method,
builderVarExpr,
NESTED_RETRYABLE_CODE_DEFINITIONS_VAR_EXPR,
NESTED_RETRY_PARAM_DEFINITIONS_VAR_EXPR));
}

return MethodDefinition.builder()
.setScope(ScopeNode.PRIVATE)
Expand Down
Loading

0 comments on commit 15da1d0

Please sign in to comment.