Skip to content

Commit b376185

Browse files
committed
(BC) closer.New with options that allow implicit CloseAll call +
golangci-lint v2
1 parent 11980f8 commit b376185

10 files changed

Lines changed: 1477 additions & 1312 deletions

File tree

.github/workflows/actions.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ permissions:
1111

1212
env:
1313
GO_VERSION: stable
14-
GOLANGCI_LINT_VERSION: v1.64.8
14+
GOLANGCI_LINT_VERSION: v2.1.6
1515

1616
jobs:
1717
detect-modules:
@@ -40,7 +40,7 @@ jobs:
4040
with:
4141
go-version: ${{ env.GO_VERSION }}
4242
- name: golangci-lint ${{ matrix.module }}
43-
uses: golangci/golangci-lint-action@v6
43+
uses: golangci/golangci-lint-action@v8
4444
with:
4545
version: ${{ env.GOLANGCI_LINT_VERSION }}
4646
working-directory: ${{ matrix.module }}

closer/.golangci.yml

Lines changed: 231 additions & 215 deletions
Large diffs are not rendered by default.

closer/closer.go

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package closer
55
import (
66
"context"
77
"errors"
8-
"os"
98
"os/signal"
109
"sync"
1110
"sync/atomic"
@@ -62,29 +61,34 @@ func CloseAll() {
6261
global.CloseAll()
6362
}
6463

65-
// New returns signal notifiable Context and base Closer implementation.
66-
//
67-
// If signals specified, then close functions will trigger when any arrives.
68-
func New(ctx context.Context, signals ...os.Signal) (context.Context, *closer) {
64+
// New returns Closer implementation.
65+
func New(ctx context.Context, opts ...Option) (context.Context, *closer) {
66+
o := options{}
67+
for _, opt := range opts {
68+
opt(&o)
69+
}
70+
71+
var cancel context.CancelFunc
72+
if len(o.signals) > 0 {
73+
ctx, cancel = signal.NotifyContext(ctx, o.signals...)
74+
}
75+
6976
c := &closer{done: make(chan struct{})}
7077
if ctx == nil {
7178
panic("cannot create closer with nil context")
7279
}
7380
c.ctx.Store(&ctx)
7481

75-
var cancel context.CancelFunc
76-
if len(signals) > 0 {
77-
ctx, cancel = signal.NotifyContext(ctx, signals...)
78-
}
79-
80-
go func() {
81-
if cancel != nil {
82-
defer cancel()
83-
}
82+
if o.ctxCancel {
83+
go func() {
84+
if cancel != nil {
85+
defer cancel()
86+
}
8487

85-
<-ctx.Done()
86-
c.CloseAll() //nolint:contextcheck
87-
}()
88+
<-ctx.Done()
89+
c.CloseAll() //nolint:contextcheck
90+
}()
91+
}
8892

8993
return ctx, c
9094
}

closer/closer_test.go

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ package closer_test
55
import (
66
"context"
77
"errors"
8+
"os"
89
"sync"
910
"sync/atomic"
11+
"syscall"
1012
"testing"
1113

1214
. "github.com/nbgrp/pkg/closer"
@@ -39,11 +41,11 @@ func TestCloser(t *testing.T) {
3941
wg.Wait()
4042
})
4143

42-
t.Run("with cancel", func(t *testing.T) {
44+
t.Run("with context cancel", func(t *testing.T) {
4345
goleak.VerifyNone(t, goleak.IgnoreCurrent())
4446

4547
ctx, cancel := context.WithCancel(context.Background())
46-
_, c := New(ctx)
48+
_, c := New(ctx, WithContextCancel())
4749

4850
var cnt atomic.Uint32
4951
c.Add(func(context.Context) error {
@@ -74,7 +76,36 @@ func TestCloser(t *testing.T) {
7476
cancel()
7577
wg.Wait()
7678

77-
c.CloseAll()
79+
assert.Equal(t, uint32(2), cnt.Load())
80+
})
81+
82+
t.Run("with signals", func(t *testing.T) {
83+
goleak.VerifyNone(t, goleak.IgnoreCurrent())
84+
85+
ctx := context.Background()
86+
_, c := New(ctx, WithSignals(syscall.SIGINT, syscall.SIGTERM))
87+
88+
var cnt atomic.Uint32
89+
c.Add(func(context.Context) error {
90+
cnt.Add(1)
91+
return nil
92+
})
93+
c.Add(func(context.Context) error {
94+
cnt.Add(1)
95+
return nil
96+
})
97+
98+
wg := sync.WaitGroup{}
99+
wg.Add(1)
100+
go func() {
101+
<-c.Done()
102+
wg.Done()
103+
}()
104+
105+
err := syscall.Kill(os.Getpid(), syscall.SIGTERM)
106+
assert.NoError(t, err)
107+
108+
wg.Wait()
78109

79110
assert.Equal(t, uint32(2), cnt.Load())
80111
})

closer/options.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
3+
package closer
4+
5+
import (
6+
"os"
7+
)
8+
9+
type options struct {
10+
signals []os.Signal
11+
ctxCancel bool
12+
}
13+
14+
type Option func(*options)
15+
16+
// WithContextCancel allows to call closer CloseAll on context cancel implicitly.
17+
func WithContextCancel() Option {
18+
return func(o *options) {
19+
o.ctxCancel = true
20+
}
21+
}
22+
23+
// WithSignals will trigger creation of signal notifiable context.
24+
// The closer CloseAll will be called implicitly when any of the specified signals arrives.
25+
func WithSignals(signals ...os.Signal) Option {
26+
return func(o *options) {
27+
o.ctxCancel = true
28+
if o.signals == nil {
29+
o.signals = signals
30+
return
31+
}
32+
o.signals = append(o.signals, signals...)
33+
}
34+
}

0 commit comments

Comments
 (0)