Skip to content

Commit 35cd3b9

Browse files
committed
refactor: simplify listener logic
1 parent 90145dd commit 35cd3b9

2 files changed

Lines changed: 151 additions & 156 deletions

File tree

internal/bootstrap/app_bootstrap.go

Lines changed: 23 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"encoding/json"
88
"errors"
99
"fmt"
10-
"net"
1110
"net/http"
1211
"net/url"
1312
"os"
@@ -38,16 +37,17 @@ type Services struct {
3837
}
3938

4039
type BootstrapApp struct {
41-
config model.Config
42-
runtime model.RuntimeConfig
43-
services Services
44-
log *logger.Logger
45-
ctx context.Context
46-
cancel context.CancelFunc
47-
queries *repository.Queries
48-
router *gin.Engine
49-
db *sql.DB
50-
wg sync.WaitGroup
40+
config model.Config
41+
runtime model.RuntimeConfig
42+
services Services
43+
log *logger.Logger
44+
ctx context.Context
45+
cancel context.CancelFunc
46+
queries *repository.Queries
47+
router *gin.Engine
48+
db *sql.DB
49+
wg sync.WaitGroup
50+
listeners []Listener
5151
}
5252

5353
func NewBootstrapApp(config model.Config) *BootstrapApp {
@@ -254,56 +254,32 @@ func (app *BootstrapApp) Setup() error {
254254
app.wg.Go(app.heartbeatRoutine)
255255
}
256256

257-
// create err channel to listen for server errors
258-
errChanLen := 0
259-
257+
// setup listeners
260258
runUnix := app.config.Server.SocketPath != ""
261259
runHTTP := app.config.Server.SocketPath == "" || app.config.Server.ConcurrentListenersEnabled
262260
runTailscale := app.services.tailscaleService != nil
263261

264-
if runUnix {
265-
errChanLen++
262+
if runHTTP {
263+
app.listeners = append(app.listeners, ListenerHTTP)
266264
}
267265

268-
if runHTTP {
269-
errChanLen++
266+
if runUnix {
267+
app.listeners = append(app.listeners, ListenerUnix)
270268
}
271269

272270
if runTailscale {
273-
errChanLen++
271+
app.listeners = append(app.listeners, ListenerTailscale)
274272
}
275273

276-
errChan := make(chan error, errChanLen)
277-
278274
if app.config.Server.ConcurrentListenersEnabled {
279275
app.log.App.Info().Msg("Concurrent listeners enabled, will run on all available listeners")
280276
}
281277

282-
// serve unix
283-
if runUnix {
284-
app.wg.Go(func() {
285-
if err := app.serveUnix(); err != nil {
286-
errChan <- err
287-
}
288-
})
289-
}
290-
291-
// serve to http
292-
if runHTTP {
293-
app.wg.Go(func() {
294-
if err := app.serveHTTP(); err != nil {
295-
errChan <- err
296-
}
297-
})
298-
}
278+
// run listeners
279+
lec, err := app.runListeners()
299280

300-
// serve to tailscale
301-
if runTailscale {
302-
app.wg.Go(func() {
303-
if err := app.serveTailscale(); err != nil {
304-
errChan <- err
305-
}
306-
})
281+
if err != nil {
282+
return fmt.Errorf("failed to run listeners: %w", err)
307283
}
308284

309285
// monitor cancellation and server errors
@@ -312,123 +288,14 @@ func (app *BootstrapApp) Setup() error {
312288
case <-app.ctx.Done():
313289
app.log.App.Info().Msg("Oh, it's time for me to go, bye!")
314290
return nil
315-
case err := <-errChan:
291+
case err := <-lec:
316292
if err != nil {
317-
return fmt.Errorf("server error: %w", err)
293+
return fmt.Errorf("listener error: %w", err)
318294
}
319295
}
320296
}
321297
}
322298

323-
func (app *BootstrapApp) serveHTTP() error {
324-
address := fmt.Sprintf("%s:%d", app.config.Server.Address, app.config.Server.Port)
325-
326-
app.log.App.Info().Msgf("Starting server on %s", address)
327-
328-
server := &http.Server{
329-
Addr: address,
330-
Handler: app.router.Handler(),
331-
}
332-
333-
go func() {
334-
<-app.ctx.Done()
335-
app.log.App.Debug().Msg("Shutting down http listener")
336-
server.Shutdown(app.ctx)
337-
}()
338-
339-
err := server.ListenAndServe()
340-
341-
if err != nil && !errors.Is(err, http.ErrServerClosed) {
342-
return fmt.Errorf("failed to start http listener: %w", err)
343-
}
344-
345-
return nil
346-
}
347-
348-
func (app *BootstrapApp) serveUnix() error {
349-
if app.config.Server.SocketPath == "" {
350-
return nil
351-
}
352-
353-
_, err := os.Stat(app.config.Server.SocketPath)
354-
355-
if err == nil {
356-
app.log.App.Info().Msgf("Removing existing socket file %s", app.config.Server.SocketPath)
357-
err := os.Remove(app.config.Server.SocketPath)
358-
359-
if err != nil {
360-
return fmt.Errorf("failed to remove existing socket file: %w", err)
361-
}
362-
}
363-
364-
app.log.App.Info().Msgf("Starting server on unix socket %s", app.config.Server.SocketPath)
365-
366-
listener, err := net.Listen("unix", app.config.Server.SocketPath)
367-
368-
if err != nil {
369-
return fmt.Errorf("failed to create unix socket listener: %w", err)
370-
}
371-
372-
server := &http.Server{
373-
Handler: app.router.Handler(),
374-
}
375-
376-
shutdown := func() {
377-
server.Shutdown(app.ctx)
378-
listener.Close()
379-
os.Remove(app.config.Server.SocketPath)
380-
}
381-
382-
go func() {
383-
<-app.ctx.Done()
384-
app.log.App.Debug().Msg("Shutting down unix socket listener")
385-
shutdown()
386-
}()
387-
388-
err = server.Serve(listener)
389-
390-
if err != nil && !errors.Is(err, http.ErrServerClosed) {
391-
shutdown()
392-
return fmt.Errorf("failed to start unix socket listener: %w", err)
393-
}
394-
395-
return nil
396-
}
397-
398-
func (app *BootstrapApp) serveTailscale() error {
399-
app.log.App.Info().Msgf("Starting Tailscale server on %s", fmt.Sprintf("https://%s", app.services.tailscaleService.GetHostname()))
400-
401-
listener, err := app.services.tailscaleService.CreateListener()
402-
403-
if err != nil {
404-
return fmt.Errorf("failed to create tailscale listener: %w", err)
405-
}
406-
407-
server := &http.Server{
408-
Handler: app.router.Handler(),
409-
}
410-
411-
shutdown := func() {
412-
server.Shutdown(app.ctx)
413-
listener.Close()
414-
}
415-
416-
go func() {
417-
<-app.ctx.Done()
418-
app.log.App.Debug().Msg("Shutting down Tailscale listener")
419-
shutdown()
420-
}()
421-
422-
err = server.Serve(listener)
423-
424-
if err != nil && !errors.Is(err, http.ErrServerClosed) {
425-
shutdown()
426-
return fmt.Errorf("failed to start tailscale listener: %w", err)
427-
}
428-
429-
return nil
430-
}
431-
432299
func (app *BootstrapApp) heartbeatRoutine() {
433300
ticker := time.NewTicker(time.Duration(12) * time.Hour)
434301
defer ticker.Stop()

internal/bootstrap/router_bootstrap.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
package bootstrap
22

33
import (
4+
"errors"
45
"fmt"
6+
"net"
7+
"net/http"
8+
"os"
59

610
"github.com/tinyauthapp/tinyauth/internal/controller"
711
"github.com/tinyauthapp/tinyauth/internal/middleware"
812

913
"github.com/gin-gonic/gin"
1014
)
1115

16+
type Listener int
17+
18+
const (
19+
ListenerHTTP Listener = iota
20+
ListenerUnix
21+
ListenerTailscale
22+
)
23+
1224
func (app *BootstrapApp) setupRouter() error {
1325
// we don't want gin debug mode
1426
gin.SetMode(gin.ReleaseMode)
@@ -53,3 +65,119 @@ func (app *BootstrapApp) setupRouter() error {
5365
app.router = engine
5466
return nil
5567
}
68+
69+
func (app *BootstrapApp) runListeners() (chan error, error) {
70+
// lec -> listener error channel
71+
lec := make(chan error, len(app.listeners))
72+
73+
for _, listenerType := range app.listeners {
74+
listenerFunc, err := app.listenerFromType(listenerType)
75+
76+
if err != nil {
77+
return nil, fmt.Errorf("failed to get listener function: %w", err)
78+
}
79+
80+
app.wg.Go(func() {
81+
lec <- listenerFunc()
82+
})
83+
}
84+
85+
return lec, nil
86+
}
87+
88+
func (app *BootstrapApp) listenerFromType(listenerType Listener) (func() error, error) {
89+
switch listenerType {
90+
case ListenerHTTP:
91+
return app.serveHTTP, nil
92+
case ListenerUnix:
93+
return app.serveUnix, nil
94+
case ListenerTailscale:
95+
return app.serveTailscale, nil
96+
default:
97+
return nil, fmt.Errorf("invalid listener type: %d", listenerType)
98+
}
99+
}
100+
101+
func (app *BootstrapApp) serveHTTP() error {
102+
address := fmt.Sprintf("%s:%d", app.config.Server.Address, app.config.Server.Port)
103+
104+
app.log.App.Info().Msgf("Starting server on %s", address)
105+
106+
listener, err := net.Listen("tcp", address)
107+
108+
if err != nil {
109+
return fmt.Errorf("failed to create tcp listener: %w", err)
110+
}
111+
112+
server := &http.Server{
113+
Addr: address,
114+
Handler: app.router.Handler(),
115+
}
116+
117+
return app.serve(listener, server, "http")
118+
}
119+
120+
func (app *BootstrapApp) serveUnix() error {
121+
_, err := os.Stat(app.config.Server.SocketPath)
122+
123+
if err == nil {
124+
app.log.App.Info().Msgf("Removing existing socket file %s", app.config.Server.SocketPath)
125+
err := os.Remove(app.config.Server.SocketPath)
126+
127+
if err != nil {
128+
return fmt.Errorf("failed to remove existing socket file: %w", err)
129+
}
130+
}
131+
132+
app.log.App.Info().Msgf("Starting server on unix socket %s", app.config.Server.SocketPath)
133+
134+
listener, err := net.Listen("unix", app.config.Server.SocketPath)
135+
136+
if err != nil {
137+
return fmt.Errorf("failed to create unix socket listener: %w", err)
138+
}
139+
140+
server := &http.Server{
141+
Handler: app.router.Handler(),
142+
}
143+
144+
return app.serve(listener, server, "unix socket")
145+
}
146+
147+
func (app *BootstrapApp) serveTailscale() error {
148+
app.log.App.Info().Msgf("Starting Tailscale server on %s", fmt.Sprintf("https://%s", app.services.tailscaleService.GetHostname()))
149+
150+
listener, err := app.services.tailscaleService.CreateListener()
151+
152+
if err != nil {
153+
return fmt.Errorf("failed to create tailscale listener: %w", err)
154+
}
155+
156+
server := &http.Server{
157+
Handler: app.router.Handler(),
158+
}
159+
160+
return app.serve(listener, server, "tailscale")
161+
}
162+
163+
func (app *BootstrapApp) serve(listener net.Listener, server *http.Server, name string) error {
164+
shutdown := func() {
165+
server.Shutdown(app.ctx)
166+
listener.Close()
167+
}
168+
169+
go func() {
170+
<-app.ctx.Done()
171+
app.log.App.Debug().Msgf("Shutting down %s listener", name)
172+
shutdown()
173+
}()
174+
175+
err := server.Serve(listener)
176+
177+
if err != nil && !errors.Is(err, http.ErrServerClosed) {
178+
shutdown()
179+
return fmt.Errorf("failed to start %s listener: %w", name, err)
180+
}
181+
182+
return nil
183+
}

0 commit comments

Comments
 (0)