Skip to content

Commit

Permalink
[ggj][codegen] feat: add initDefaults() to ServiceStubSettings (#239)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
miraleung authored Aug 29, 2020
1 parent 9204030 commit 99f354d
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
import com.google.api.generator.engine.ast.VariableExpr;
import com.google.api.generator.gapic.model.GapicRetrySettings;
import com.google.api.generator.gapic.model.GapicServiceConfig;
import com.google.api.generator.gapic.model.Method;
import com.google.api.generator.gapic.model.Service;
import com.google.api.generator.gapic.utils.JavaStyle;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
Expand All @@ -53,6 +55,12 @@ public class RetrySettingsComposer {
private static final TypeNode STATUS_CODE_CODE_TYPE =
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;

public static BlockStatement createRetryParamDefinitionsBlock(
Service service,
GapicServiceConfig serviceConfig,
Expand Down Expand Up @@ -177,6 +185,52 @@ public static BlockStatement createRetryCodesDefinitionsBlock(
.build();
}

public static Expr createSimpleBuilderSettingsExpr(
Service service,
GapicServiceConfig serviceConfig,
Method method,
VariableExpr builderVarExpr,
VariableExpr retryableCodeDefsVarExpr,
VariableExpr retryParamDefsVarExpr) {
String codeName = serviceConfig.getRetryCodeName(service, method);
String retryParamName = serviceConfig.getRetryParamsName(service, method);
String settingsGetterMethodName =
String.format("%sSettings", JavaStyle.toLowerCamelCase(method.name()));

Expr builderSettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(builderVarExpr)
.setMethodName(settingsGetterMethodName)
.build();

Function<String, ValueExpr> strValExprFn =
s -> ValueExpr.withValue(StringObjectValue.withValue(s));
builderSettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(builderSettingsExpr)
.setMethodName("setRetryableCodes")
.setArguments(
MethodInvocationExpr.builder()
.setExprReferenceExpr(retryableCodeDefsVarExpr)
.setMethodName("get")
.setArguments(strValExprFn.apply(codeName))
.build())
.build();
builderSettingsExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(builderSettingsExpr)
.setMethodName("setRetrySettings")
.setArguments(
MethodInvocationExpr.builder()
.setExprReferenceExpr(retryParamDefsVarExpr)
.setMethodName("get")
.setArguments(strValExprFn.apply(retryParamName))
.build())
.build();

return builderSettingsExpr;
}

private static Expr createRetryCodeDefinitionExpr(
String codeName, List<Code> retryCodes, VariableExpr definitionsVarExpr) {
// Construct something like `definitions.put("code_name",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,9 @@ private static ClassDefinition createNestedBuilderClass(
.setExtendsType(extendsType)
.setStatements(
createNestedClassStatements(service, serviceConfig, nestedMethodSettingsMemberVarExprs))
.setMethods(createNestedClassMethods(nestedMethodSettingsMemberVarExprs, types))
.setMethods(
createNestedClassMethods(
service, serviceConfig, nestedMethodSettingsMemberVarExprs, types))
.build();
}

Expand Down Expand Up @@ -1155,15 +1157,55 @@ private static List<Statement> createNestedClassStatements(
}

private static List<MethodDefinition> createNestedClassMethods(
Map<String, VariableExpr> nestedMethodSettingsMemberVarExprs, Map<String, TypeNode> types) {
Service service,
GapicServiceConfig serviceConfig,
Map<String, VariableExpr> nestedMethodSettingsMemberVarExprs,
Map<String, TypeNode> types) {
List<MethodDefinition> nestedClassMethods = new ArrayList<>();
nestedClassMethods.addAll(
createNestedClassConstructorMethods(nestedMethodSettingsMemberVarExprs, types));
nestedClassMethods.add(createNestedClassInitDefaultsMethod(service, serviceConfig, types));

// TODO(miraleung): initDefaults().
// TODO(miraleung): More methods.
return nestedClassMethods;
}

private static MethodDefinition createNestedClassInitDefaultsMethod(
Service service, GapicServiceConfig serviceConfig, Map<String, TypeNode> types) {
TypeNode builderType = types.get(NESTED_BUILDER_CLASS_NAME);
VariableExpr builderVarExpr =
VariableExpr.withVariable(
Variable.builder().setType(builderType).setName("builder").build());

List<Expr> bodyExprs = new ArrayList<>();
// Iterate through methods twice to so we can have LRO expressions appear last.
for (Method method : service.methods()) {
Method.Stream streamKind = method.stream();
if (streamKind.equals(Method.Stream.CLIENT) || streamKind.equals(Method.Stream.BIDI)) {
continue;
}
bodyExprs.add(
RetrySettingsComposer.createSimpleBuilderSettingsExpr(
service,
serviceConfig,
method,
builderVarExpr,
NESTED_RETRYABLE_CODE_DEFINITIONS_VAR_EXPR,
NESTED_RETRY_PARAM_DEFINITIONS_VAR_EXPR));
}

return MethodDefinition.builder()
.setScope(ScopeNode.PRIVATE)
.setIsStatic(true)
.setReturnType(builderType)
.setName("initDefaults")
.setArguments(builderVarExpr.toBuilder().setIsDecl(true).build())
.setBody(
bodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList()))
.setReturnExpr(builderVarExpr)
.build();
}

private static List<MethodDefinition> createNestedClassConstructorMethods(
Map<String, VariableExpr> nestedMethodSettingsMemberVarExprs, Map<String, TypeNode> types) {
TypeNode builderType = types.get(NESTED_BUILDER_CLASS_NAME);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,22 @@

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

import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;

import com.google.api.gax.rpc.StatusCode;
import com.google.api.generator.engine.ast.BlockStatement;
import com.google.api.generator.engine.ast.ConcreteReference;
import com.google.api.generator.engine.ast.Expr;
import com.google.api.generator.engine.ast.TypeNode;
import com.google.api.generator.engine.ast.VaporReference;
import com.google.api.generator.engine.ast.Variable;
import com.google.api.generator.engine.ast.VariableExpr;
import com.google.api.generator.engine.writer.JavaWriterVisitor;
import com.google.api.generator.gapic.model.GapicServiceConfig;
import com.google.api.generator.gapic.model.Message;
import com.google.api.generator.gapic.model.Method;
import com.google.api.generator.gapic.model.ResourceName;
import com.google.api.generator.gapic.model.Service;
import com.google.api.generator.gapic.protoparser.Parser;
Expand Down Expand Up @@ -214,6 +217,107 @@ public void codesDefinitionsBlock_basic() {
assertEquals(expected, writerVisitor.write());
}

@Test
public void simplerBuilderExpr_basic() {
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
ServiceDescriptor echoServiceDescriptor = echoFileDescriptor.getServices().get(0);
Map<String, Message> messageTypes = Parser.parseMessages(echoFileDescriptor);
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
Set<ResourceName> outputResourceNames = new HashSet<>();
List<Service> services =
Parser.parseService(echoFileDescriptor, messageTypes, resourceNames, outputResourceNames);
assertEquals(1, services.size());

Service service = services.get(0);

String jsonFilename = "showcase_grpc_service_config.json";
Path jsonPath = Paths.get(JSON_DIRECTORY, jsonFilename);
Optional<GapicServiceConfig> serviceConfigOpt = ServiceConfigParser.parse(jsonPath.toString());
assertTrue(serviceConfigOpt.isPresent());
GapicServiceConfig serviceConfig = serviceConfigOpt.get();

// Regular method.
Method echoMethod = findMethod(service, "Echo");
assertThat(echoMethod).isNotNull();

VariableExpr builderVarExpr = createBuilderVarExpr(service);
Expr builderExpr =
RetrySettingsComposer.createSimpleBuilderSettingsExpr(
service,
serviceConfig,
echoMethod,
builderVarExpr,
RETRY_CODES_DEFINITIONS_VAR_EXPR,
RETRY_PARAM_DEFINITIONS_VAR_EXPR);
builderExpr.accept(writerVisitor);
String expected =
createLines(
"builder.echoSettings()"
+ ".setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get(\"retry_policy_1_codes\"))"
+ ".setRetrySettings(RETRY_PARAM_DEFINITIONS.get(\"retry_policy_1_params\"))");
assertEquals(expected, writerVisitor.write());

// Server-streaming method.
Method expandMethod = findMethod(service, "Expand");
assertThat(expandMethod).isNotNull();
builderExpr =
RetrySettingsComposer.createSimpleBuilderSettingsExpr(
service,
serviceConfig,
expandMethod,
builderVarExpr,
RETRY_CODES_DEFINITIONS_VAR_EXPR,
RETRY_PARAM_DEFINITIONS_VAR_EXPR);
writerVisitor.clear();
builderExpr.accept(writerVisitor);
expected =
createLines(
"builder.expandSettings()"
+ ".setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get(\"retry_policy_1_codes\"))"
+ ".setRetrySettings(RETRY_PARAM_DEFINITIONS.get(\"retry_policy_1_params\"))");
assertEquals(expected, writerVisitor.write());

// LRO method.
Method waitMethod = findMethod(service, "Wait");
assertThat(waitMethod).isNotNull();
builderExpr =
RetrySettingsComposer.createSimpleBuilderSettingsExpr(
service,
serviceConfig,
waitMethod,
builderVarExpr,
RETRY_CODES_DEFINITIONS_VAR_EXPR,
RETRY_PARAM_DEFINITIONS_VAR_EXPR);
writerVisitor.clear();
builderExpr.accept(writerVisitor);
expected =
createLines(
"builder.waitSettings()"
+ ".setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get(\"no_retry_0_codes\"))"
+ ".setRetrySettings(RETRY_PARAM_DEFINITIONS.get(\"no_retry_0_params\"))");
assertEquals(expected, writerVisitor.write());
}

private static Method findMethod(Service service, String methodName) {
for (Method m : service.methods()) {
if (m.name().equals(methodName)) {
return m;
}
}
return null;
}

private static VariableExpr createBuilderVarExpr(Service service) {
TypeNode builderType =
TypeNode.withReference(
VaporReference.builder()
.setPakkage(String.format("%s.stub", service.pakkage()))
.setName("Builder")
.build());
return VariableExpr.withVariable(
Variable.builder().setType(builderType).setName("builder").build());
}

private static VariableExpr createRetryableCodesDefinitionsVarExpr() {
TypeNode immutableSetType =
TypeNode.withReference(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,36 @@ public void generateServiceClasses() {
+ " echoSettings, pagedExpandSettings, waitSettings, blockSettings);\n"
+ " initDefaults(this);\n"
+ " }\n"
+ "\n"
+ " private static Builder initDefaults(Builder builder) {\n"
+ " builder\n"
+ " .echoSettings()\n"
+ " "
+ " .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get(\"retry_policy_1_codes\"))\n"
+ " "
+ " .setRetrySettings(RETRY_PARAM_DEFINITIONS.get(\"retry_policy_1_params\"));\n"
+ " builder\n"
+ " .expandSettings()\n"
+ " "
+ " .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get(\"retry_policy_1_codes\"))\n"
+ " "
+ " .setRetrySettings(RETRY_PARAM_DEFINITIONS.get(\"retry_policy_1_params\"));\n"
+ " builder\n"
+ " .pagedExpandSettings()\n"
+ " "
+ " .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get(\"retry_policy_1_codes\"))\n"
+ " "
+ " .setRetrySettings(RETRY_PARAM_DEFINITIONS.get(\"retry_policy_1_params\"));\n"
+ " builder\n"
+ " .waitSettings()\n"
+ " .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get(\"no_retry_0_codes\"))\n"
+ " .setRetrySettings(RETRY_PARAM_DEFINITIONS.get(\"no_retry_0_params\"));\n"
+ " builder\n"
+ " .blockSettings()\n"
+ " .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get(\"no_retry_0_codes\"))\n"
+ " .setRetrySettings(RETRY_PARAM_DEFINITIONS.get(\"no_retry_0_params\"));\n"
+ " return builder;\n"
+ " }\n"
+ " }\n"
+ "}\n";
}

0 comments on commit 99f354d

Please sign in to comment.