@@ -63,9 +63,7 @@ type Topology struct {
63
63
64
64
done chan struct {}
65
65
66
- fsm * fsm
67
- changes chan description.Server
68
- changeswg sync.WaitGroup
66
+ fsm * fsm
69
67
70
68
SessionPool * session.Pool
71
69
@@ -84,8 +82,6 @@ type Topology struct {
84
82
serversLock sync.Mutex
85
83
serversClosed bool
86
84
servers map [address.Address ]* Server
87
-
88
- wg sync.WaitGroup
89
85
}
90
86
91
87
// New creates a new topology.
@@ -99,7 +95,6 @@ func New(opts ...Option) (*Topology, error) {
99
95
cfg : cfg ,
100
96
done : make (chan struct {}),
101
97
fsm : newFSM (),
102
- changes : make (chan description.Server ),
103
98
subscribers : make (map [uint64 ]chan description.Topology ),
104
99
servers : make (map [address.Address ]* Server ),
105
100
}
@@ -134,9 +129,6 @@ func (t *Topology) Connect(ctx context.Context) error {
134
129
}
135
130
t .serversLock .Unlock ()
136
131
137
- go t .update ()
138
- t .changeswg .Add (1 )
139
-
140
132
t .subscriptionsClosed = false // explicitly set in case topology was disconnected and then reconnected
141
133
142
134
atomic .StoreInt32 (& t .connectionstate , connected )
@@ -154,16 +146,25 @@ func (t *Topology) Disconnect(ctx context.Context) error {
154
146
return ErrTopologyClosed
155
147
}
156
148
149
+ servers := make (map [address.Address ]* Server )
157
150
t .serversLock .Lock ()
158
151
t .serversClosed = true
159
152
for addr , server := range t .servers {
160
- t . removeServer ( ctx , addr , server )
153
+ servers [ addr ] = server
161
154
}
162
155
t .serversLock .Unlock ()
163
156
164
- t .wg .Wait ()
165
- t .done <- struct {}{}
166
- t .changeswg .Wait ()
157
+ for _ , server := range servers {
158
+ _ = server .Disconnect (ctx )
159
+ }
160
+
161
+ t .subLock .Lock ()
162
+ for id , ch := range t .subscribers {
163
+ close (ch )
164
+ delete (t .subscribers , id )
165
+ }
166
+ t .subscriptionsClosed = true
167
+ t .subLock .Unlock ()
167
168
168
169
t .desc .Store (description.Topology {})
169
170
@@ -328,110 +329,73 @@ func (t *Topology) selectServer(ctx context.Context, subscriptionCh <-chan descr
328
329
}
329
330
}
330
331
331
- func (t * Topology ) update () {
332
- defer t .changeswg .Done ()
333
- defer func () {
334
- // ¯\_(ツ)_/¯
335
- if r := recover (); r != nil {
336
- <- t .done
337
- }
338
- }()
332
+ func (t * Topology ) apply (ctx context.Context , desc description.Server ) {
333
+ var err error
339
334
340
- for {
341
- select {
342
- case change := <- t .changes :
343
- current , err := t .apply (context .TODO (), change )
344
- if err != nil {
345
- continue
346
- }
335
+ t .serversLock .Lock ()
336
+ defer t .serversLock .Unlock ()
347
337
348
- t .desc .Store (current )
349
- t .subLock .Lock ()
350
- for _ , ch := range t .subscribers {
351
- // We drain the description if there's one in the channel
352
- select {
353
- case <- ch :
354
- default :
355
- }
356
- ch <- current
357
- }
358
- t .subLock .Unlock ()
359
- case <- t .done :
360
- t .subLock .Lock ()
361
- for id , ch := range t .subscribers {
362
- close (ch )
363
- delete (t .subscribers , id )
364
- }
365
- t .subscriptionsClosed = true
366
- t .subLock .Unlock ()
367
- return
368
- }
338
+ if _ , ok := t .servers [desc .Addr ]; t .serversClosed || ! ok {
339
+ return
369
340
}
370
- }
371
341
372
- func (t * Topology ) apply (ctx context.Context , desc description.Server ) (description.Topology , error ) {
373
- var err error
374
342
prev := t .fsm .Topology
375
343
376
344
current , err := t .fsm .apply (desc )
377
345
if err != nil {
378
- return description. Topology {}, err
346
+ return
379
347
}
380
348
381
349
diff := description .DiffTopology (prev , current )
382
- t .serversLock .Lock ()
383
- if t .serversClosed {
384
- t .serversLock .Unlock ()
385
- return description.Topology {}, nil
386
- }
387
350
388
351
for _ , removed := range diff .Removed {
389
352
if s , ok := t .servers [removed .Addr ]; ok {
390
- t .removeServer (ctx , removed .Addr , s )
353
+ go func () {
354
+ cancelCtx , cancel := context .WithCancel (ctx )
355
+ cancel ()
356
+ _ = s .Disconnect (cancelCtx )
357
+ }()
358
+ delete (t .servers , removed .Addr )
391
359
}
392
360
}
393
361
394
362
for _ , added := range diff .Added {
395
363
_ = t .addServer (ctx , added .Addr )
396
364
}
397
- t .serversLock .Unlock ()
398
- return current , nil
365
+
366
+ t .desc .Store (current )
367
+
368
+ t .subLock .Lock ()
369
+ for _ , ch := range t .subscribers {
370
+ // We drain the description if there's one in the channel
371
+ select {
372
+ case <- ch :
373
+ default :
374
+ }
375
+ ch <- current
376
+ }
377
+ t .subLock .Unlock ()
378
+
399
379
}
400
380
401
381
func (t * Topology ) addServer (ctx context.Context , addr address.Address ) error {
402
382
if _ , ok := t .servers [addr ]; ok {
403
383
return nil
404
384
}
405
385
406
- svr , err := ConnectServer (ctx , addr , t .cfg .serverOpts ... )
407
- if err != nil {
408
- return err
386
+ topoFunc := func (desc description.Server ) {
387
+ t .apply (context .TODO (), desc )
409
388
}
410
-
411
- t .servers [addr ] = svr
412
- var sub * ServerSubscription
413
- sub , err = svr .Subscribe ()
389
+ svr , err := ConnectServer (ctx , addr , topoFunc , t .cfg .serverOpts ... )
414
390
if err != nil {
415
391
return err
416
392
}
417
393
418
- t .wg .Add (1 )
419
- go func () {
420
- for c := range sub .C {
421
- t .changes <- c
422
- }
423
-
424
- t .wg .Done ()
425
- }()
394
+ t .servers [addr ] = svr
426
395
427
396
return nil
428
397
}
429
398
430
- func (t * Topology ) removeServer (ctx context.Context , addr address.Address , server * Server ) {
431
- _ = server .Disconnect (ctx )
432
- delete (t .servers , addr )
433
- }
434
-
435
399
// String implements the Stringer interface
436
400
func (t * Topology ) String () string {
437
401
desc := t .Description ()
0 commit comments