Skip to content

Commit 9d1c092

Browse files
committed
fix problem with puma workers, refactoring
1 parent 4e5683c commit 9d1c092

File tree

8 files changed

+307
-414
lines changed

8 files changed

+307
-414
lines changed

internal/app/caddyrailsapp.go

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,30 @@ import (
55
"github.com/caddyserver/caddy/v2/caddyconfig"
66
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
77
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
8-
"github.com/evilmartians/caddy_rails/internal/utils"
8+
"github.com/evilmartians/caddy_rails/internal/logger"
9+
"github.com/evilmartians/caddy_rails/internal/process"
10+
"os"
911
)
1012

13+
var caddyLogger = logger.NewCaddyRailsLogger()
14+
1115
func init() {
1216
caddy.RegisterModule(CaddyRailsApp{})
13-
httpcaddyfile.RegisterGlobalOption("serve-rails", parseGlobalCaddyfileBlock)
17+
httpcaddyfile.RegisterGlobalOption("serve", parseGlobalCaddyfileBlock)
1418
}
1519

1620
type CaddyRailsApp struct {
1721
Command []string `json:"command,omitempty"`
1822
PidFile string `json:"pid_file,omitempty"`
1923

20-
process *utils.UpstreamProcess
21-
stopCh chan struct{}
24+
process *process.UpstreamProcess
2225
}
2326

2427
func (a *CaddyRailsApp) Provision(_ caddy.Context) error {
28+
return nil
29+
}
30+
31+
func (a *CaddyRailsApp) Start() error {
2532
var command string
2633
var arguments []string
2734

@@ -32,64 +39,59 @@ func (a *CaddyRailsApp) Provision(_ caddy.Context) error {
3239
arguments = a.Command[1:]
3340
}
3441

35-
process, err := utils.NewUpstreamProcess(command, arguments, false, a.PidFile)
42+
proc, err := process.NewUpstreamProcess(command, arguments, false, a.PidFile)
3643
if err != nil {
3744
return err
3845
}
3946

40-
a.process = process
41-
a.stopCh = make(chan struct{})
47+
a.process = proc
4248

43-
return nil
44-
}
49+
caddyLogger.Info("CaddyRails was started")
4550

46-
func (a CaddyRailsApp) Start() error {
47-
_, err := a.process.Run()
48-
49-
return err
51+
return a.process.Run()
5052
}
5153

5254
func (a *CaddyRailsApp) Stop() error {
53-
caddy.Log().Info("CaddyRails stopped")
54-
55-
if a.process != nil {
56-
return a.process.Stop()
55+
err := a.process.Shutdown(os.Interrupt)
56+
if err != nil {
57+
return err
5758
}
5859

59-
close(a.stopCh)
60+
caddyLogger.Info("CaddyRails stopped")
61+
6062
return nil
6163
}
6264

6365
func (a CaddyRailsApp) CaddyModule() caddy.ModuleInfo {
6466
return caddy.ModuleInfo{
65-
ID: "serve-rails",
67+
ID: "serve",
6668
New: func() caddy.Module { return new(CaddyRailsApp) },
6769
}
6870
}
6971

7072
func parseGlobalCaddyfileBlock(d *caddyfile.Dispenser, _ interface{}) (interface{}, error) {
71-
var caddy_rails CaddyRailsApp
73+
var caddyRails CaddyRailsApp
7274

7375
if d.NextArg() && d.NextArg() {
74-
caddy_rails.Command = append([]string{d.Val()}, d.RemainingArgs()...)
76+
caddyRails.Command = append([]string{d.Val()}, d.RemainingArgs()...)
7577
}
7678

7779
for d.NextBlock(0) {
7880
switch d.Val() {
7981
case "command":
80-
caddy_rails.Command = d.RemainingArgs()
82+
caddyRails.Command = d.RemainingArgs()
8183
case "pid_file":
8284
if d.NextArg() {
83-
caddy_rails.PidFile = d.Val()
85+
caddyRails.PidFile = d.Val()
8486
} else {
8587
return nil, d.ArgErr()
8688
}
8789
}
8890
}
8991

9092
return httpcaddyfile.App{
91-
Name: "serve-rails",
92-
Value: caddyconfig.JSON(caddy_rails, nil),
93+
Name: "serve",
94+
Value: caddyconfig.JSON(caddyRails, nil),
9395
}, nil
9496
}
9597

internal/commands/CaddyfileTemplate

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
serve-rails bin/rails s -p {{.BackendPort}}
2+
serve bin/rails s -p {{.BackendPort}}
33
{{if .Debug}}debug{{end}}
44
{{if .AccessLog}}log{{end}}
55
https_port {{.HttpsPort}}

internal/commands/serve.go

Lines changed: 69 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"github.com/caddyserver/caddy/v2"
77
caddycmd "github.com/caddyserver/caddy/v2/cmd"
88
_ "github.com/caddyserver/caddy/v2/modules/standard"
9+
"github.com/evilmartians/caddy_rails/internal/logger"
10+
"github.com/evilmartians/caddy_rails/internal/process"
911
"github.com/evilmartians/caddy_rails/internal/utils"
1012
"github.com/spf13/cobra"
1113
"go.uber.org/zap"
@@ -14,48 +16,39 @@ import (
1416
"time"
1517
)
1618

17-
const (
18-
errStopUpstream = "failed to stop upstream process: %v"
19-
errPhasedRestart = "failed to phased restart upstream process: %v"
20-
errRunUpstreamProcess = "failed to run upstream process: %v"
21-
errLoadCaddyConfig = "Caddyfile loading error"
22-
errAccessCaddyFile = "Error accessing Caddyfile"
23-
infoCaddyFileAbsent = "Caddyfile does not exist. The server is running direct way"
24-
infoCaddyFileLoaded = "Caddyfile is correct and loaded. The server is running via Caddyfile"
25-
)
26-
27-
var logger = utils.NewCaddyRailsLogger()
19+
var caddyLogger = logger.NewCaddyRailsLogger()
2820

2921
func init() {
3022
caddycmd.RegisterCommand(caddycmd.Command{
3123
Name: "serve",
3224
Short: "Runs an external server and sets up a reverse proxy to it",
33-
Long: `
34-
The serve command runs an external server specified as its argument and
35-
sets up a reverse proxy to forward requests to it.`,
3625
CobraFunc: func(cmd *cobra.Command) {
37-
cmd.Flags().String("pid-file", "", "Path to the PID file to control an existing process")
38-
cmd.Flags().Bool("stop", false, "Stop the running process")
39-
cmd.Flags().Bool("phased-restart", false, "Perform a phased restart of the server")
40-
cmd.Flags().Bool("anycable-enabled", false, "Activate AnyCable")
41-
cmd.Flags().String("server-type", "puma", "The type of server (puma or unicorn) to control")
42-
cmd.Flags().Int("target-port", 3000, "The port that your server should run on. caddy-rails will set this values to the PORT env variable when starting your server.")
43-
cmd.Flags().Int("http-port", 80, "The port to listen on for HTTP traffic.")
44-
cmd.Flags().Int("https-port", 443, "The port to listen on for HTTPS traffic.")
45-
cmd.Flags().StringP("listen", "l", "localhost", "The address to which to bind the listener")
46-
cmd.Flags().String("ssl-domain", "", "The domain name to use for SSL provisioning. If not set, SSL will be disabled.")
47-
cmd.Flags().StringP("files-path", "f", "", "The domain name to use for SSL provisioning. If not set, SSL will be disabled.")
48-
cmd.Flags().BoolP("debug", "v", false, "Enable verbose debug logs")
49-
cmd.Flags().Bool("access-log", true, "Enable the access log")
50-
cmd.Flags().Bool("no-compress", false, "Disable Zstandard and Gzip compression")
51-
cmd.Flags().Duration("http-idle-timeout", 60*time.Second, "The maximum time in seconds that a client can be idle before the connection is closed.")
52-
cmd.Flags().Duration("http-read-timeout", 30*time.Second, "The maximum time in seconds that a client can take to send the request headers.")
53-
cmd.Flags().Duration("http-write-timeout", 30*time.Second, "The maximum time in seconds during which the client must read the response.")
26+
addServeFlags(cmd)
5427
cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdServeRails)
5528
},
5629
})
5730
}
5831

32+
func addServeFlags(cmd *cobra.Command) {
33+
cmd.Flags().String("pid-file", "", "Path to the PID file to control an existing process")
34+
cmd.Flags().Bool("stop", false, "Stop the running process")
35+
cmd.Flags().Bool("phased-restart", false, "Perform a phased restart of the server")
36+
cmd.Flags().String("server-type", "puma", "The type of server (puma or unicorn) to control")
37+
cmd.Flags().Int("target-port", 3000, "The port that your server should run on")
38+
cmd.Flags().Int("http-port", 80, "The port to listen on for HTTP traffic.")
39+
cmd.Flags().Int("https-port", 443, "The port to listen on for HTTPS traffic.")
40+
cmd.Flags().StringP("listen", "l", "localhost", "The address to which to bind the listener")
41+
cmd.Flags().String("ssl-domain", "", "The domain name to use for SSL provisioning. If not set, SSL will be disabled.")
42+
cmd.Flags().StringP("files-path", "f", "", "The path to the files to serve")
43+
cmd.Flags().BoolP("debug", "v", false, "Enable verbose debug logs")
44+
cmd.Flags().Bool("access-log", true, "Enable the access log")
45+
cmd.Flags().Bool("no-compress", false, "Disable Zstandard and Gzip compression")
46+
cmd.Flags().Bool("anycable-enabled", false, "Activate AnyCable")
47+
cmd.Flags().Duration("http-idle-timeout", 60*time.Second, "The maximum idle time for HTTP connections.")
48+
cmd.Flags().Duration("http-read-timeout", 30*time.Second, "The maximum read timeout for HTTP connections.")
49+
cmd.Flags().Duration("http-write-timeout", 30*time.Second, "The maximum write timeout for HTTP connections.")
50+
}
51+
5952
func cmdServeRails(fs caddycmd.Flags) (int, error) {
6053
caddy.TrapSignals()
6154

@@ -65,86 +58,75 @@ func cmdServeRails(fs caddycmd.Flags) (int, error) {
6558
serverType := fs.String("server-type")
6659

6760
if stop || phasedRestart {
68-
upstream, err := utils.NewUpstreamProcess("", nil, false, pidFile)
69-
if err != nil {
70-
return 1, err
71-
}
72-
73-
if stop {
74-
if err := upstream.Stop(); err != nil {
75-
return 1, fmt.Errorf(errStopUpstream, err)
76-
}
77-
return 0, nil
78-
}
79-
80-
if phasedRestart {
81-
if err := upstream.PhasedRestart(serverType); err != nil {
82-
return 1, fmt.Errorf(errPhasedRestart, err)
83-
}
84-
return 0, nil
85-
}
61+
return handleProcessControl(pidFile, stop, phasedRestart, serverType)
8662
}
8763

88-
if loadConfigIfNeeded() {
64+
loaded, err := loadConfigIfNeeded()
65+
if err != nil {
66+
return 1, err
67+
}
68+
if loaded {
8969
select {}
9070
}
9171

72+
if fs.Int("target-port") != 0 {
73+
os.Setenv("PORT", fmt.Sprintf("%d", fs.Int("target-port")))
74+
}
75+
9276
if err := utils.StartCaddyReverseProxy(fs); err != nil {
9377
return 1, err
9478
}
9579

96-
return runUpstreamProcess(fs, pidFile)
80+
select {}
9781
}
9882

99-
func loadConfigIfNeeded() bool {
100-
curdir, _ := os.Getwd()
101-
configFile := filepath.Join(curdir, "Caddyfile")
102-
103-
if _, err := os.Stat(configFile); err != nil {
104-
if errors.Is(err, os.ErrNotExist) {
105-
logger.Info(infoCaddyFileAbsent)
106-
} else {
107-
logger.Error(errAccessCaddyFile, zap.Error(err))
108-
}
109-
return false
110-
}
111-
112-
config, _, err := caddycmd.LoadConfig(configFile, "")
83+
func handleProcessControl(pidFile string, stop, phasedRestart bool, serverType string) (int, error) {
84+
upstream, err := process.NewUpstreamProcess("", nil, false, pidFile)
11385
if err != nil {
114-
logger.Error(errLoadCaddyConfig, zap.Error(err))
115-
116-
return false
86+
return 1, err
11787
}
11888

119-
err = caddy.Load(config, true)
120-
if err != nil {
121-
logger.Error(errLoadCaddyConfig, zap.Error(err))
122-
123-
return false
89+
if stop {
90+
if err := upstream.Stop(); err != nil {
91+
return 1, fmt.Errorf("failed to stop upstream process: %v", err)
92+
}
93+
return 0, nil
12494
}
12595

126-
logger.Info(infoCaddyFileLoaded)
96+
if phasedRestart {
97+
if err := upstream.PhasedRestart(serverType); err != nil {
98+
return 1, fmt.Errorf("failed to phased restart upstream process: %v", err)
99+
}
100+
return 0, nil
101+
}
127102

128-
return true
103+
return 1, errors.New("invalid process control command")
129104
}
130105

131-
func runUpstreamProcess(fs caddycmd.Flags, pidFile string) (int, error) {
132-
// Set PORT to be inherited by the upstream process.
133-
os.Setenv("PORT", fmt.Sprintf("%d", fs.Int("target-port")))
106+
func loadConfigIfNeeded() (bool, error) {
107+
curdir, _ := os.Getwd()
108+
configFile := filepath.Join(curdir, "Caddyfile")
134109

135-
var args []string
136-
if len(fs.Args()) > 0 {
137-
args = fs.Args()[1:]
110+
if _, err := os.Stat(configFile); err != nil {
111+
if errors.Is(err, os.ErrNotExist) {
112+
caddyLogger.Info("Caddyfile does not exist. Running directly")
113+
} else {
114+
caddyLogger.Error("Error accessing Caddyfile", zap.Error(err))
115+
}
116+
return false, nil
138117
}
139118

140-
upstream, err := utils.NewUpstreamProcess(fs.Arg(0), args, true, pidFile)
119+
config, _, err := caddycmd.LoadConfig(configFile, "")
141120
if err != nil {
142-
return 1, err
121+
caddyLogger.Error("Caddyfile loading error", zap.Error(err))
122+
return false, err
143123
}
144124

145-
exitCode, err := upstream.Run()
146-
if err != nil {
147-
return 1, fmt.Errorf(errRunUpstreamProcess, err)
125+
if err := caddy.Load(config, true); err != nil {
126+
caddyLogger.Error("Caddyfile loading error", zap.Error(err))
127+
return false, err
148128
}
149-
return exitCode, nil
129+
130+
caddyLogger.Info("Caddyfile loaded successfully")
131+
return true, nil
150132
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package utils
1+
package logger
22

33
import (
44
"github.com/caddyserver/caddy/v2"

0 commit comments

Comments
 (0)