go.uber.org/yarpc@v1.72.1/encoding/thrift/thriftrw-plugin-yarpc/fx.go (about) 1 // Copyright (c) 2022 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package main 22 23 import ( 24 "path/filepath" 25 26 "go.uber.org/thriftrw/plugin" 27 ) 28 29 const fxDocTemplate = ` 30 // Code generated by thriftrw-plugin-yarpc 31 // @generated 32 33 <$pkgname := printf "%sfx" (lower .Name)> 34 <$serverpkgname := printf "%sserver" (lower .Name)> 35 // Package <$pkgname> provides better integration for Fx for services 36 // implementing or calling <.Name>. 37 // 38 // Clients 39 // 40 // If you are making requests to <.Name>, use the Client function to inject a 41 // <.Name> client into your container. 42 // 43 // fx.Provide(<$pkgname>.Client("...")) 44 // 45 // Servers 46 // 47 // If you are implementing <.Name>, provide a <$serverpkgname>.Interface into 48 // the container and use the Server function. 49 // 50 // Given, 51 // 52 // func New<.Name>Handler() <$serverpkgname>.Interface 53 // 54 // You can do the following to have the procedures of <.Name> made available 55 // to an Fx application. 56 // 57 // fx.Provide( 58 // New<.Name>Handler, 59 // <$pkgname>.Server(), 60 // ) 61 package <$pkgname> 62 ` 63 64 const fxClientTemplate = ` 65 // Code generated by thriftrw-plugin-yarpc 66 // @generated 67 68 <$pkgname := printf "%sfx" (lower .Name)> 69 package <$pkgname> 70 71 <$yarpc := import "go.uber.org/yarpc"> 72 <$transport := import "go.uber.org/yarpc/api/transport"> 73 <$restriction := import "go.uber.org/yarpc/api/x/restriction"> 74 <$thrift := import "go.uber.org/yarpc/encoding/thrift"> 75 <$client := import .ClientPackagePath> 76 <$fx := import "go.uber.org/fx"> 77 78 // Params defines the dependencies for the <.Name> client. 79 type Params struct { 80 <$fx>.In 81 82 Provider <$yarpc>.ClientConfig 83 Restriction <$restriction>.Checker ` + "`optional:\"true\"`" + ` 84 } 85 86 // Result defines the output of the <.Name> client module. It provides a 87 // <.Name> client to an Fx application. 88 type Result struct { 89 <$fx>.Out 90 91 Client <$client>.Interface 92 93 // We are using an fx.Out struct here instead of just returning a client 94 // so that we can add more values or add named versions of the client in 95 // the future without breaking any existing code. 96 } 97 98 // Client provides a <.Name> client to an Fx application using the given name 99 // for routing. 100 // 101 // fx.Provide( 102 // <$pkgname>.Client("..."), 103 // newHandler, 104 // ) 105 func Client(name string, opts ...<$thrift>.ClientOption) interface{} { 106 return func(p Params) Result { 107 cc := p.Provider.ClientConfig(name) 108 if namer, ok := cc.GetUnaryOutbound().(transport.Namer); ok && p.Restriction != nil { 109 if err := p.Restriction.Check(thrift.Encoding, namer.TransportName()); err != nil { 110 panic(err.Error()) 111 } 112 } 113 client := <$client>.New(cc, opts...) 114 return Result{Client: client} 115 } 116 }` 117 118 const fxServerTemplate = ` 119 // Code generated by thriftrw-plugin-yarpc 120 // @generated 121 122 <$pkgname := printf "%sfx" (lower .Name)> 123 package <$pkgname> 124 125 <$transport := import "go.uber.org/yarpc/api/transport"> 126 <$thrift := import "go.uber.org/yarpc/encoding/thrift"> 127 <$server := import .ServerPackagePath> 128 <$fx := import "go.uber.org/fx"> 129 130 // ServerParams defines the dependencies for the <.Name> server. 131 type ServerParams struct { 132 <$fx>.In 133 134 Handler <$server>.Interface 135 } 136 137 // ServerResult defines the output of <.Name> server module. It provides the 138 // procedures of a <.Name> handler to an Fx application. 139 // 140 // The procedures are provided to the "yarpcfx" value group. Dig 1.2 or newer 141 // must be used for this feature to work. 142 type ServerResult struct { 143 <$fx>.Out 144 145 Procedures []<$transport>.Procedure ` + "`group:\"yarpcfx\"`" + ` 146 } 147 148 // Server provides procedures for <.Name> to an Fx application. It expects a 149 // <$pkgname>.Interface to be present in the container. 150 // 151 // fx.Provide( 152 // func(h *My<.Name>Handler) <$server>.Interface { 153 // return h 154 // }, 155 // <$pkgname>.Server(), 156 // ) 157 func Server(opts ...<$thrift>.RegisterOption) interface{} { 158 return func(p ServerParams) ServerResult { 159 procedures := <$server>.New(p.Handler, opts...) 160 return ServerResult{Procedures: procedures} 161 } 162 } 163 ` 164 165 func fxGenerator(data *serviceTemplateData, files map[string][]byte) (err error) { 166 packageName := filepath.Base(data.FxPackagePath()) 167 168 // kv.thrift => .../kv/keyvaluefx/doc.go 169 docPath := filepath.Join(data.Module.Directory, packageName, "doc.go") 170 files[docPath], err = plugin.GoFileFromTemplate(docPath, fxDocTemplate, data, templateOptions...) 171 172 // kv.thrift => .../kv/keyvaluefx/client.go 173 clientPath := filepath.Join(data.Module.Directory, packageName, "client.go") 174 files[clientPath], err = plugin.GoFileFromTemplate(clientPath, fxClientTemplate, data, templateOptions...) 175 176 // kv.thrift => .../kv/keyvaluefx/server.go 177 serverPath := filepath.Join(data.Module.Directory, packageName, "server.go") 178 files[serverPath], err = plugin.GoFileFromTemplate(serverPath, fxServerTemplate, data, templateOptions...) 179 180 return 181 }