Skip to content
This repository was archived by the owner on May 14, 2026. It is now read-only.

Commit 9204030

Browse files
authored
[ggj][codegen] feat: add codes def to ServiceStubSettings (#238)
* 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
1 parent f59e1e9 commit 9204030

6 files changed

Lines changed: 224 additions & 2 deletions

File tree

src/main/java/com/google/api/generator/gapic/composer/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ java_library(
1313
deps = [
1414
"//:longrunning_java_proto",
1515
"//:monitored_resource_java_proto",
16+
"//:rpc_java_proto",
1617
"//:service_config_java_proto",
1718
"//src/main/java/com/google/api/generator/engine/ast",
1819
"//src/main/java/com/google/api/generator/gapic:status_java_proto",

src/main/java/com/google/api/generator/gapic/composer/RetrySettingsComposer.java

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
package com.google.api.generator.gapic.composer;
1616

1717
import com.google.api.gax.retrying.RetrySettings;
18+
import com.google.api.gax.rpc.StatusCode;
1819
import com.google.api.generator.engine.ast.AssignmentExpr;
1920
import com.google.api.generator.engine.ast.BlockStatement;
2021
import com.google.api.generator.engine.ast.ConcreteReference;
22+
import com.google.api.generator.engine.ast.EnumRefExpr;
2123
import com.google.api.generator.engine.ast.Expr;
2224
import com.google.api.generator.engine.ast.ExprStatement;
2325
import com.google.api.generator.engine.ast.MethodInvocationExpr;
@@ -33,8 +35,11 @@
3335
import com.google.api.generator.gapic.model.Service;
3436
import com.google.common.base.Preconditions;
3537
import com.google.common.collect.ImmutableMap;
38+
import com.google.common.collect.ImmutableSet;
39+
import com.google.common.collect.Lists;
3640
import com.google.protobuf.Duration;
3741
import com.google.protobuf.util.Durations;
42+
import com.google.rpc.Code;
3843
import io.grpc.serviceconfig.MethodConfig.RetryPolicy;
3944
import java.util.ArrayList;
4045
import java.util.Arrays;
@@ -45,6 +50,8 @@
4550

4651
public class RetrySettingsComposer {
4752
private static final Map<String, TypeNode> STATIC_TYPES = createStaticTypes();
53+
private static final TypeNode STATUS_CODE_CODE_TYPE =
54+
TypeNode.withReference(ConcreteReference.withClazz(StatusCode.Code.class));
4855

4956
public static BlockStatement createRetryParamDefinitionsBlock(
5057
Service service,
@@ -116,6 +123,88 @@ public static BlockStatement createRetryParamDefinitionsBlock(
116123
.build();
117124
}
118125

126+
public static BlockStatement createRetryCodesDefinitionsBlock(
127+
Service service,
128+
GapicServiceConfig serviceConfig,
129+
VariableExpr retryCodesDefinitionsClassMemberVarExpr) {
130+
TypeNode definitionsType =
131+
TypeNode.withReference(
132+
ConcreteReference.builder()
133+
.setClazz(ImmutableMap.Builder.class)
134+
.setGenerics(retryCodesDefinitionsClassMemberVarExpr.type().reference().generics())
135+
.build());
136+
VariableExpr definitionsVarExpr =
137+
VariableExpr.withVariable(
138+
Variable.builder().setType(definitionsType).setName("definitions").build());
139+
140+
List<Expr> bodyExprs = new ArrayList<>();
141+
// Create the first expr.
142+
bodyExprs.add(
143+
AssignmentExpr.builder()
144+
.setVariableExpr(definitionsVarExpr.toBuilder().setIsDecl(true).build())
145+
.setValueExpr(
146+
MethodInvocationExpr.builder()
147+
.setStaticReferenceType(STATIC_TYPES.get("ImmutableMap"))
148+
.setMethodName("builder")
149+
.setReturnType(definitionsVarExpr.type())
150+
.build())
151+
.build());
152+
153+
for (Map.Entry<String, List<Code>> codeEntry :
154+
serviceConfig.getAllRetryCodes(service).entrySet()) {
155+
bodyExprs.add(
156+
createRetryCodeDefinitionExpr(
157+
codeEntry.getKey(), codeEntry.getValue(), definitionsVarExpr));
158+
}
159+
160+
// Reassign the new codes.
161+
bodyExprs.add(
162+
AssignmentExpr.builder()
163+
.setVariableExpr(retryCodesDefinitionsClassMemberVarExpr)
164+
.setValueExpr(
165+
MethodInvocationExpr.builder()
166+
.setExprReferenceExpr(definitionsVarExpr)
167+
.setMethodName("build")
168+
.setReturnType(retryCodesDefinitionsClassMemberVarExpr.type())
169+
.build())
170+
.build());
171+
172+
// Put everything together.
173+
return BlockStatement.builder()
174+
.setIsStatic(true)
175+
.setBody(
176+
bodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList()))
177+
.build();
178+
}
179+
180+
private static Expr createRetryCodeDefinitionExpr(
181+
String codeName, List<Code> retryCodes, VariableExpr definitionsVarExpr) {
182+
// Construct something like `definitions.put("code_name",
183+
// ImmutableSet.copYOf(Lists.<StatusCode.Code>newArrayList()));`
184+
MethodInvocationExpr codeListExpr =
185+
MethodInvocationExpr.builder()
186+
.setStaticReferenceType(STATIC_TYPES.get("Lists"))
187+
.setGenerics(Arrays.asList(STATUS_CODE_CODE_TYPE.reference()))
188+
.setMethodName("newArrayList")
189+
.setArguments(
190+
retryCodes.stream()
191+
.map(c -> toStatusCodeEnumRefExpr(c))
192+
.collect(Collectors.toList()))
193+
.build();
194+
195+
MethodInvocationExpr codeSetExpr =
196+
MethodInvocationExpr.builder()
197+
.setStaticReferenceType(STATIC_TYPES.get("ImmutableSet"))
198+
.setMethodName("copyOf")
199+
.setArguments(codeListExpr)
200+
.build();
201+
return MethodInvocationExpr.builder()
202+
.setExprReferenceExpr(definitionsVarExpr)
203+
.setMethodName("put")
204+
.setArguments(ValueExpr.withValue(StringObjectValue.withValue(codeName)), codeSetExpr)
205+
.build();
206+
}
207+
119208
private static List<Expr> createRetrySettingsExprs(
120209
String settingsName,
121210
GapicRetrySettings settings,
@@ -240,9 +329,19 @@ private static List<Expr> createRetrySettingsExprs(
240329
return Arrays.asList(settingsAssignExpr, definitionsPutExpr);
241330
}
242331

332+
private static EnumRefExpr toStatusCodeEnumRefExpr(Code code) {
333+
return EnumRefExpr.builder().setType(STATUS_CODE_CODE_TYPE).setName(code.name()).build();
334+
}
335+
243336
private static Map<String, TypeNode> createStaticTypes() {
244337
List<Class> concreteClazzes =
245-
Arrays.asList(org.threeten.bp.Duration.class, ImmutableMap.class, RetrySettings.class);
338+
Arrays.asList(
339+
org.threeten.bp.Duration.class,
340+
ImmutableMap.class,
341+
ImmutableSet.class,
342+
Lists.class,
343+
RetrySettings.class,
344+
StatusCode.class);
246345
return concreteClazzes.stream()
247346
.collect(
248347
Collectors.toMap(

src/main/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposer.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ private static List<Statement> createNestedClassStatements(
11211121
.map(v -> varDeclFn.apply(v))
11221122
.collect(Collectors.toList()));
11231123

1124-
// Declare the RETRYABLE_CODE_DEFNITIONS field.
1124+
// Declare the RETRYABLE_CODE_DEFINITIONS field.
11251125
Function<VariableExpr, VariableExpr> varStaticDeclFn =
11261126
v ->
11271127
v.toBuilder()
@@ -1135,8 +1135,13 @@ private static List<Statement> createNestedClassStatements(
11351135
List<Statement> statements = new ArrayList<>();
11361136
statements.addAll(
11371137
exprs.stream().map(e -> exprStatementFn.apply(e)).collect(Collectors.toList()));
1138+
1139+
// Declare and set the RETRYABLE_CODE_DEFINITIONS field.
11381140
statements.add(
11391141
exprStatementFn.apply((varStaticDeclFn.apply(NESTED_RETRYABLE_CODE_DEFINITIONS_VAR_EXPR))));
1142+
statements.add(
1143+
RetrySettingsComposer.createRetryCodesDefinitionsBlock(
1144+
service, serviceConfig, NESTED_RETRYABLE_CODE_DEFINITIONS_VAR_EXPR));
11401145

11411146
// Declare the RETRY_PARAM_DEFINITIONS field.
11421147
statements.add(

src/test/java/com/google/api/generator/gapic/composer/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ filegroup(
2828
],
2929
test_class = "com.google.api.generator.gapic.composer.{0}".format(test_name),
3030
deps = [
31+
"//:rpc_java_proto",
3132
"//:service_config_java_proto",
3233
"//src/main/java/com/google/api/generator/engine/ast",
3334
"//src/main/java/com/google/api/generator/engine/writer",
3435
"//src/main/java/com/google/api/generator/gapic/composer",
3536
"//src/main/java/com/google/api/generator/gapic/model",
3637
"//src/main/java/com/google/api/generator/gapic/protoparser",
3738
"//src/test/java/com/google/api/generator/gapic/testdata:showcase_java_proto",
39+
"@com_google_api_gax_java//jar",
3840
"@com_google_protobuf//:protobuf_java",
3941
"@com_google_truth_truth//jar",
4042
"@junit_junit//jar",

src/test/java/com/google/api/generator/gapic/composer/RetrySettingsComposerTest.java

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import static junit.framework.Assert.assertEquals;
1818
import static junit.framework.Assert.assertTrue;
1919

20+
import com.google.api.gax.rpc.StatusCode;
2021
import com.google.api.generator.engine.ast.BlockStatement;
2122
import com.google.api.generator.engine.ast.ConcreteReference;
2223
import com.google.api.generator.engine.ast.TypeNode;
@@ -31,6 +32,7 @@
3132
import com.google.api.generator.gapic.protoparser.Parser;
3233
import com.google.api.generator.gapic.protoparser.ServiceConfigParser;
3334
import com.google.common.collect.ImmutableMap;
35+
import com.google.common.collect.ImmutableSet;
3436
import com.google.protobuf.Descriptors.FileDescriptor;
3537
import com.google.protobuf.Descriptors.ServiceDescriptor;
3638
import com.google.showcase.v1beta1.EchoOuterClass;
@@ -51,6 +53,8 @@ public class RetrySettingsComposerTest {
5153
"src/test/java/com/google/api/generator/gapic/testdata/";
5254
private static final VariableExpr RETRY_PARAM_DEFINITIONS_VAR_EXPR =
5355
createRetryParamDefinitionsVarExpr();
56+
private static final VariableExpr RETRY_CODES_DEFINITIONS_VAR_EXPR =
57+
createRetryableCodesDefinitionsVarExpr();
5458

5559
private JavaWriterVisitor writerVisitor;
5660

@@ -135,6 +139,101 @@ public void paramDefinitionsBlock_basic() {
135139
assertEquals(expected, writerVisitor.write());
136140
}
137141

142+
@Test
143+
public void codesDefinitionsBlock_noConfigsFound() {
144+
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
145+
ServiceDescriptor echoServiceDescriptor = echoFileDescriptor.getServices().get(0);
146+
Map<String, Message> messageTypes = Parser.parseMessages(echoFileDescriptor);
147+
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
148+
Set<ResourceName> outputResourceNames = new HashSet<>();
149+
List<Service> services =
150+
Parser.parseService(echoFileDescriptor, messageTypes, resourceNames, outputResourceNames);
151+
assertEquals(1, services.size());
152+
153+
Service service = services.get(0);
154+
155+
String jsonFilename = "retrying_grpc_service_config.json";
156+
Path jsonPath = Paths.get(JSON_DIRECTORY, jsonFilename);
157+
Optional<GapicServiceConfig> serviceConfigOpt = ServiceConfigParser.parse(jsonPath.toString());
158+
assertTrue(serviceConfigOpt.isPresent());
159+
GapicServiceConfig serviceConfig = serviceConfigOpt.get();
160+
161+
BlockStatement paramDefinitionsBlock =
162+
RetrySettingsComposer.createRetryCodesDefinitionsBlock(
163+
service, serviceConfig, RETRY_CODES_DEFINITIONS_VAR_EXPR);
164+
165+
paramDefinitionsBlock.accept(writerVisitor);
166+
String expected =
167+
createLines(
168+
"static {\n",
169+
"ImmutableMap.Builder<String, ImmutableSet<StatusCode.Code>> definitions ="
170+
+ " ImmutableMap.builder();\n",
171+
"definitions.put(\"no_retry_codes\","
172+
+ " ImmutableSet.copyOf(Lists.<StatusCode.Code>newArrayList()));\n",
173+
"RETRYABLE_CODE_DEFINITIONS = definitions.build();\n",
174+
"}\n");
175+
assertEquals(expected, writerVisitor.write());
176+
}
177+
178+
@Test
179+
public void codesDefinitionsBlock_basic() {
180+
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
181+
ServiceDescriptor echoServiceDescriptor = echoFileDescriptor.getServices().get(0);
182+
Map<String, Message> messageTypes = Parser.parseMessages(echoFileDescriptor);
183+
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
184+
Set<ResourceName> outputResourceNames = new HashSet<>();
185+
List<Service> services =
186+
Parser.parseService(echoFileDescriptor, messageTypes, resourceNames, outputResourceNames);
187+
assertEquals(1, services.size());
188+
189+
Service service = services.get(0);
190+
191+
String jsonFilename = "showcase_grpc_service_config.json";
192+
Path jsonPath = Paths.get(JSON_DIRECTORY, jsonFilename);
193+
Optional<GapicServiceConfig> serviceConfigOpt = ServiceConfigParser.parse(jsonPath.toString());
194+
assertTrue(serviceConfigOpt.isPresent());
195+
GapicServiceConfig serviceConfig = serviceConfigOpt.get();
196+
197+
BlockStatement paramDefinitionsBlock =
198+
RetrySettingsComposer.createRetryCodesDefinitionsBlock(
199+
service, serviceConfig, RETRY_CODES_DEFINITIONS_VAR_EXPR);
200+
201+
paramDefinitionsBlock.accept(writerVisitor);
202+
String expected =
203+
createLines(
204+
"static {\n",
205+
"ImmutableMap.Builder<String, ImmutableSet<StatusCode.Code>> definitions ="
206+
+ " ImmutableMap.builder();\n",
207+
"definitions.put(\"retry_policy_1_codes\","
208+
+ " ImmutableSet.copyOf(Lists.<StatusCode.Code>newArrayList(StatusCode.Code.UNAVAILABLE,"
209+
+ " StatusCode.Code.UNKNOWN)));\n",
210+
"definitions.put(\"no_retry_0_codes\","
211+
+ " ImmutableSet.copyOf(Lists.<StatusCode.Code>newArrayList()));\n",
212+
"RETRYABLE_CODE_DEFINITIONS = definitions.build();\n",
213+
"}\n");
214+
assertEquals(expected, writerVisitor.write());
215+
}
216+
217+
private static VariableExpr createRetryableCodesDefinitionsVarExpr() {
218+
TypeNode immutableSetType =
219+
TypeNode.withReference(
220+
ConcreteReference.builder()
221+
.setClazz(ImmutableSet.class)
222+
.setGenerics(Arrays.asList(ConcreteReference.withClazz(StatusCode.Code.class)))
223+
.build());
224+
TypeNode varType =
225+
TypeNode.withReference(
226+
ConcreteReference.builder()
227+
.setClazz(ImmutableMap.class)
228+
.setGenerics(
229+
Arrays.asList(TypeNode.STRING, immutableSetType).stream()
230+
.map(t -> t.reference())
231+
.collect(Collectors.toList()))
232+
.build());
233+
return VariableExpr.withVariable(
234+
Variable.builder().setType(varType).setName("RETRYABLE_CODE_DEFINITIONS").build());
235+
}
236+
138237
private static VariableExpr createRetryParamDefinitionsVarExpr() {
139238
TypeNode retrySettingsType =
140239
TypeNode.withReference(

src/test/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposerTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ public void generateServiceClasses() {
109109
+ "import com.google.common.collect.ImmutableList;\n"
110110
+ "import com.google.common.collect.ImmutableMap;\n"
111111
+ "import com.google.common.collect.ImmutableSet;\n"
112+
+ "import com.google.common.collect.Lists;\n"
112113
+ "import com.google.longrunning.Operation;\n"
113114
+ "import com.google.showcase.v1beta1.BlockRequest;\n"
114115
+ "import com.google.showcase.v1beta1.BlockResponse;\n"
@@ -352,6 +353,21 @@ public void generateServiceClasses() {
352353
+ " blockSettings;\n"
353354
+ " private static final ImmutableMap<String, ImmutableSet<StatusCode.Code>>\n"
354355
+ " RETRYABLE_CODE_DEFINITIONS;\n"
356+
+ "\n"
357+
+ " static {\n"
358+
+ " ImmutableMap.Builder<String, ImmutableSet<StatusCode.Code>> definitions =\n"
359+
+ " ImmutableMap.builder();\n"
360+
+ " definitions.put(\n"
361+
+ " \"retry_policy_1_codes\",\n"
362+
+ " ImmutableSet.copyOf(\n"
363+
+ " Lists.<StatusCode.Code>newArrayList(\n"
364+
+ " StatusCode.Code.UNAVAILABLE, StatusCode.Code.UNKNOWN)));\n"
365+
+ " definitions.put(\n"
366+
+ " \"no_retry_0_codes\","
367+
+ " ImmutableSet.copyOf(Lists.<StatusCode.Code>newArrayList()));\n"
368+
+ " RETRYABLE_CODE_DEFINITIONS = definitions.build();\n"
369+
+ " }\n"
370+
+ "\n"
355371
+ " private static final ImmutableMap<String, RetrySettings>"
356372
+ " RETRY_PARAM_DEFINITIONS;\n"
357373
+ "\n"

0 commit comments

Comments
 (0)