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  }