golet

package module
v0.0.0-...-57c53ee Latest Latest
Warning

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

Go to latest
Published: May 30, 2018 License: MIT Imports: 15 Imported by: 1

README

Golet

Build Status GoDoc Go Report Card

Golet can manage many services with goroutine from one golang program. It's like a supervisor.
It supports go version 1.7 or higher. Golet is based on the idea of Proclet.
Proclet is a great module in Perl.

Synopsis

package main

import (
    "context"
    "fmt"
    "net/http"
    "strings"
    "syscall"
    "time"

    "github.com/Code-Hex/golet"
)

func main() {
    p := golet.New(context.Background())
    p.EnableColor()
    // Execution interval
    p.SetInterval(time.Second * 1)

    p.Env(map[string]string{
        "NAME":  "codehex",
        "VALUE": "121",
    })

    p.Add(
        golet.Service{
            Exec: "plackup --port $PORT",
            Tag:  "plack",
        },
        golet.Service{
            Exec:   "echo 'This is cron!!'",
            Every:  "30 * * * * *",
            Worker: 2,
            Tag:    "cron",
        },
    )

    p.Add(golet.Service{
        Code: func(ctx context.Context) error {
            c := ctx.(*golet.Context)
            c.Println("Hello golet!! Port:", c.Port())
            mux := http.NewServeMux()
            mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
                fmt.Fprintf(w, "Hello, World")
                buf := strings.NewReader("This is log string\nNew line1\nNew line2\nNew line3\n")
                c.Copy(buf)
            })
            go http.ListenAndServe(c.ServePort(), mux)
            for {
                select {
                // You can notify signal received.
                case <-c.Recv():
                    signal, err := c.Signal()
                    if err != nil {
                        c.Println(err.Error())
                        return err
                    }
                    switch signal {
                    case syscall.SIGTERM, syscall.SIGHUP, syscall.SIGINT:
                        c.Println(signal.String())
                        return nil
                    }
                case <-ctx.Done():
                    return nil
                }
            }
        },
        Worker: 3,
    })

    p.Run()
}

See more example.

Logging

In case to run code of synopsis. I send INT signal to golet. Logging

Usage

Basic

Make sure to generate a struct from the New(context.Context) function.

p := golet.New(context.Background())

Next, We can add the service using the Service struct.
Add(services ...Service) error method is also possible to pass multiple Service struct arguments.

p.Add(
    golet.Service{
        // Replace $PORT and automatically assigned port number.
        Exec: "plackup --port $PORT",
        Tag:  "plack", // Keyword for log.
    },
    golet.Service{
        Exec:   "echo 'This is cron!!'",
        // Crontab like format. 
        Every:  "30 * * * * *", // See https://godoc.org/github.com/robfig/cron#hdr-CRON_Expression_Format
        Worker: 2,              // Number of goroutine. The maximum number of workers is 100.
        Tag:    "cron",
    },
)

Finally, You can run many services. use Run() error

p.Run()

Option

The default option is like this.

interval:   0
color:      false
logger:     colorable.NewColorableStderr()
logWorker:  true
execNotice: true
cancelSignal: -1

By using the go-colorable, colored output is also compatible with windows.
You can change these options by using the following method.

// SetInterval can specify the interval at which the command is executed.
func (c *config) SetInterval(t time.Duration) { c.interval = t }

// EnableColor can output colored log.
func (c *config) EnableColor() { c.color = true }

// SetLogger can specify the *os.File
// for example in https://github.com/lestrrat/go-file-rotatelogs
/*
      logf, _ := rotatelogs.New(
          "/path/to/access_log.%Y%m%d%H%M",
          rotatelogs.WithLinkName("/path/to/access_log"),
          rotatelogs.WithMaxAge(24 * time.Hour),
          rotatelogs.WithRotationTime(time.Hour),
      )

      golet.New(context.Background()).SetLogger(logf)
*/
func (c *config) SetLogger(f io.Writer) { c.logger = f }

// DisableLogger is prevent to output log
func (c *config) DisableLogger() { c.logWorker = false }

// DisableExecNotice is disable execute notifications
func (c *config) DisableExecNotice() { c.execNotice = false }

// SetCtxCancelSignal can specify the signal to send processes when context cancel.
// If you do not set, golet will not send the signal when context cancel.
func (c *config) SetCtxCancelSignal(signal syscall.Signal) { c.cancelSignal = signal }

Environment variables

You can use temporary environment variables in golet program.

p.Env(map[string]string{
    "NAME":  "codehex",
    "VALUE": "121",
})

and, If you execute service as command, you can get also PORT env variable.

golet.Context

See, https://godoc.org/github.com/Code-Hex/golet#Context

golet.Context can be to context.Context, io.Writer also io.Closer.

So, you can try to write strange code like this.

golet.Service{
    Code: func(ctx context.Context) error {
        // die program
        c := ctx.(*golet.Context)
        fmt.Fprintf(c, "Hello, World!!\n")
        c.Printf("Hello, Port: %d\n", c.Port())
        time.Sleep(time.Second * 1)
        select {
        case <-c.Recv():
            signal, err := c.Signal()
            if err != nil {
                c.Println(err.Error())
                return err
            }
            switch signal {
            case syscall.SIGTERM, syscall.SIGHUP:
                c.Println(signal.String())
                return fmt.Errorf("die message")
            case syscall.SIGINT:
                return nil
            }
            return nil
        }
    },
}

Installation

go get -u github.com/Code-Hex/golet

Contribution

  1. Fork https://github.com/Code-Hex/golet/fork
  2. Commit your changes
  3. Create a new Pull Request

I'm waiting for a lot of PR.

Future

  • Create like foreman command
  • Support better windows
  • Write a test for signals for some distribution

Author

codehex

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Context

type Context struct {
	// contains filtered or unexported fields
}

Context struct for golet

func (*Context) Copy

func (c *Context) Copy(src io.Reader) (written int64, err error)

Copy method is wrapped by io.Copy

func (*Context) Deadline

func (c *Context) Deadline() (deadline time.Time, ok bool)

Deadline is implemented for context.Context

func (*Context) Done

func (c *Context) Done() <-chan struct{}

Done is implemented for context.Context

func (*Context) Err

func (c *Context) Err() error

Err is implemented for context.Context

func (*Context) Port

func (c *Context) Port() int

Port returns assgined port

func (*Context) Print

func (c *Context) Print(a ...interface{}) (n int, err error)

Print formats using the default formats for its operands and writes to golet writer. Spaces are added between operands when neither is a string. It returns the number of bytes written and any write error encountered.

func (*Context) Printf

func (c *Context) Printf(format string, a ...interface{}) (n int, err error)

Printf formats according to a format specifier and writes to golet writer It returns the number of bytes written and any write error encountered.

func (*Context) Println

func (c *Context) Println(a ...interface{}) (n int, err error)

Println formats using the default formats for its operands and writes to golet writer. Spaces are always added between operands and a newline is appended. It returns the number of bytes written and any write error encountered.

func (*Context) Recv

func (c *Context) Recv() <-chan struct{}

Recv send channel when a process receives a signal.

func (*Context) ServePort

func (c *Context) ServePort() string

ServePort returns assigned port which is serve format

func (*Context) Signal

func (c *Context) Signal() (os.Signal, error)

Signal returns os.Signal and error.

func (*Context) Value

func (c *Context) Value(key interface{}) interface{}

Value is implemented for context.Context

func (*Context) Write

func (c *Context) Write(p []byte) (n int, err error)

Improved io.writer for golet

type Logger

type Logger struct {
	// contains filtered or unexported fields
}

func (*Logger) Write

func (l *Logger) Write(data []byte) (n int, err error)

Improved io.writer for golet

type Runner

type Runner interface {
	SetInterval(time.Duration)
	EnableColor()
	SetLogger(io.Writer)
	DisableLogger()
	DisableExecNotice()
	SetCtxCancelSignal(syscall.Signal)
	Env(map[string]string) error
	Add(...Service) error
	Run() error
}

Runner interface have methods for configuration and to run services.

func New

func New(ctx context.Context) Runner

New to create struct of golet.

type Service

type Service struct {
	Exec   string
	Code   func(context.Context) error // Routine of services.
	Worker int                         // Number of goroutine. The maximum number of workers is 100.
	Tag    string                      // Keyword for log.
	Every  string                      // Crontab like format. See https://godoc.org/github.com/robfig/cron#hdr-CRON_Expression_Format
	// contains filtered or unexported fields
}

Service struct to add services to golet.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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