-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlistener.go
87 lines (78 loc) · 1.71 KB
/
listener.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package dominoes
import (
"context"
"io"
)
type linkedListener struct {
current Listener
next Listener
ctx context.Context
shutdown context.CancelFunc
managed []io.Closer
logger logger
}
func newListener(config configuration) ListenCloser {
if len(config.listeners) == 0 {
return nil
}
current := config.listeners[0]
if current == nil {
panic("nil listener")
}
ctx, shutdown := context.WithCancel(context.Background())
config.listeners = config.listeners[1:]
managed := config.managed
if len(config.listeners) > 0 {
managed = nil
}
return &linkedListener{
ctx: ctx,
shutdown: shutdown,
current: current,
next: newListener(config),
managed: managed,
logger: config.logger,
}
}
func (this *linkedListener) Listen() {
if this.isLast() {
this.listen()
} else {
go this.listen()
this.next.Listen()
}
}
func (this *linkedListener) listen() {
defer this.onListenComplete()
this.current.Listen()
<-this.ctx.Done()
closeListener(this.next) // current just completed, now cause the next in line to conclude (if one exists)
}
func (this *linkedListener) onListenComplete() {
if !this.isLast() {
return
}
CloseResources(this.managed...)
this.managed = this.managed[0:0]
this.logger.Printf("[INFO] All listeners have concluded.")
}
func (this *linkedListener) isLast() bool {
return this.next == nil
}
func (this *linkedListener) Close() error {
defer this.shutdown()
closeListener(this.current)
return nil
}
func closeListener(listener any) {
if resource, ok := listener.(io.Closer); ok {
CloseResources(resource)
}
}
func CloseResources(resources ...io.Closer) {
for _, resource := range resources {
if resource != nil {
_ = resource.Close()
}
}
}