Skip to content

lastbackend/toolkit

Repository files navigation

Last.Backend Toolkit

License GoDev Go Report Card Sourcegraph

lastbackend:toolkit is a programming toolkit for building microservices, services (or elegant monoliths) in Go. We provide you base application modular bolierpate with plugins so you can focus on delivering business value.

Communication

Overview

Last.Backend provides the modular boilerplate with plugins and package management, developed for distributed systems development including RPC and Event driven communication. We provide basics to get you started as quickliy as possible.

Features

Toolkit abstracts away the details of distributed systems. Here are the main features.

  • 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.

  • Plugins - Rich plugin system to reuse same code. Plugins are designed as connectors to user services like databases, brokers, caches, etc... See repository.

  • 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.

  • Services/Clients - Define another services clients and use it anywhere.

  • Logging - One loggins system available across all applications with different log leves.

  • RPC/HTTP Server - GRPC and HTTP servers in the box. Enabled by request in proto file.

  • Usefull help - Print rich usefull helm information how to operate with application

Preparation

Run go mod tidy to resolve the versions. Install all dependencies by running Configure

Download annotations and place them to: $GOPATH/grpc/annotations

Annotations: toolkit

Getting Started

Start with define your apis/.proto file:

syntax = "proto3";

package lastbackend.example;

option go_package = "github.com/lastbackend/toolkit/examples/service/gen;servicepb";
import "github.com/lastbackend/toolkit/protoc-gen-toolkit/toolkit/options/annotations.proto";

message HelloWorldRequest {
  string name = 1;
}

message HelloWorldResponse {
  string id = 1;
}

service Example {
  //  Example methods
  rpc HelloWorld(HelloWorldRequest) returns (HelloWorldResponse) {}
};

Generate toolkit service with command

protoc \
    -I. \
    -I$GOPATH/src \
    -I$GOPATH/grpc/annotations \
    -I. \
    --go_out=:$GOPATH/src \
    --go-grpc_out=require_unimplemented_servers=false:$GOPATH/src \
    ./apis/<service name>.proto

Import generated serive in main.go

import servicepb "<app path>/gen"

Define your application

  app, err := servicepb.NewExampleService("example")
  if err != nil {
    fmt.Println(err)
  }

And now you can start it:

  if err := app.Start(context.Background()); err != nil {
    app.Log().Errorf("could not run the service %v", err)
    os.Exit(1)
    return
  }

  // <- code goes here after application stops

Start application with:

go run main.go

Get help

go run main.go -h

Now you can add options/servers/plugins and packages. After modifing .proto file you need to re-run code generation command from step above.

Add some servers:

only GRPC

  option (toolkit.runtime) = {
    servers: [GRPC]
  };

only HTTP

  option (toolkit.runtime) = {
    servers: [HTTP]
  };

only GRPC, HTTP

  option (toolkit.runtime) = {
    servers: [GRPC, HTTP]
  };

Add plugin:

option (toolkit.plugins) = {
  prefix: "pgsql"    // prefix used if you need to add multiple same plugin instances
  plugin: "postgres" // check available plugins in plugins directory
};

Add anoter service client:

option (toolkit.services) = {
  service: "example",
  package: "<package path>"
};

Register your config

  app, err := servicepb.NewExampleService("example")
  if err != nil {
    fmt.Println(err)
  }

  // Config management
  cfg := config.New()

  if err := app.RegisterConfig(cfg); err != nil {
    app.Log().Error(err)
    return
  }

Register custom package

  app, err := servicepb.NewExampleService("example")
  if err != nil {
    fmt.Println(err)
  }

  // Config management
  cfg := config.New()

  if err := app.RegisterConfig(cfg); err != nil {
    app.Log().Error(err)
    return
  }

  // Add packages
  app.RegisterPackage(repository.NewRepository, controller.NewController)

Define GRPC service descriptor

// exmaple services
type Handlers struct {
  servicepb.ExampleRpcServer

  app  toolkit.Service
  cfg  *config.Config
  repo *repository.Repository
}

func (h Handlers) HelloWorld(ctx context.Context, req *typespb.HelloWorldRequest) (*typespb.HelloWorldResponse, error) {
  h.app.Log().Info("ExamplseRpcServer: HelloWorld: call")

  md, ok := metadata.FromIncomingContext(ctx)
  if !ok {
    return nil, status.Errorf(codes.DataLoss, "failed to get metadata")
  }

  demo := h.repo.Get(ctx)

  resp := typespb.HelloWorldResponse{
    Id:   fmt.Sprintf("%d", demo.Id),
    Name: fmt.Sprintf("%s: %d", req.Name, demo.Count),
    Type: req.Type,
  }

  if len(md["x-req-id"]) > 0 {
    header := metadata.New(map[string]string{"x-response-id": md["x-req-id"][0]})
    grpc.SendHeader(ctx, header)
  }

  return &resp, nil
}

func NewServer(app toolkit.Service, cfg *config.Config, repo *repository.Repository) servicepb.ExampleRpcServer {
  return &Handlers{
    repo: repo,
    app:  app,
    cfg:  cfg,
  }
}
// main.go
  app, err := servicepb.NewExampleService("example")
  if err != nil {
    fmt.Println(err)
  }

  // Config management
  cfg := config.New()

  if err := app.RegisterConfig(cfg); err != nil {
    app.Log().Error(err)
    return
  }

  // Add packages
  app.RegisterPackage(repository.NewRepository, controller.NewController)

  // GRPC service descriptor
  app.Server().GRPC().SetService(server.NewServer)

More examples

See here See examples for more examples.

Changelog

See CHANGELOG for release history.

Contributing

Want to help develop? Check out our contributing documentation.

License

Last.Backend Toolkit is Apache 2.0 licensed.

About

Toolkit is a framework for distributed systems

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published