Skip to content

Commit

Permalink
feat(generator): automatic longrunning mixin (#812)
Browse files Browse the repository at this point in the history
Some services need the `longrunning` mixin, but their service config YAML file
does not provide it. Automatically add it when needed.
coryan authored Jan 24, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 50a37e1 commit 33b8ab7
Showing 2 changed files with 37 additions and 6 deletions.
22 changes: 17 additions & 5 deletions generator/internal/parser/mixin.go
Original file line number Diff line number Diff line change
@@ -40,15 +40,27 @@ const (
type mixinMethods map[string]bool

// loadMixins loads file descriptors for configured mixins.
func loadMixins(serviceConfig *serviceconfig.Service) (mixinMethods, []*descriptorpb.FileDescriptorProto) {
func loadMixins(serviceConfig *serviceconfig.Service, withLongrunning bool) (mixinMethods, []*descriptorpb.FileDescriptorProto) {
var files []*descriptorpb.FileDescriptorProto
var enabledMixinMethods mixinMethods = make(map[string]bool)
apis := serviceConfig.GetApis()
if len(apis) < 2 {
var apiNames []string
hasLongrunning := false
for _, api := range serviceConfig.GetApis() {
// Only insert the service if needed. We want to preserve the order
// to make the generated code reproducible, so we cannot use a map.
if api.GetName() == longrunningService {
hasLongrunning = true
}
apiNames = append(apiNames, api.GetName())
}
if withLongrunning && !hasLongrunning {
apiNames = append(apiNames, longrunningService)
}
if len(apiNames) < 2 {
return enabledMixinMethods, files
}
for _, api := range apis {
switch api.GetName() {
for _, apiName := range apiNames {
switch apiName {
case locationService:
files = append(files, protodesc.ToFileDescriptorProto(location.File_google_cloud_location_locations_proto))
case iamService:
21 changes: 20 additions & 1 deletion generator/internal/parser/protobuf.go
Original file line number Diff line number Diff line change
@@ -227,7 +227,8 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code
if serviceConfig.Documentation != nil {
result.Description = serviceConfig.Documentation.Summary
}
enabledMixinMethods, mixinFileDesc = loadMixins(serviceConfig)
withLongrunning := requiresLongrunningMixin(req)
enabledMixinMethods, mixinFileDesc = loadMixins(serviceConfig, withLongrunning)
packageName := ""
for _, api := range serviceConfig.Apis {
packageName, _ = splitApiName(api.Name)
@@ -355,6 +356,24 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code
return result
}

// requiresLongrunningMixin finds out if any method returns a LRO. This is used
// to forcibly load the longrunning mixin. It needs to happen before the proto
// descriptors are converted to the `api.*`, as that conversion requires the
// mixin.
func requiresLongrunningMixin(req *pluginpb.CodeGeneratorRequest) bool {
for _, f := range req.GetSourceFileDescriptors() {
for _, s := range f.Service {
for _, m := range s.Method {
info := parseOperationInfo(f.GetPackage(), m)
if info != nil && m.GetOutputType() == ".google.longrunning.Operation" {
return true
}
}
}
}
return false
}

var descriptorpbToTypez = map[descriptorpb.FieldDescriptorProto_Type]api.Typez{
descriptorpb.FieldDescriptorProto_TYPE_DOUBLE: api.DOUBLE_TYPE,
descriptorpb.FieldDescriptorProto_TYPE_FLOAT: api.FLOAT_TYPE,

0 comments on commit 33b8ab7

Please sign in to comment.