func (t *Topology) apply(ctx context.Context, desc description.Server) description.Server {
	t.serversLock.Lock()
	defer t.serversLock.Unlock()
	ind, ok := t.fsm.findServer(desc.Addr)
	if t.serversClosed || !ok {
		return desc
	}
	prev := t.fsm.Topology
	oldDesc := t.fsm.Servers[ind]
	if oldDesc.TopologyVersion.CompareToIncoming(desc.TopologyVersion) > 0 {
		return oldDesc
	}
	var current description.Topology
	var err error
	current, desc, err = t.fsm.apply(desc)
	if err != nil {
		return desc
	}
	if !oldDesc.Equal(desc) {
		t.publishServerDescriptionChangedEvent(oldDesc, desc)
	}
	diff := diffTopology(prev, current)
	for _, removed := range diff.Removed {
		if s, ok := t.servers[removed.Addr]; ok {
			go func() {
				cancelCtx, cancel := context.WithCancel(ctx)
				cancel()
				_ = s.Disconnect(cancelCtx)
			}()
			delete(t.servers, removed.Addr)
			t.publishServerClosedEvent(s.address)
		}
	}
	for _, added := range diff.Added {
		_ = t.addServer(added.Addr)
	}
	t.desc.Store(current)
	if !prev.Equal(current) {
		t.publishTopologyDescriptionChangedEvent(prev, current)
	}
	t.subLock.Lock()
	for _, ch := range t.subscribers {
		select {
		case <-ch:
		default:
		}
		ch <- current
	}
	t.subLock.Unlock()
	return desc
}
apply updates the Topology and its underlying FSM based on the provided server description and returns the server
description that should be stored.
package topology  
import (
	"context"
	"errors"
	"math/rand"
	"strings"
	"sync"
	"sync/atomic"
	"time"
	"fmt"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/event"
	"go.mongodb.org/mongo-driver/mongo/address"
	"go.mongodb.org/mongo-driver/mongo/description"
	"go.mongodb.org/mongo-driver/x/mongo/driver"
	"go.mongodb.org/mongo-driver/x/mongo/driver/dns"
)
var ErrSubscribeAfterClosed = errors.New("cannot subscribe after closeConnection")
var ErrTopologyClosed = errors.New("topology is closed")
var ErrTopologyConnected = errors.New("topology is connected or connecting")
var ErrServerSelectionTimeout = errors.New("server selection timeout")
type MonitorMode uint8
const (
	AutomaticMode MonitorMode = iota
	SingleMode
)
type Topology struct {
	connectionstate int32
	cfg *config
	desc atomic.Value  
	dnsResolver *dns.Resolver
	done chan struct{}
	pollingRequired   bool
	pollingDone       chan struct{}
	pollingwg         sync.WaitGroup
	rescanSRVInterval time.Duration
	pollHeartbeatTime atomic.Value  
	updateCallback updateTopologyCallback
	fsm            *fsm
	subscribers         map[uint64]chan description.Topology
	currentSubscriberID uint64
	subscriptionsClosed bool
	subLock             sync.Mutex
	serversLock   sync.Mutex
	serversClosed bool
	servers       map[address.Address]*Server
	id primitive.ObjectID
}
var _ driver.Deployment = &Topology{}
var _ driver.Subscriber = &Topology{}
type serverSelectionState struct {
	selector    description.ServerSelector
	timeoutChan <-chan time.Time
}
func newServerSelectionState(selector description.ServerSelector, timeoutChan <-chan time.Time) serverSelectionState {
	return serverSelectionState{
		selector:    selector,
		timeoutChan: timeoutChan,
	}
}
func New(opts ...Option) (*Topology, error) {
	cfg, err := newConfig(opts...)
	if err != nil {
		return nil, err
	}
	t := &Topology{
		cfg:               cfg,
		done:              make(chan struct{}),
		pollingDone:       make(chan struct{}),
		rescanSRVInterval: 60 * time.Second,
		fsm:               newFSM(),
		subscribers:       make(map[uint64]chan description.Topology),
		servers:           make(map[address.Address]*Server),
		dnsResolver:       dns.DefaultResolver,
		id:                primitive.NewObjectID(),
	}
	t.desc.Store(description.Topology{})
	t.updateCallback = func(desc description.Server) description.Server {
		return t.apply(context.TODO(), desc)
	}
	if t.cfg.uri != "" {
		t.pollingRequired = strings.HasPrefix(t.cfg.uri, "mongodb+srv://")
	}
	t.publishTopologyOpeningEvent()
	return t, nil
}
func (t *Topology) Connect() error {
	if !atomic.CompareAndSwapInt32(&t.connectionstate, disconnected, connecting) {
		return ErrTopologyConnected
	}
	t.desc.Store(description.Topology{})
	var err error
	t.serversLock.Lock()
	if t.cfg.replicaSetName != "" {
		t.fsm.SetName = t.cfg.replicaSetName
		t.fsm.Kind = description.ReplicaSetNoPrimary
	}
	if t.cfg.mode == SingleMode {
		t.fsm.Kind = description.Single
	}
	for _, a := range t.cfg.seedList {
		addr := address.Address(a).Canonicalize()
		t.fsm.Servers = append(t.fsm.Servers, description.NewDefaultServer(addr))
	}
	newDesc := description.Topology{
		Kind:                  t.fsm.Kind,
		Servers:               t.fsm.Servers,
		SessionTimeoutMinutes: t.fsm.SessionTimeoutMinutes,
	}
	t.desc.Store(newDesc)
	t.publishTopologyDescriptionChangedEvent(description.Topology{}, t.fsm.Topology)
	for _, a := range t.cfg.seedList {
		addr := address.Address(a).Canonicalize()
		err = t.addServer(addr)
		if err != nil {
			return err
		}
	}
	t.serversLock.Unlock()
	if t.pollingRequired {
		go t.pollSRVRecords()
		t.pollingwg.Add(1)
	}
	t.subscriptionsClosed = false  
	atomic.StoreInt32(&t.connectionstate, connected)
	return nil
}
func (t *Topology) Disconnect(ctx context.Context) error {
	if !atomic.CompareAndSwapInt32(&t.connectionstate, connected, disconnecting) {
		return ErrTopologyClosed
	}
	servers := make(map[address.Address]*Server)
	t.serversLock.Lock()
	t.serversClosed = true
	for addr, server := range t.servers {
		servers[addr] = server
	}
	t.serversLock.Unlock()
	for _, server := range servers {
		_ = server.Disconnect(ctx)
		t.publishServerClosedEvent(server.address)
	}
	t.subLock.Lock()
	for id, ch := range t.subscribers {
		close(ch)
		delete(t.subscribers, id)
	}
	t.subscriptionsClosed = true
	t.subLock.Unlock()
	if t.pollingRequired {
		t.pollingDone <- struct{}{}
		t.pollingwg.Wait()
	}
	t.desc.Store(description.Topology{})
	atomic.StoreInt32(&t.connectionstate, disconnected)
	t.publishTopologyClosedEvent()
	return nil
}
func (t *Topology) Description() description.Topology {
	td, ok := t.desc.Load().(description.Topology)
	if !ok {
		td = description.Topology{}
	}
	return td
}
func (t *Topology) Kind() description.TopologyKind { return t.Description().Kind }
func (t *Topology) Subscribe() (*driver.Subscription, error) {
	if atomic.LoadInt32(&t.connectionstate) != connected {
		return nil, errors.New("cannot subscribe to Topology that is not connected")
	}
	ch := make(chan description.Topology, 1)
	td, ok := t.desc.Load().(description.Topology)
	if !ok {
		td = description.Topology{}
	}
	ch <- td
	t.subLock.Lock()
	defer t.subLock.Unlock()
	if t.subscriptionsClosed {
		return nil, ErrSubscribeAfterClosed
	}
	id := t.currentSubscriberID
	t.subscribers[id] = ch
	t.currentSubscriberID++
	return &driver.Subscription{
		Updates: ch,
		ID:      id,
	}, nil
}
func (t *Topology) Unsubscribe(sub *driver.Subscription) error {
	t.subLock.Lock()
	defer t.subLock.Unlock()
	if t.subscriptionsClosed {
		return nil
	}
	ch, ok := t.subscribers[sub.ID]
	if !ok {
		return nil
	}
	close(ch)
	delete(t.subscribers, sub.ID)
	return nil
}
func (t *Topology) RequestImmediateCheck() {
	if atomic.LoadInt32(&t.connectionstate) != connected {
		return
	}
	t.serversLock.Lock()
	for _, server := range t.servers {
		server.RequestImmediateCheck()
	}
	t.serversLock.Unlock()
}
func (t *Topology) SelectServer(ctx context.Context, ss description.ServerSelector) (driver.Server, error) {
	if atomic.LoadInt32(&t.connectionstate) != connected {
		return nil, ErrTopologyClosed
	}
	var ssTimeoutCh <-chan time.Time
	if t.cfg.serverSelectionTimeout > 0 {
		ssTimeout := time.NewTimer(t.cfg.serverSelectionTimeout)
		ssTimeoutCh = ssTimeout.C
		defer ssTimeout.Stop()
	}
	var doneOnce bool
	var sub *driver.Subscription
	selectionState := newServerSelectionState(ss, ssTimeoutCh)
	for {
		var suitable []description.Server
		var selectErr error
		if !doneOnce {
			suitable, selectErr = t.selectServerFromDescription(t.Description(), selectionState)
			doneOnce = true
		} else {
			if sub == nil {
				var err error
				sub, err = t.Subscribe()
				if err != nil {
					return nil, err
				}
				defer t.Unsubscribe(sub)
			}
			suitable, selectErr = t.selectServerFromSubscription(ctx, sub.Updates, selectionState)
		}
		if selectErr != nil {
			return nil, selectErr
		}
		if len(suitable) == 0 {
			continue
		}
		selected := suitable[rand.Intn(len(suitable))]
		selectedS, err := t.FindServer(selected)
		switch {
		case err != nil:
			return nil, err
		case selectedS != nil:
			return selectedS, nil
		default:
		}
	}
}
func (t *Topology) SelectServerLegacy(ctx context.Context, ss description.ServerSelector) (*SelectedServer, error) {
	if atomic.LoadInt32(&t.connectionstate) != connected {
		return nil, ErrTopologyClosed
	}
	var ssTimeoutCh <-chan time.Time
	if t.cfg.serverSelectionTimeout > 0 {
		ssTimeout := time.NewTimer(t.cfg.serverSelectionTimeout)
		ssTimeoutCh = ssTimeout.C
		defer ssTimeout.Stop()
	}
	sub, err := t.Subscribe()
	if err != nil {
		return nil, err
	}
	defer t.Unsubscribe(sub)
	selectionState := newServerSelectionState(ss, ssTimeoutCh)
	for {
		suitable, err := t.selectServerFromSubscription(ctx, sub.Updates, selectionState)
		if err != nil {
			return nil, err
		}
		selected := suitable[rand.Intn(len(suitable))]
		selectedS, err := t.FindServer(selected)
		switch {
		case err != nil:
			return nil, err
		case selectedS != nil:
			return selectedS, nil
		default:
		}
	}
}
func (t *Topology) FindServer(selected description.Server) (*SelectedServer, error) {
	if atomic.LoadInt32(&t.connectionstate) != connected {
		return nil, ErrTopologyClosed
	}
	t.serversLock.Lock()
	defer t.serversLock.Unlock()
	server, ok := t.servers[selected.Addr]
	if !ok {
		return nil, nil
	}
	desc := t.Description()
	return &SelectedServer{
		Server: server,
		Kind:   desc.Kind,
	}, nil
}
func (t *Topology) selectServerFromSubscription(ctx context.Context, subscriptionCh <-chan description.Topology,
	selectionState serverSelectionState) ([]description.Server, error) {
	current := t.Description()
	for {
		select {
		case <-ctx.Done():
			return nil, ServerSelectionError{Wrapped: ctx.Err(), Desc: current}
		case <-selectionState.timeoutChan:
			return nil, ServerSelectionError{Wrapped: ErrServerSelectionTimeout, Desc: current}
		case current = <-subscriptionCh:
		}
		suitable, err := t.selectServerFromDescription(current, selectionState)
		if err != nil {
			return nil, err
		}
		if len(suitable) > 0 {
			return suitable, nil
		}
		t.RequestImmediateCheck()
	}
}
func (t *Topology) selectServerFromDescription(desc description.Topology,
	selectionState serverSelectionState) ([]description.Server, error) {
	if desc.CompatibilityErr != nil {
		return nil, desc.CompatibilityErr
	}
	var allowed []description.Server
	for _, s := range desc.Servers {
		if s.Kind != description.Unknown {
			allowed = append(allowed, s)
		}
	}
	suitable, err := selectionState.selector.SelectServer(desc, allowed)
	if err != nil {
		return nil, ServerSelectionError{Wrapped: err, Desc: desc}
	}
	return suitable, nil
}
func (t *Topology) pollSRVRecords() {
	defer t.pollingwg.Done()
	serverConfig, _ := newServerConfig(t.cfg.serverOpts...)
	heartbeatInterval := serverConfig.heartbeatInterval
	pollTicker := time.NewTicker(t.rescanSRVInterval)
	defer pollTicker.Stop()
	t.pollHeartbeatTime.Store(false)
	var doneOnce bool
	defer func() {
		if r := recover(); r != nil && !doneOnce {
			<-t.pollingDone
		}
	}()
	uri := t.cfg.uri[14:]
	hosts := uri
	if idx := strings.IndexAny(uri, "/?@"); idx != -1 {
		hosts = uri[:idx]
	}
	for {
		select {
		case <-pollTicker.C:
		case <-t.pollingDone:
			doneOnce = true
			return
		}
		topoKind := t.Description().Kind
		if !(topoKind == description.Unknown || topoKind == description.Sharded) {
			break
		}
		parsedHosts, err := t.dnsResolver.ParseHosts(hosts, false)
		if err != nil || len(parsedHosts) == 0 {
			if !t.pollHeartbeatTime.Load().(bool) {
				pollTicker.Stop()
				pollTicker = time.NewTicker(heartbeatInterval)
				t.pollHeartbeatTime.Store(true)
			}
			continue
		}
		if t.pollHeartbeatTime.Load().(bool) {
			pollTicker.Stop()
			pollTicker = time.NewTicker(t.rescanSRVInterval)
			t.pollHeartbeatTime.Store(false)
		}
		cont := t.processSRVResults(parsedHosts)
		if !cont {
			break
		}
	}
	<-t.pollingDone
	doneOnce = true
}
func (t *Topology) processSRVResults(parsedHosts []string) bool {
	t.serversLock.Lock()
	defer t.serversLock.Unlock()
	if t.serversClosed {
		return false
	}
	prev := t.fsm.Topology
	diff := diffHostList(t.fsm.Topology, parsedHosts)
	if len(diff.Added) == 0 && len(diff.Removed) == 0 {
		return true
	}
	for _, r := range diff.Removed {
		addr := address.Address(r).Canonicalize()
		s, ok := t.servers[addr]
		if !ok {
			continue
		}
		go func() {
			cancelCtx, cancel := context.WithCancel(context.Background())
			cancel()
			_ = s.Disconnect(cancelCtx)
		}()
		delete(t.servers, addr)
		t.fsm.removeServerByAddr(addr)
		t.publishServerClosedEvent(s.address)
	}
	for _, a := range diff.Added {
		addr := address.Address(a).Canonicalize()
		_ = t.addServer(addr)
		t.fsm.addServer(addr)
	}
	newDesc := description.Topology{
		Kind:                  t.fsm.Kind,
		Servers:               t.fsm.Servers,
		SessionTimeoutMinutes: t.fsm.SessionTimeoutMinutes,
	}
	t.desc.Store(newDesc)
	if !prev.Equal(newDesc) {
		t.publishTopologyDescriptionChangedEvent(prev, newDesc)
	}
	t.subLock.Lock()
	for _, ch := range t.subscribers {
		select {
		case <-ch:
		default:
		}
		ch <- newDesc
	}
	t.subLock.Unlock()
	return true
}