github.com/lastbackend/toolkit@v0.0.0-20241020043710-cafa37b95aad/README.md (about) 1 # Last.Backend Toolkit 2 [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) 3 [![GoDev](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/github.com/lastbackend/toolkit?tab=doc) 4 [![Go Report Card](https://goreportcard.com/badge/github.com/lastbackend/toolkit)](https://goreportcard.com/report/github.com/lastbackend/toolkit) 5 [![Sourcegraph](https://sourcegraph.com/github.com/lastbackend/toolkit/-/badge.svg)](https://sourcegraph.com/github.com/lastbackend/toolkit?badge) 6 7 **lastbackend:toolkit** is a **programming toolkit** for building microservices, services 8 (or elegant monoliths) in Go. We provide you base application modular bolierpate with plugins so you can focus on delivering 9 business value. 10 11 ## Communication 12 13 [![](https://dcbadge.vercel.app/api/server/WhK9ujvem9)](https://discord.gg/WhK9ujvem9) 14 15 ## Overview 16 17 Last.Backend provides the modular boilerplate with plugins and package management, developed for distributed systems development including RPC and Event driven communication. 18 We provide basics to get you started as quickliy as possible. 19 20 ## Features 21 22 Toolkit abstracts away the details of distributed systems. Here are the main features. 23 24 - **Configs** - Register your own config in main.go and use it from anywhere. The config interface provides a way to load application level config from env vars. 25 26 - **Plugins** - Rich plugin system to reuse same code. Plugins are designed as connectors to user services like databases, brokers, caches, etc... [See repository](https://github.com/lastbackend/toolkit-plugins). 27 28 - **Packages** - Automatic packages system for custom packages logic. Like repositories, controllers and other stuff. Can be powerupped with Hooks: <PreStart, OnStart, OnStop> to customize applciation logic. 29 30 - **Services/Clients** - Define another services clients and use it anywhere. 31 32 - **Logging** - One loggins system available across all applications with different log leves. 33 34 - **RPC/HTTP Server** - GRPC and HTTP servers in the box. Enabled by request in proto file. 35 36 - **Usefull help** - Print rich usefull helm information how to operate with application 37 38 ## Preparation 39 40 Run go mod tidy to resolve the versions. Install all dependencies by running 41 [Configure](https://github.com/lastbackend/toolkit/tree/master/hack/hack/bootstrap.sh) 42 43 Download annotations and place them to: 44 `$GOPATH/grpc/annotations` 45 46 Annotations: [toolkit](https://github.com/lastbackend/toolkit/tree/master/protoc-gen-toolkit/toolkit/options/annotations.proto) 47 48 ## Getting Started 49 50 Start with define your apis/<service name>.proto file: 51 52 ```proto 53 syntax = "proto3"; 54 55 package lastbackend.example; 56 57 option go_package = "github.com/lastbackend/toolkit/examples/service/gen;servicepb"; 58 import "github.com/lastbackend/toolkit/protoc-gen-toolkit/toolkit/options/annotations.proto"; 59 60 message HelloWorldRequest { 61 string name = 1; 62 } 63 64 message HelloWorldResponse { 65 string id = 1; 66 } 67 68 service Example { 69 // Example methods 70 rpc HelloWorld(HelloWorldRequest) returns (HelloWorldResponse) {} 71 }; 72 ``` 73 74 Generate toolkit service with command 75 76 ```bash 77 protoc \ 78 -I. \ 79 -I$GOPATH/src \ 80 -I$GOPATH/grpc/annotations \ 81 -I. \ 82 --go_out=:$GOPATH/src \ 83 --go-grpc_out=require_unimplemented_servers=false:$GOPATH/src \ 84 ./apis/<service name>.proto 85 ``` 86 87 Import generated serive in main.go 88 89 ```go 90 import servicepb "<app path>/gen" 91 ``` 92 93 Define your application 94 95 ```go 96 app, err := servicepb.NewExampleService("example") 97 if err != nil { 98 fmt.Println(err) 99 } 100 ``` 101 102 And now you can start it: 103 104 ```go 105 if err := app.Start(context.Background()); err != nil { 106 app.Log().Errorf("could not run the service %v", err) 107 os.Exit(1) 108 return 109 } 110 111 // <- code goes here after application stops 112 ``` 113 114 Start application with: 115 116 ```bash 117 go run main.go 118 ``` 119 120 Get help 121 122 ```bash 123 go run main.go -h 124 ``` 125 126 Now you can add options/servers/plugins and packages. After modifing .proto file you need to re-run code generation command from step above. 127 128 Add some servers: 129 130 only GRPC 131 ```proto 132 option (toolkit.runtime) = { 133 servers: [GRPC] 134 }; 135 ``` 136 137 only HTTP 138 ```proto 139 option (toolkit.runtime) = { 140 servers: [HTTP] 141 }; 142 ``` 143 144 only GRPC, HTTP 145 ```proto 146 option (toolkit.runtime) = { 147 servers: [GRPC, HTTP] 148 }; 149 ``` 150 151 Add plugin: 152 153 ```proto 154 option (toolkit.plugins) = { 155 prefix: "pgsql" // prefix used if you need to add multiple same plugin instances 156 plugin: "postgres" // check available plugins in plugins directory 157 }; 158 ``` 159 160 Add anoter service client: 161 162 ```proto 163 option (toolkit.services) = { 164 service: "example", 165 package: "<package path>" 166 }; 167 ``` 168 169 Register your config 170 171 ```go 172 app, err := servicepb.NewExampleService("example") 173 if err != nil { 174 fmt.Println(err) 175 } 176 177 // Config management 178 cfg := config.New() 179 180 if err := app.RegisterConfig(cfg); err != nil { 181 app.Log().Error(err) 182 return 183 } 184 ``` 185 186 Register custom package 187 188 ```go 189 app, err := servicepb.NewExampleService("example") 190 if err != nil { 191 fmt.Println(err) 192 } 193 194 // Config management 195 cfg := config.New() 196 197 if err := app.RegisterConfig(cfg); err != nil { 198 app.Log().Error(err) 199 return 200 } 201 202 // Add packages 203 app.RegisterPackage(repository.NewRepository, controller.NewController) 204 ``` 205 206 Define GRPC service descriptor 207 208 ```go 209 // exmaple services 210 type Handlers struct { 211 servicepb.ExampleRpcServer 212 213 app toolkit.Service 214 cfg *config.Config 215 repo *repository.Repository 216 } 217 218 func (h Handlers) HelloWorld(ctx context.Context, req *typespb.HelloWorldRequest) (*typespb.HelloWorldResponse, error) { 219 h.app.Log().Info("ExamplseRpcServer: HelloWorld: call") 220 221 md, ok := metadata.FromIncomingContext(ctx) 222 if !ok { 223 return nil, status.Errorf(codes.DataLoss, "failed to get metadata") 224 } 225 226 demo := h.repo.Get(ctx) 227 228 resp := typespb.HelloWorldResponse{ 229 Id: fmt.Sprintf("%d", demo.Id), 230 Name: fmt.Sprintf("%s: %d", req.Name, demo.Count), 231 Type: req.Type, 232 } 233 234 if len(md["x-req-id"]) > 0 { 235 header := metadata.New(map[string]string{"x-response-id": md["x-req-id"][0]}) 236 grpc.SendHeader(ctx, header) 237 } 238 239 return &resp, nil 240 } 241 242 func NewServer(app toolkit.Service, cfg *config.Config, repo *repository.Repository) servicepb.ExampleRpcServer { 243 return &Handlers{ 244 repo: repo, 245 app: app, 246 cfg: cfg, 247 } 248 } 249 ``` 250 251 ```go 252 // main.go 253 app, err := servicepb.NewExampleService("example") 254 if err != nil { 255 fmt.Println(err) 256 } 257 258 // Config management 259 cfg := config.New() 260 261 if err := app.RegisterConfig(cfg); err != nil { 262 app.Log().Error(err) 263 return 264 } 265 266 // Add packages 267 app.RegisterPackage(repository.NewRepository, controller.NewController) 268 269 // GRPC service descriptor 270 app.Server().GRPC().SetService(server.NewServer) 271 ``` 272 273 ## More examples 274 275 See here [See examples](https://github.com/lastbackend/toolkit/tree/master/examples) for more examples. 276 277 ## Changelog 278 279 See [CHANGELOG](https://github.com/lastbackend/toolkit/tree/master/CHANGELOG.md) for release history. 280 281 ## Contributing 282 283 Want to help develop? Check out our [contributing documentation](https://github.com/lastbackend/toolkit/tree/master/CONTRIBUTING.md). 284 285 ## License 286 287 Last.Backend Toolkit is Apache 2.0 licensed.