Giter Site home page Giter Site logo

go-boot's Introduction

go-boot

Go

A micro-framework for deterministic and graceful services boot and shutdown.

Check the article on Medium about the framework.

Why?

Most golang applications are made of multiple services, where each service is an entity that can be started and stopped on-demand. Most of the services depend on each other, for example it makes little sense to start HTTP server until a DB connection is established. Therefore, all the services need to be started in the right order and then stopped in the reverse order. This allows application to boot and shutdown gracefully and deterministically, properly acquiring and releasing all the resources, locks, etc.

Furthermore, each application has to respect OS signals (e.g. SIGINT, SIGTERM). And such the signals can be caught even during the application boot process and in that case they should trigger the shutdown flow immediately. The shutdown flow is also non-trivial, because for most execution environments an application is given a little window to shutdown gracefully (usually 5 to 15 seconds) before it gets SIGKILL. All the flows are usually controlled by a context provided by the application, either bound to OS signals, or a timeout.

This architecure pattern became very common for most applications, and this is why go-boot was built as a standalone micro-framework.

Usage

  1. Installation
go get -u github.com/pinebit/go-boot
  1. Make your services conforming the boot.Service interface
package service1

type Service1 interface {
    boot.Service
}
  1. Instantiate all your services

Recommended to use Dependency Injection frameworks, such as wire, fx or any other, for now we simply create all services one by one.

s1 := service1.NewService1(...)
s2 := service2.NewService2(...)
s3 := service3.NewService3(...) 
  1. Start all services respecting the given context
// You can choose between boot.Sequentially, boot.Simultaneously or combine them.
services := boot.Sequentially(s1, s2, s3)
// the ctx can stop the boot flow gracefully
if err := services.Start(ctx); err != nil {
    // report error and proceed with the shutdown 
}

You can combine sequential and parallel boot flows. For example, given services A, B, C and D. Where service A must be started first, then B and C can be started simultaneously and then D can be started only after A, B and C have started:

services := boot.Sequentially(a, boot.Simultaneously(b, c), d)
err := services.Start(ctx)
  1. Shutdown all services respecting a timeout
// The recommended shutdown timeout is five seconds for most systems.
ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second)
defer cancel()
// Stop() will stop all services in the reverse order.
// The shutdown flow would break if the ctx is done.
if err := services.Stop(ctx); err != nil {
    // One of the services reported error, or ctx is done.
    // Log the error for further investigation.
    // You still have a good chance to release critical resources, locks. 
}

Using Application wrapper

Almost every application is handling OS signals to trigger a shutdown. The framework provides this convenient wrapper, that allows you to build a complete graceful application:

func main() {
    // creating services: s1, s2, s3
    services := boot.Sequentially(s1, s2, s3)
    app := boot.NewApplicationForService(services, 5 * time.Second)
    if err := app.Run(context.Background()); err != nil {
        fmt.Println("application error:", err)
    }
}

Using HttpServer wrapper for the standard http.Server

The framework also provides a convenient wrapper for http.Server that gracefully starts/stops the HTTP server. Together with Application you get the complete minimalistic yet graceful HTTP server:

func main() {
	server := &http.Server{
		Addr: ":8080",
	}
	serverAsService := boot.NewHttpServer(server)
	app := boot.NewApplicationForService(serverAsService, 5*time.Second)
	if err := app.Run(context.Background()); err != nil {
		fmt.Println("server error:", err)
	}
}

License

MIT. See the LICENSE file for details.

go-boot's People

Contributors

pinebit avatar

Stargazers

Steve Ellis avatar Konstantin Komelin avatar  avatar

Watchers

 avatar

Forkers

jaekook

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.