@@ -10,7 +10,12 @@ import (
10
10
11
11
// manages set of AMQP channels
12
12
type chanPool struct {
13
- mu sync.Mutex
13
+ // timeout to backoff redial
14
+ tout time.Duration
15
+ url string
16
+
17
+ mu sync.Mutex
18
+
14
19
conn * amqp.Connection
15
20
channels map [string ]* channel
16
21
wait chan interface {}
@@ -19,35 +24,39 @@ type chanPool struct {
19
24
20
25
// manages single channel
21
26
type channel struct {
22
- ch * amqp.Channel
27
+ ch * amqp.Channel
23
28
// todo unused
24
29
//consumer string
25
- confirm chan amqp.Confirmation
26
- signal chan error
30
+ confirm chan amqp.Confirmation
31
+ signal chan error
27
32
}
28
33
29
- type dialer func () (* amqp.Connection , error )
30
-
31
34
// newConn creates new watched AMQP connection
32
- func newConn (dial dialer , tout time.Duration ) (* chanPool , error ) {
33
- conn , err := dial ()
35
+ func newConn (url string , tout time.Duration ) (* chanPool , error ) {
36
+ conn , err := dial (url )
34
37
if err != nil {
35
38
return nil , err
36
39
}
37
40
38
41
cp := & chanPool {
42
+ url : url ,
43
+ tout : tout ,
39
44
conn : conn ,
40
45
channels : make (map [string ]* channel ),
41
46
wait : make (chan interface {}),
42
47
connected : make (chan interface {}),
43
48
}
44
49
45
50
close (cp .connected )
46
- go cp .watch (dial , conn .NotifyClose (make (chan * amqp.Error )))
47
-
51
+ go cp .watch ()
48
52
return cp , nil
49
53
}
50
54
55
+ // dial dials to AMQP.
56
+ func dial (url string ) (* amqp.Connection , error ) {
57
+ return amqp .Dial (url )
58
+ }
59
+
51
60
// Close gracefully closes all underlying channels and connection.
52
61
func (cp * chanPool ) Close () error {
53
62
cp .mu .Lock ()
@@ -91,14 +100,16 @@ func (cp *chanPool) waitConnected() chan interface{} {
91
100
}
92
101
93
102
// watch manages connection state and reconnects if needed
94
- func (cp * chanPool ) watch (dial dialer , errors chan * amqp. Error ) {
103
+ func (cp * chanPool ) watch () {
95
104
for {
96
105
select {
97
106
case <- cp .wait :
98
107
// connection has been closed
99
108
return
100
- case err := <- errors :
109
+ // here we are waiting for the errors from amqp connection
110
+ case err := <- cp .conn .NotifyClose (make (chan * amqp.Error )):
101
111
cp .mu .Lock ()
112
+ // clear connected, since connections are dead
102
113
cp .connected = make (chan interface {})
103
114
104
115
// broadcast error to all consume to let them for the tryReconnect
@@ -109,20 +120,20 @@ func (cp *chanPool) watch(dial dialer, errors chan *amqp.Error) {
109
120
// disable channel allocation while server is dead
110
121
cp .conn = nil
111
122
cp .channels = nil
112
- cp .mu .Unlock ()
113
123
114
124
// initialize the backoff
115
125
expb := backoff .NewExponentialBackOff ()
116
- expb .MaxInterval = DefaultMaxInterval
126
+ expb .MaxInterval = cp .tout
127
+ cp .mu .Unlock ()
117
128
118
- //reconnect function
129
+ // reconnect function
119
130
reconnect := func () error {
120
131
cp .mu .Lock ()
121
- defer cp .mu .Unlock ()
122
- conn , err := dial ()
132
+ conn , err := dial (cp .url )
123
133
if err != nil {
124
134
// still failing
125
135
fmt .Println (fmt .Sprintf ("error during the amqp dialing, %s" , err .Error ()))
136
+ cp .mu .Unlock ()
126
137
return err
127
138
}
128
139
@@ -134,18 +145,16 @@ func (cp *chanPool) watch(dial dialer, errors chan *amqp.Error) {
134
145
cp .conn = conn
135
146
// re-init the channels
136
147
cp .channels = make (map [string ]* channel )
137
- errors = cp .conn . NotifyClose ( make ( chan * amqp. Error ) )
148
+ cp .mu . Unlock ( )
138
149
return nil
139
150
}
140
151
141
-
152
+ // start backoff retry
142
153
errb := backoff .Retry (reconnect , expb )
143
154
if errb != nil {
144
155
fmt .Println (fmt .Sprintf ("backoff Retry error, %s" , errb .Error ()))
145
156
// reconnection failed
146
- cp .mu .Lock ()
147
157
close (cp .connected )
148
- cp .mu .Unlock ()
149
158
return
150
159
}
151
160
close (cp .connected )
@@ -162,7 +171,7 @@ func (cp *chanPool) channel(name string) (*channel, error) {
162
171
if dead {
163
172
// wait for connection restoration (doubled the timeout duration)
164
173
select {
165
- case <- time .NewTimer (DefaultMaxInterval * 2 ).C :
174
+ case <- time .NewTimer (cp . tout * 2 ).C :
166
175
return nil , fmt .Errorf ("connection is dead" )
167
176
case <- cp .connected :
168
177
// connected
0 commit comments