Skip to content

Commit 71ddfbb

Browse files
committed
feat: use sync groups for better cancellation
1 parent b73a9db commit 71ddfbb

7 files changed

Lines changed: 61 additions & 34 deletions

File tree

internal/bootstrap/app_bootstrap.go

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"os/signal"
1515
"sort"
1616
"strings"
17+
"sync"
1718
"syscall"
1819
"time"
1920

@@ -45,6 +46,7 @@ type BootstrapApp struct {
4546
queries *repository.Queries
4647
router *gin.Engine
4748
db *sql.DB
49+
wg sync.WaitGroup
4850
}
4951

5052
func NewBootstrapApp(config model.Config) *BootstrapApp {
@@ -227,33 +229,39 @@ func (app *BootstrapApp) Setup() error {
227229

228230
// start db cleanup routine
229231
app.log.App.Debug().Msg("Starting database cleanup routine")
230-
go app.dbCleanupRoutine()
232+
app.wg.Go(app.dbCleanupRoutine)
231233

232234
// if analytics are not disabled, start heartbeat
233235
if app.config.Analytics.Enabled {
234236
app.log.App.Debug().Msg("Starting heartbeat routine")
235-
go app.heartbeatRoutine()
237+
app.wg.Go(app.heartbeatRoutine)
236238
}
237239

238240
// create err channel to listen for server errors
239241
errChan := make(chan error, 1)
240242

241243
// serve unix
242-
go func() {
243-
errChan <- app.serveUnix()
244-
}()
244+
app.wg.Go(func() {
245+
if err := app.serveUnix(); err != nil {
246+
errChan <- err
247+
}
248+
})
245249

246250
// serve to http
247-
go func() {
248-
errChan <- app.serveHTTP()
249-
}()
251+
app.wg.Go(func() {
252+
if err := app.serveHTTP(); err != nil {
253+
errChan <- err
254+
}
255+
})
250256

251257
// monitor cancellation and server errors
252258
for {
253259
select {
254260
case <-app.ctx.Done():
255-
app.log.App.Info().Msg("Oh, seems like I got to shutdown, bye!")
261+
app.wg.Wait()
262+
app.log.App.Debug().Msg("Closing database")
256263
app.db.Close()
264+
app.log.App.Info().Msg("Oh, it's time for me to go, bye!")
257265
return nil
258266
case err := <-errChan:
259267
if err != nil {
@@ -275,14 +283,14 @@ func (app *BootstrapApp) serveHTTP() error {
275283

276284
go func() {
277285
<-app.ctx.Done()
278-
app.log.App.Debug().Msg("Shutting down server")
286+
app.log.App.Debug().Msg("Shutting down http listener")
279287
server.Close()
280288
}()
281289

282290
err := server.ListenAndServe()
283291

284292
if err != nil && !errors.Is(err, http.ErrServerClosed) {
285-
return fmt.Errorf("failed to start server: %w", err)
293+
return fmt.Errorf("failed to start http listener: %w", err)
286294
}
287295

288296
return nil
@@ -312,24 +320,26 @@ func (app *BootstrapApp) serveUnix() error {
312320
return fmt.Errorf("failed to create unix socket listner: %w", err)
313321
}
314322

323+
server := &http.Server{
324+
Handler: app.router.Handler(),
325+
}
326+
327+
defer server.Close()
315328
defer listener.Close()
316329
defer os.Remove(app.config.Server.SocketPath)
317330

318331
go func() {
319332
<-app.ctx.Done()
320-
app.log.App.Debug().Msg("Shutting down server")
333+
app.log.App.Debug().Msg("Shutting down unix sokcet listener")
334+
server.Close()
321335
listener.Close()
322336
os.Remove(app.config.Server.SocketPath)
323337
}()
324338

325-
server := &http.Server{
326-
Handler: app.router.Handler(),
327-
}
328-
329339
err = server.Serve(listener)
330340

331-
if err != nil && !errors.Is(err, net.ErrClosed) {
332-
return fmt.Errorf("failed to start server: %w", err)
341+
if err != nil && (!errors.Is(err, net.ErrClosed) || !errors.Is(err, http.ErrServerClosed)) {
342+
return fmt.Errorf("failed to start unix socket listener: %w", err)
333343
}
334344

335345
return nil

internal/bootstrap/service_bootstrap.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
)
99

1010
func (app *BootstrapApp) setupServices() error {
11-
ldapService := service.NewLdapService(app.log, app.config, app.ctx)
11+
ldapService := service.NewLdapService(app.log, app.config, app.ctx, &app.wg)
1212

1313
err := ldapService.Init()
1414

@@ -27,7 +27,7 @@ func (app *BootstrapApp) setupServices() error {
2727
if useKubernetes {
2828
app.log.App.Debug().Msg("Using Kubernetes label provider")
2929

30-
kubernetesService := service.NewKubernetesService(app.log, app.ctx)
30+
kubernetesService := service.NewKubernetesService(app.log, app.ctx, &app.wg)
3131

3232
err = kubernetesService.Init()
3333

@@ -40,7 +40,7 @@ func (app *BootstrapApp) setupServices() error {
4040
} else {
4141
app.log.App.Debug().Msg("Using Docker label provider")
4242

43-
dockerService := service.NewDockerService(app.log, app.ctx)
43+
dockerService := service.NewDockerService(app.log, app.ctx, &app.wg)
4444

4545
err = dockerService.Init()
4646

@@ -72,7 +72,7 @@ func (app *BootstrapApp) setupServices() error {
7272

7373
app.services.oauthBrokerService = oauthBrokerService
7474

75-
authService := service.NewAuthService(app.log, app.config, app.runtime, app.ctx, app.services.ldapService, app.queries, app.services.oauthBrokerService)
75+
authService := service.NewAuthService(app.log, app.config, app.runtime, app.ctx, &app.wg, app.services.ldapService, app.queries, app.services.oauthBrokerService)
7676

7777
err = authService.Init()
7878

@@ -82,7 +82,7 @@ func (app *BootstrapApp) setupServices() error {
8282

8383
app.services.authService = authService
8484

85-
oidcService := service.NewOIDCService(app.log, app.config, app.runtime, app.queries, app.ctx)
85+
oidcService := service.NewOIDCService(app.log, app.config, app.runtime, app.queries, app.ctx, &app.wg)
8686

8787
err = oidcService.Init()
8888

internal/service/auth_service.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ type AuthService struct {
7777
config model.Config
7878
runtime model.RuntimeConfig
7979
context context.Context
80+
wg *sync.WaitGroup
8081

8182
ldap *LdapService
8283
queries *repository.Queries
@@ -98,6 +99,7 @@ func NewAuthService(
9899
config model.Config,
99100
runtime model.RuntimeConfig,
100101
context context.Context,
102+
wg *sync.WaitGroup,
101103
ldap *LdapService,
102104
queries *repository.Queries,
103105
oauthBroker *OAuthBrokerService,
@@ -106,6 +108,7 @@ func NewAuthService(
106108
log: log,
107109
runtime: runtime,
108110
context: context,
111+
wg: wg,
109112
config: config,
110113
loginAttempts: make(map[string]*LoginAttempt),
111114
ldapGroupsCache: make(map[string]*LdapGroupsCache),
@@ -117,7 +120,7 @@ func NewAuthService(
117120
}
118121

119122
func (auth *AuthService) Init() error {
120-
go auth.CleanupOAuthSessionsRoutine()
123+
auth.wg.Go(auth.CleanupOAuthSessionsRoutine)
121124
return nil
122125
}
123126

internal/service/docker_service.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package service
33
import (
44
"context"
55
"strings"
6+
"sync"
67

78
"github.com/tinyauthapp/tinyauth/internal/model"
89
"github.com/tinyauthapp/tinyauth/internal/utils/decoders"
@@ -16,17 +17,20 @@ type DockerService struct {
1617
log *logger.Logger
1718
client *client.Client
1819
context context.Context
20+
wg *sync.WaitGroup
1921

2022
isConnected bool
2123
}
2224

2325
func NewDockerService(
2426
log *logger.Logger,
2527
context context.Context,
28+
wg *sync.WaitGroup,
2629
) *DockerService {
2730
return &DockerService{
2831
log: log,
2932
context: context,
33+
wg: wg,
3034
}
3135
}
3236

@@ -53,7 +57,7 @@ func (docker *DockerService) Init() error {
5357
docker.isConnected = true
5458
docker.log.App.Debug().Msg("Docker connected successfully")
5559

56-
go docker.watchAndClose()
60+
docker.wg.Go(docker.watchAndClose)
5761

5862
return nil
5963
}

internal/service/kubernetes_service.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ type ingressApp struct {
3838
type KubernetesService struct {
3939
log *logger.Logger
4040
ctx context.Context
41+
wg *sync.WaitGroup
4142

4243
client dynamic.Interface
43-
cancel context.CancelFunc
4444
started bool
4545
mu sync.RWMutex
4646
ingressApps map[ingressKey][]ingressApp
@@ -51,10 +51,12 @@ type KubernetesService struct {
5151
func NewKubernetesService(
5252
log *logger.Logger,
5353
context context.Context,
54+
wg *sync.WaitGroup,
5455
) *KubernetesService {
5556
return &KubernetesService{
5657
log: log,
5758
ctx: context,
59+
wg: wg,
5860
ingressApps: make(map[ingressKey][]ingressApp),
5961
domainIndex: make(map[string]ingressAppKey),
6062
appNameIndex: make(map[string]ingressAppKey),
@@ -264,8 +266,6 @@ func (k *KubernetesService) Init() error {
264266
}
265267

266268
k.client = client
267-
k.ctx, k.cancel = context.WithCancel(k.ctx)
268-
269269
gvr := schema.GroupVersionResource{
270270
Group: "networking.k8s.io",
271271
Version: "v1",
@@ -274,6 +274,7 @@ func (k *KubernetesService) Init() error {
274274

275275
accessCtx, accessCancel := context.WithTimeout(k.ctx, 5*time.Second)
276276
defer accessCancel()
277+
277278
_, err = k.client.Resource(gvr).List(accessCtx, metav1.ListOptions{Limit: 1})
278279
if err != nil {
279280
k.log.App.Warn().Err(err).Str("api", gvr.GroupVersion().String()).Msg("Failed to access Ingress API, Kubernetes label provider will be disabled")
@@ -282,7 +283,9 @@ func (k *KubernetesService) Init() error {
282283
}
283284

284285
k.log.App.Debug().Str("api", gvr.GroupVersion().String()).Msg("Successfully accessed Ingress API, starting watcher")
285-
go k.watchGVR(gvr)
286+
k.wg.Go(func() {
287+
k.watchGVR(gvr)
288+
})
286289

287290
k.started = true
288291
k.log.App.Debug().Msg("Kubernetes label provider started successfully")

internal/service/ldap_service.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type LdapService struct {
1717
log *logger.Logger
1818
config model.Config
1919
context context.Context
20+
wg *sync.WaitGroup
2021

2122
conn *ldapgo.Conn
2223
mutex sync.RWMutex
@@ -28,11 +29,13 @@ func NewLdapService(
2829
log *logger.Logger,
2930
config model.Config,
3031
context context.Context,
32+
wg *sync.WaitGroup,
3133
) *LdapService {
3234
return &LdapService{
3335
log: log,
3436
config: config,
3537
context: context,
38+
wg: wg,
3639
}
3740
}
3841

@@ -88,7 +91,7 @@ func (ldap *LdapService) Init() error {
8891
return fmt.Errorf("failed to connect to LDAP server: %w", err)
8992
}
9093

91-
go func() {
94+
ldap.wg.Go(func() {
9295
ldap.log.App.Debug().Msg("Starting LDAP connection heartbeat routine")
9396

9497
ticker := time.NewTicker(5 * time.Minute)
@@ -111,7 +114,7 @@ func (ldap *LdapService) Init() error {
111114
return
112115
}
113116
}
114-
}()
117+
})
115118

116119
return nil
117120
}

internal/service/oidc_service.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"net/url"
1717
"os"
1818
"strings"
19+
"sync"
1920
"time"
2021

2122
"slices"
@@ -117,6 +118,7 @@ type OIDCService struct {
117118
runtime model.RuntimeConfig
118119
queries *repository.Queries
119120
context context.Context
121+
wg *sync.WaitGroup
120122

121123
clients map[string]model.OIDCClientConfig
122124
privateKey *rsa.PrivateKey
@@ -130,13 +132,15 @@ func NewOIDCService(
130132
config model.Config,
131133
runtime model.RuntimeConfig,
132134
queries *repository.Queries,
133-
context context.Context) *OIDCService {
135+
context context.Context,
136+
wg *sync.WaitGroup) *OIDCService {
134137
return &OIDCService{
135138
log: log,
136139
config: config,
137140
runtime: runtime,
138141
queries: queries,
139142
context: context,
143+
wg: wg,
140144
}
141145
}
142146

@@ -281,7 +285,7 @@ func (service *OIDCService) Init() error {
281285
}
282286

283287
// Start cleanup routine
284-
go service.cleanupRoutine()
288+
service.wg.Go(service.cleanupRoutine)
285289

286290
return nil
287291
}
@@ -811,7 +815,7 @@ func (service *OIDCService) cleanupRoutine() {
811815

812816
service.log.App.Debug().Msg("Finished OIDC cleanup routine")
813817
case <-service.context.Done():
814-
service.log.App.Debug().Msg("OIDC cleanup routine context cancelled, stopping")
818+
service.log.App.Debug().Msg("Stopping OIDC cleanup routine")
815819
return
816820
}
817821
}

0 commit comments

Comments
 (0)