SetServerPool allows updating the server pool for the connection. This replaces the existing pool with the provided list of server URLs. If the current server is not in the new pool, the client will switch to a server in the new pool on the next reconnect attempt. This function is thread-safe and ca
(servers []string)
| 6409 | // This function should not be called from within connection callbacks to avoid |
| 6410 | // potential deadlocks. |
| 6411 | func (nc *Conn) SetServerPool(servers []string) error { |
| 6412 | nc.mu.Lock() |
| 6413 | defer nc.mu.Unlock() |
| 6414 | if nc.isClosed() { |
| 6415 | return ErrConnectionClosed |
| 6416 | } |
| 6417 | |
| 6418 | // Parse and validate all URLs first (without modifying state) |
| 6419 | newPool := make([]*Server, 0, len(servers)) |
| 6420 | newURLs := make(map[string]struct{}) |
| 6421 | |
| 6422 | for _, addr := range servers { |
| 6423 | s, err := nc.parseServerURL(addr, false, false) |
| 6424 | if err != nil { |
| 6425 | return err |
| 6426 | } |
| 6427 | if isWebsocketScheme(s.URL) != nc.ws { |
| 6428 | return ErrMixingWebsocketSchemes |
| 6429 | } |
| 6430 | |
| 6431 | newPool = append(newPool, s) |
| 6432 | newURLs[s.URL.Host] = struct{}{} |
| 6433 | } |
| 6434 | |
| 6435 | // Preserve state from existing pool entries |
| 6436 | for _, newSrv := range newPool { |
| 6437 | if idx := slices.IndexFunc(nc.srvPool, func(oldSrv *Server) bool { |
| 6438 | return oldSrv != nil && oldSrv.URL.String() == newSrv.URL.String() |
| 6439 | }); idx != -1 { |
| 6440 | newSrv.Reconnects = nc.srvPool[idx].Reconnects |
| 6441 | newSrv.didConnect = nc.srvPool[idx].didConnect |
| 6442 | newSrv.lastErr = nc.srvPool[idx].lastErr |
| 6443 | } |
| 6444 | } |
| 6445 | |
| 6446 | nc.srvPool = newPool |
| 6447 | nc.urls = newURLs |
| 6448 | |
| 6449 | // Update nc.current to point to the corresponding server in the new pool |
| 6450 | // This is important because currentServer() uses pointer equality |
| 6451 | if nc.current != nil { |
| 6452 | currentURL := nc.current.URL.String() |
| 6453 | found := false |
| 6454 | for _, s := range newPool { |
| 6455 | if s.URL.String() == currentURL { |
| 6456 | // Update nc.current to point to the server instance in the new pool |
| 6457 | nc.current = s |
| 6458 | found = true |
| 6459 | break |
| 6460 | } |
| 6461 | } |
| 6462 | if !found && len(newPool) > 0 { |
| 6463 | // Current server not in new pool - point to first server in new pool |
| 6464 | // This ensures selectNextServer() can find it and properly rotate |
| 6465 | nc.current = newPool[0] |
| 6466 | } |
| 6467 | } |
| 6468 |