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.