toolkit

package module
v0.0.0-...-692e367 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 15, 2024 License: Apache-2.0 Imports: 5 Imported by: 3

README

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.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client interface {
	GRPC() client.GRPCClient
	HTTP() client.HTTPClient
}

type Config

type Config any

type Package

type Package any

type PackageItem

type PackageItem struct {
	Index  int
	Source any
}

type Plugin

type Plugin any

type Server

type Server interface {
	HTTP() server.HTTPServer
	GRPC() server.GRPCServer

	HTTPGet(name string) server.HTTPServer
	HTTPNew(name string, options *server.HTTPServerOptions) server.HTTPServer

	GRPCGet(name string) server.GRPCServer
	GRPCNew(name string, options *server.GRPCServerOptions) server.GRPCServer
}

type Service

type Service interface {
	Meta() *meta.Meta

	Log() logger.Logger
	Client() Client
	Server() Server

	RegisterConfig(config ...any) error
	RegisterPlugin(constructor ...any)
	RegisterPackage(constructor ...any)

	Start(ctx context.Context) error
	Stop(ctx context.Context, err error)

	RegisterOnStartHook(...func(ctx context.Context) error)
	RegisterOnStartSyncHook(...func(ctx context.Context) error)

	RegisterOnStopHook(...func(ctx context.Context) error)
	RegisterOnStopSyncHook(...func(ctx context.Context) error)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL