@@ -214,6 +214,7 @@ type ringShards struct {
214
214
opt * RingOptions
215
215
216
216
mu sync.RWMutex
217
+ muClose sync.Mutex
217
218
hash ConsistentHash
218
219
shards map [string ]* ringShard // read only, updated by SetAddrs
219
220
list []* ringShard // read only, updated by SetAddrs
@@ -230,36 +231,30 @@ func newRingShards(opt *RingOptions) *ringShards {
230
231
return c
231
232
}
232
233
233
- // SetAddrs must not be called concurrently.
234
+ // SetAddrs replaces the shards in use, such that you can increase and
235
+ // decrease number of shards, that you use. It will reuse shards that
236
+ // existed before and close the ones that will not be used anymore.
234
237
func (c * ringShards ) SetAddrs (addrs map [string ]string ) {
235
- shards := make (map [string ]* ringShard )
238
+ c .muClose .Lock ()
239
+ defer c .muClose .Unlock ()
236
240
if c .closed {
237
241
return
238
242
}
239
243
244
+ shards := make (map [string ]* ringShard )
245
+ unusedShards := make (map [string ]* ringShard )
246
+
240
247
for k , shard := range c .shards {
241
248
if addr , ok := addrs [k ]; ok && shard .addr == addr {
242
249
shards [k ] = shard
243
250
} else {
244
- // close shards that are not reused
245
- defer func () {
246
- c .mu .Lock ()
247
- if ! c .closed {
248
- err := shard .Client .Close ()
249
- if err != nil {
250
- internal .Logger .Printf (context .Background (), "Failed to close ring shard client %s %s: %v" , k , shard .addr , err )
251
- }
252
- }
253
- c .mu .Unlock ()
254
- }()
251
+ unusedShards [k ] = shard
255
252
}
256
253
}
257
254
258
- newShardNames := make ([]string , 0 )
259
255
for k , addr := range addrs {
260
256
if shard , ok := c .shards [k ]; ! ok || shard .addr != addr {
261
257
shards [k ] = newRingShard (c .opt , k , addr )
262
- newShardNames = append (newShardNames , k )
263
258
}
264
259
}
265
260
@@ -269,15 +264,16 @@ func (c *ringShards) SetAddrs(addrs map[string]string) {
269
264
}
270
265
271
266
c .mu .Lock ()
272
- if c .closed {
273
- for _ , k := range newShardNames {
274
- shards [k ].Client .Close ()
267
+ c .shards = shards
268
+ c .list = list
269
+ c .mu .Unlock ()
270
+
271
+ for k , shard := range unusedShards {
272
+ err := shard .Client .Close ()
273
+ if err != nil {
274
+ internal .Logger .Printf (context .Background (), "Failed to close ring shard client %s %s: %v" , k , shard .addr , err )
275
275
}
276
- } else {
277
- c .shards = shards
278
- c .list = list
279
276
}
280
- c .mu .Unlock ()
281
277
282
278
c .rebalance ()
283
279
}
@@ -404,6 +400,8 @@ func (c *ringShards) Len() int {
404
400
}
405
401
406
402
func (c * ringShards ) Close () error {
403
+ c .muClose .Lock ()
404
+ defer c .muClose .Unlock ()
407
405
c .mu .Lock ()
408
406
defer c .mu .Unlock ()
409
407
0 commit comments