@@ -93,9 +93,10 @@ const subConnCacheTime = time.Second * 10
9393// lbCacheClientConn is a wrapper balancer.ClientConn with a SubConn cache.
9494// SubConns will be kept in cache for subConnCacheTime before being removed.
9595//
96- // Its new and remove methods are updated to do cache first.
96+ // Its NewSubconn and SubConn.Shutdown methods are updated to do cache first.
9797type lbCacheClientConn struct {
98- cc balancer.ClientConn
98+ balancer.ClientConn
99+
99100 timeout time.Duration
100101
101102 mu sync.Mutex
@@ -113,7 +114,7 @@ type subConnCacheEntry struct {
113114
114115func newLBCacheClientConn (cc balancer.ClientConn ) * lbCacheClientConn {
115116 return & lbCacheClientConn {
116- cc : cc ,
117+ ClientConn : cc ,
117118 timeout : subConnCacheTime ,
118119 subConnCache : make (map [resolver.Address ]* subConnCacheEntry ),
119120 subConnToAddr : make (map [balancer.SubConn ]resolver.Address ),
@@ -137,16 +138,27 @@ func (ccc *lbCacheClientConn) NewSubConn(addrs []resolver.Address, opts balancer
137138 return entry .sc , nil
138139 }
139140
140- scNew , err := ccc .cc .NewSubConn (addrs , opts )
141+ scNew , err := ccc .ClientConn .NewSubConn (addrs , opts )
141142 if err != nil {
142143 return nil , err
143144 }
145+ scNew = & lbCacheSubConn {SubConn : scNew , ccc : ccc }
144146
145147 ccc .subConnToAddr [scNew ] = addrWithoutAttrs
146148 return scNew , nil
147149}
148150
149151func (ccc * lbCacheClientConn ) RemoveSubConn (sc balancer.SubConn ) {
152+ sc .Shutdown ()
153+ }
154+
155+ type lbCacheSubConn struct {
156+ balancer.SubConn
157+ ccc * lbCacheClientConn
158+ }
159+
160+ func (sc * lbCacheSubConn ) Shutdown () {
161+ ccc := sc .ccc
150162 ccc .mu .Lock ()
151163 defer ccc .mu .Unlock ()
152164 addr , ok := ccc .subConnToAddr [sc ]
@@ -160,7 +172,7 @@ func (ccc *lbCacheClientConn) RemoveSubConn(sc balancer.SubConn) {
160172 // same address, and those SubConns are all removed. We remove sc
161173 // immediately here.
162174 delete (ccc .subConnToAddr , sc )
163- ccc . cc . RemoveSubConn ( sc )
175+ sc . SubConn . Shutdown ( )
164176 }
165177 return
166178 }
@@ -176,7 +188,7 @@ func (ccc *lbCacheClientConn) RemoveSubConn(sc balancer.SubConn) {
176188 if entry .abortDeleting {
177189 return
178190 }
179- ccc . cc . RemoveSubConn ( sc )
191+ sc . SubConn . Shutdown ( )
180192 delete (ccc .subConnToAddr , sc )
181193 delete (ccc .subConnCache , addr )
182194 })
@@ -195,14 +207,28 @@ func (ccc *lbCacheClientConn) RemoveSubConn(sc balancer.SubConn) {
195207}
196208
197209func (ccc * lbCacheClientConn ) UpdateState (s balancer.State ) {
198- ccc .cc .UpdateState (s )
210+ s .Picker = & lbCachePicker {Picker : s .Picker }
211+ ccc .ClientConn .UpdateState (s )
199212}
200213
201214func (ccc * lbCacheClientConn ) close () {
202215 ccc .mu .Lock ()
216+ defer ccc .mu .Unlock ()
203217 // Only cancel all existing timers. There's no need to remove SubConns.
204218 for _ , entry := range ccc .subConnCache {
205219 entry .cancel ()
206220 }
207- ccc .mu .Unlock ()
221+ }
222+
223+ type lbCachePicker struct {
224+ balancer.Picker
225+ }
226+
227+ func (cp * lbCachePicker ) Pick (i balancer.PickInfo ) (balancer.PickResult , error ) {
228+ res , err := cp .Picker .Pick (i )
229+ if err != nil {
230+ return res , err
231+ }
232+ res .SubConn = res .SubConn .(* lbCacheSubConn ).SubConn
233+ return res , nil
208234}
0 commit comments