hippo

package module
v2.1.0 Latest Latest
Warning

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

Go to latest
Published: Feb 16, 2020 License: MIT Imports: 10 Imported by: 4

README

hippo

The hippo is an easy, fast, lightweight engine which supports gracefully shutting down the servers.

Build Status Go Report Card

Hippo

Import it in your program as:

import "github.com/devplayg/hippo/v2"

Simple server

type SimpleServer struct {
    hippo.Launcher // DO NOT REMOVE; Launcher links servers and engine each other.
}

func (s *SimpleServer) Start() error {
    return nil
}

func (s *SimpleServer) Stop() error {
    return nil
}

Run

Simple
engine := hippo.NewEngine(&SimpleServer{}, nil)
if err := engine.Start(); err != nil {
    panic(err)
}
Debug
engine := hippo.NewEngine(&SimpleServer{}, &hippo.Config{Debug:true})
if err := engine.Start(); err != nil {
    panic(err)
}
Log to the file

powered by https://github.com/sirupsen/logrus

config := &hippo.Config{
    Debug:  true,
    LogDir: "/var/log/",
}
engine := hippo.NewEngine(&SimpleServer{}, config)
if err := engine.Start(); err != nil {
    s.Log.Error(err)
}

Normal server

Shutting down the server gracefully

type NormalServer struct {
    hippo.Launcher // DO NOT REMOVE; Launcher links servers and engine each other.
}

func (s *NormalServer) Start() error {
    s.Log.Debug("server has been started")

    for {
        // Do your repetitive jobs
        s.Log.Info("server is working on it")

        // Intentional error
        // return errors.New("intentional error")

        select {
        case <-s.Ctx.Done(): // for gracefully shutdown
            s.Log.Debug("server canceled; no longer works")
            return nil
        case <-time.After(2 * time.Second):
        }
    }
}

func (s *NormalServer) Stop() error {
    s.Log.Debug("server has been stopped")
    return nil
}

console output

DEBU[2020-02-16T07:36:35+09:00] engine has been started                      
DEBU[2020-02-16T07:36:35+09:00] server has been started                      
INFO[2020-02-16T07:36:35+09:00] server is working on it                      
INFO[2020-02-16T07:36:37+09:00] server is working on it                      
INFO[2020-02-16T07:36:39+09:00] server is working on it                      
INFO[2020-02-16T07:36:40+09:00] received signal, shutting down..             
DEBU[2020-02-16T07:36:40+09:00] server canceled; no longer works             
DEBU[2020-02-16T07:36:40+09:00] server has been stopped                      
DEBU[2020-02-16T07:36:40+09:00] engine has been stopped  

Server including HTTP Server

Shutting down the server including HTTP server

type Server struct {
    hippo.Launcher // DO NOT REMOVE; Launcher links servers and engine each other.
}

func (s *Server) Start() error {
    s.Log.Debug("server has been started")
    ch := make(chan struct{})
    go func() {
        if err := s.startHttpServer(); err != nil {
            s.Log.Error(err)
        }
        close(ch)
    }()

    defer func() {
        <-ch
    }()

    for {
        // Do your repetitive jobs
        s.Log.Info("server is working on it")

        // Intentional error
        // s.Cancel() // send cancel signal to engine
        // return errors.New("intentional error")

        select {
        case <-s.Ctx.Done(): // for gracefully shutdown
            s.Log.Debug("server canceled; no longer works")
            return nil
        case <-time.After(2 * time.Second):
        }
    }
}

func (s *Server) startHttpServer() error {
    var srv http.Server

    ch := make(chan struct{})
    go func() {
        <-s.Ctx.Done()
        if err := srv.Shutdown(context.Background()); err != nil {
            s.Log.Error(err)
        }
        close(ch)
    }()

    s.Log.Debug("HTTP server has been started")
    if err := srv.ListenAndServe(); err != http.ErrServerClosed {
        s.Log.Fatalf("HTTP server ListenAndServe: %v", err)
    }
    <-ch
    s.Log.Debug("HTTP server has been stopped")
    return nil
}

func (s *Server) Stop() error {
    s.Log.Debug("server has been stopped")
    return nil
}

Console output

DEBU[2020-02-16T07:45:35+09:00] engine has been started                      
DEBU[2020-02-16T07:45:35+09:00] server has been started                      
INFO[2020-02-16T07:45:35+09:00] server is working on it                      
DEBU[2020-02-16T07:45:35+09:00] HTTP server has been started                 
INFO[2020-02-16T07:45:37+09:00] server is working on it                      
INFO[2020-02-16T07:45:39+09:00] server is working on it                      
INFO[2020-02-16T07:45:40+09:00] received signal, shutting down..             
DEBU[2020-02-16T07:45:40+09:00] server canceled; no longer works             
DEBU[2020-02-16T07:45:40+09:00] HTTP server has been stopped                 
DEBU[2020-02-16T07:45:40+09:00] server has been stopped                      
DEBU[2020-02-16T07:45:40+09:00] engine has been stopped    

Multiple servers

Shutting down multiple servers gracefully

type Server struct {
    hippo.Launcher // DO NOT REMOVE; Launcher links servers and engine each other.
}

func (s *Server) Start() error {
	wg := new(sync.WaitGroup)

	// Server 1
	wg.Add(1)
	go func() {
		defer wg.Done()
		if err := s.startServer1(); err != nil {
			s.Log.Error(err)
		}
	}()

	// Server 2
	wg.Add(1)
	go func() {
		defer wg.Done()
		if err := s.startServer2(); err != nil {
			s.Log.Error(err)
		}
	}()

	// Server 3
	wg.Add(1)
	go func() {
		defer wg.Done()
		if err := s.startHttpServer(); err != nil {
			s.Log.Error(err)
		}
	}()

	s.Log.Debug("all servers has been started")
	wg.Wait()
	return nil
}

func (s *Server) startServer1() error {
    s.Log.Debug("server-1 has been started")
    for {
        s.Log.Info("server-1 is working on it")
        select {
        case <-s.Ctx.Done(): // for gracefully shutdown
            s.Log.Debug("server-1 canceled; no longer works")
            return nil
        case <-time.After(2 * time.Second):
        }
    }
}

func (s *Server) startServer2() error {
    s.Log.Debug("server-2 has been started")
    for {
        s.Log.Info("server-2 is working on it")

        // s.Cancel() // if you want to stop all server, uncomment this line
        return errors.New("intentional error on server-2; no longer works")

        select {
        case <-s.Ctx.Done(): // for gracefully shutdown
            s.Log.Debug("server-2 canceled; no longer works")
            return nil
        case <-time.After(2 * time.Second):
        }
    }
}

func (s *Server) startHttpServer() error {
    var srv http.Server

    ch := make(chan struct{})
    go func() {
        <-s.Ctx.Done()
        if err := srv.Shutdown(context.Background()); err != nil {
            s.Log.Error(err)
        }
        close(ch)
    }()

    s.Log.Debug("HTTP server has been started")
    if err := srv.ListenAndServe(); err != http.ErrServerClosed {
        s.Log.Fatalf("HTTP server ListenAndServe: %v", err)
    }
    <-ch
    s.Log.Debug("HTTP server has been stopped")
    return nil
}

func (s *Server) Stop() error {
    s.Log.Debug("all server has been stopped")
    return nil
}

Console output

DEBU[2020-02-16T07:50:00+09:00] engine has been started                      
DEBU[2020-02-16T07:50:00+09:00] all servers has been started                 
DEBU[2020-02-16T07:50:00+09:00] HTTP server has been started                 
DEBU[2020-02-16T07:50:00+09:00] server-1 has been started                    
INFO[2020-02-16T07:50:00+09:00] server-1 is working on it                    
DEBU[2020-02-16T07:50:00+09:00] server-2 has been started                    
INFO[2020-02-16T07:50:00+09:00] server-2 is working on it                    
ERRO[2020-02-16T07:50:00+09:00] intentional error on server-2; no longer works 
INFO[2020-02-16T07:50:02+09:00] server-1 is working on it                    
INFO[2020-02-16T07:50:03+09:00] received signal, shutting down..             
DEBU[2020-02-16T07:50:03+09:00] server-1 canceled; no longer works           
DEBU[2020-02-16T07:50:03+09:00] HTTP server has been stopped                 
DEBU[2020-02-16T07:50:03+09:00] all server has been stopped                  
DEBU[2020-02-16T07:50:03+09:00] engine has been stopped

Documentation

Overview

Hippo is an easy, fast, lightweight server framework.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	Name        string
	Description string
	Version     string
	LogDir      string
	Debug       bool
	Trace       bool
	Logger      *log.Logger
}

Hippo configuration struct

type Engine

type Engine struct {
	Config *Config
	// contains filtered or unexported fields
}

Engine supports engine framework.

func NewEngine

func NewEngine(server Server, config *Config) *Engine

NewEngine allocates a new server to engine.

func (*Engine) Start

func (e *Engine) Start() error

Start starts server and opens error channel.

type Launcher

type Launcher struct {
	Engine     *Engine
	Log        *logrus.Logger
	Ctx        context.Context
	Cancel     context.CancelFunc
	WorkingDir string
}

type Server

type Server interface {
	Start() error
	Stop() error
	// contains filtered or unexported methods
}

Server is the interface that configures the server

Directories

Path Synopsis
examples
normal command
normal-multiple command
simple command

Jump to

Keyboard shortcuts

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