Skip to content
This repository has been archived by the owner on Jul 7, 2021. It is now read-only.

Commit

Permalink
Merge pull request #12 from lucaslorentz/improvements
Browse files Browse the repository at this point in the history
Improvements
  • Loading branch information
lucaslorentz authored Nov 26, 2019
2 parents 225d711 + 365b95c commit 25acc2e
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 128 deletions.
7 changes: 6 additions & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ echo ==Starting caddy with servertype==
./caddy -type supervisor -conf ./examples/Supervisorfile -log stdout &
CADDY_PID=$!
sleep 5
echo "Reloading caddy"
kill -USR1 $CADDY_PID
sleep 5
kill $CADDY_PID
wait $CADDY_PID || true
echo ==Killed caddy with servertype==

sleep 5

echo ""
Expand All @@ -27,6 +29,9 @@ echo ==Starting caddy with httpplugin==
./caddy -conf ./examples/Caddyfile -log stdout &
CADDY_PID=$!
sleep 5
echo "Reloading caddy"
kill -USR1 $CADDY_PID
sleep 5
kill $CADDY_PID
wait $CADDY_PID || true
echo ==Killed caddy with httpplugin==
Expand Down
2 changes: 1 addition & 1 deletion examples/Caddyfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ localhost {
supervisor echo "Hello World {{.Replica}}" {
redirect_stdout stdout
restart_policy on_failure
replicas 5
replicas 3
}
}
2 changes: 1 addition & 1 deletion examples/Supervisorfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ echo {
args "Hello World {{.Replica}}"
redirect_stdout stdout
restart_policy on_failure
replicas 5
replicas 3
}
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ module github.com/lucaslorentz/caddy-supervisor
go 1.13

require (
github.com/Masterminds/goutils v1.1.0 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.15.0+incompatible
github.com/aokoli/goutils v1.1.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible
github.com/caddyserver/caddy v1.0.4
github.com/hacdias/caddy-service v1.0.1
github.com/huandu/xstrings v1.2.1 // indirect
github.com/imdario/mergo v0.3.8 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
)
63 changes: 17 additions & 46 deletions go.sum

Large diffs are not rendered by default.

57 changes: 19 additions & 38 deletions httpplugin/setup.go
Original file line number Diff line number Diff line change
@@ -1,63 +1,44 @@
package httpplugin

import (
"sync"

"github.com/caddyserver/caddy"
"github.com/lucaslorentz/caddy-supervisor/supervisor"
)

func init() {
caddy.RegisterPlugin("supervisor", caddy.Plugin{
ServerType: "http",
Action: setup,
Action: setupDirective,
})
}

var supervisors []*supervisor.Supervisor

func setup(c *caddy.Controller) error {
setupEventsOnlyOnce(c)

func setupDirective(c *caddy.Controller) error {
return c.OncePerServerBlock(func() error {
optionsList, err := parseHTTPDirectives(c)
if err != nil {
return err
}

for _, options := range optionsList {
newSupervisors := supervisor.CreateSupervisors(options)
supervisors = append(supervisors, newSupervisors...)
for _, supervisor := range newSupervisors {
go supervisor.Start()
supervisors := supervisor.CreateSupervisors(options)
for _, sup := range supervisors {
func(s *supervisor.Supervisor) {
c.OnStartup(func() error {
go s.Run()
return nil
})
// Use OnRestart to shutdown supervisors before new instances starts
c.OnRestart(func() error {
s.Stop()
return nil
})
c.OnFinalShutdown(func() error {
s.Stop()
return nil
})
}(sup)
}
}
return nil
})
}

var didSetupEvents = false

func setupEventsOnlyOnce(c *caddy.Controller) {
if didSetupEvents {
return
}
c.OnShutdown(shutdownExecutions)
didSetupEvents = true
}

func shutdownExecutions() error {
var wg sync.WaitGroup

for _, s := range supervisors {
wg.Add(1)
go func(s *supervisor.Supervisor) {
defer wg.Done()
s.Stop()
}(s)
}

wg.Wait()

return nil
}
1 change: 0 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"github.com/caddyserver/caddy/caddy/caddymain"

// Plugins
_ "github.com/hacdias/caddy-service"
_ "github.com/lucaslorentz/caddy-supervisor/httpplugin"
_ "github.com/lucaslorentz/caddy-supervisor/servertype"
)
Expand Down
60 changes: 39 additions & 21 deletions servertype/setup.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package servertype

import (
"net"
"strings"
"sync"

Expand Down Expand Up @@ -32,21 +33,30 @@ func init() {
for _, directive := range directives {
caddy.RegisterPlugin(directive, caddy.Plugin{
ServerType: "supervisor",
Action: setup,
Action: setupDirective,
})
}
}

func newContext(inst *caddy.Instance) caddy.Context {
return &supervisorContext{
instance: inst,
options: make(map[string]*supervisor.Options),
context := &supervisorContext{
instance: inst,
options: make(map[string]*supervisor.Options),
supervisors: []*supervisor.Supervisor{},
}

inst.OnShutdown = append(inst.OnShutdown, func() error {
shutdownSupervisors(context.supervisors)
return nil
})

return context
}

type supervisorContext struct {
instance *caddy.Instance
options map[string]*supervisor.Options
instance *caddy.Instance
options map[string]*supervisor.Options
supervisors []*supervisor.Supervisor
}

func (n *supervisorContext) InspectServerBlocks(sourceFile string, serverBlocks []caddyfile.ServerBlock) ([]caddyfile.ServerBlock, error) {
Expand All @@ -63,23 +73,41 @@ var supervisors []*supervisor.Supervisor

// MakeServers uses the newly-created configs to create and return a list of server instances.
func (n *supervisorContext) MakeServers() ([]caddy.Server, error) {
servers := []caddy.Server{}
for _, options := range n.options {
newSupervisors := supervisor.CreateSupervisors(options)
supervisors = append(supervisors, newSupervisors...)
for _, supervisor := range newSupervisors {
go supervisor.Start()
n.supervisors = append(n.supervisors, supervisor)
servers = append(servers, &supervisorServer{supervisor: supervisor})
}
}
return servers, nil
}

type supervisorServer struct {
supervisor *supervisor.Supervisor
}

func (server *supervisorServer) Listen() (net.Listener, error) {
return nil, nil
}
func (server *supervisorServer) Serve(net.Listener) error {
server.supervisor.Run()
return nil
}
func (server *supervisorServer) ListenPacket() (net.PacketConn, error) {
return nil, nil
}
func (server *supervisorServer) ServePacket(net.PacketConn) error {
return nil
}

func setup(c *caddy.Controller) error {
func setupDirective(c *caddy.Controller) error {
key := mergeKeys(c.ServerBlockKeys)

ctx := c.Context().(*supervisorContext)

setupEventsOnlyOnce(c)

return c.OncePerServerBlock(func() error {
options := ctx.options[key]
for c.Next() {
Expand All @@ -93,17 +121,7 @@ func mergeKeys(keys []string) string {
return strings.Join(keys, " ")
}

var didSetupEvents = false

func setupEventsOnlyOnce(c *caddy.Controller) {
if didSetupEvents {
return
}
c.OnShutdown(shutdownSupervisors)
didSetupEvents = true
}

func shutdownSupervisors() error {
func shutdownSupervisors(supervisors []*supervisor.Supervisor) error {
var wg sync.WaitGroup

for _, s := range supervisors {
Expand Down
41 changes: 25 additions & 16 deletions supervisor/supervisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import (
"time"
)

var emptyFunc = func() {}

const (
minRestartDelay = time.Duration(0)
maxRestartDelay = 5 * time.Minute
minRestartDelay = 10 * time.Second
durationToResetRestartDelay = 10 * time.Minute
)

Expand Down Expand Up @@ -41,13 +43,10 @@ func CreateSupervisors(options *Options) []*Supervisor {
return supervisors
}

// Start a process and supervise
func (s *Supervisor) Start() {
// Run a process and supervise
func (s *Supervisor) Run() {
s.keepRunning = true
go s.supervise()
}

func (s *Supervisor) supervise() {
restartDelay := minRestartDelay

for s.keepRunning {
Expand All @@ -59,14 +58,18 @@ func (s *Supervisor) supervise() {
s.cmd.Dir = s.options.Dir
}

if stdoutFile := getFile(s.options.RedirectStdout); stdoutFile != nil {
if stdoutFile, closeStdout, err := getOutputFile(s.options.RedirectStdout); err == nil {
s.cmd.Stdout = stdoutFile
defer stdoutFile.Close()
closeStdout()
} else {
log.Printf("RedirectStdout error: %v\n", err)
}

if stderrFile := getFile(s.options.RedirectStderr); stderrFile != nil {
if stderrFile, closeStderr, err := getOutputFile(s.options.RedirectStderr); err == nil {
s.cmd.Stderr = stderrFile
defer stderrFile.Close()
closeStderr()
} else {
log.Printf("RedirectStderr error: %v\n", err)
}

start := time.Now()
Expand Down Expand Up @@ -135,26 +138,32 @@ func cmdIsRunning(cmd *exec.Cmd) bool {
return cmd != nil && cmd.Process != nil && (cmd.ProcessState == nil || !cmd.ProcessState.Exited())
}

func getFile(value string) *os.File {
func getOutputFile(value string) (*os.File, func(), error) {
if value == "" {
return nil
return nil, emptyFunc, nil
}

switch value {
case "stdout":
return os.Stdout
return os.Stdout, emptyFunc, nil
case "stderr":
return os.Stderr
return os.Stderr, emptyFunc, nil
default:
outFile, err := os.OpenFile(value, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
if err != nil {
return nil
return nil, nil, err
}
return outFile
return outFile, func() {
outFile.Close()
}, nil
}
}

func increaseRestartDelay(restartDelay time.Duration) time.Duration {
if restartDelay == 0 {
return 1 * time.Second
}

restartDelay = restartDelay * 2

if restartDelay > maxRestartDelay {
Expand Down

0 comments on commit 25acc2e

Please sign in to comment.